Hola, primero varias cosas para comentar de tu código. Lo primero que yo haria seria aislar el patrón de caracteres para verificar si funciona. Es mejor aislar la expresión regular y colocar solo esto.
Código PHP:
preg_match("@^(/d{3})?(-)?(/d{3})?(-)?(/d{3})?$@" , $_POST["telefono"]);
Esto es simplemente para saber si esta funcionando bien o no.
En segundo no sobra leer un poco este articulo
http://www.bloogie.es/tecnologia/pro...lares-para-php
así a primera vista la arroba(@) yo jamas la he utilizado para delimitar patrones. Generalmente se usa /. En el mismo artículo se habla que el digito decimal se puede escribir como \d y no /d como lo tienes. Yo por fuerza de costumbre lo suelo usar como [0-9].
El indicador ? implica que la expresión regular debe estar al menos una vez o ninguna entonces si lo colocas así (/d{3})? indicas que los números pueden llegar a estar una vez o ninguna (lo cual no tiene mucha lógica porque los números siempre deben estar ahí).
A mi también me dan lata eso de las expresiones regulares. Lee el articulo, realiza los cambios necesarios y nos comentas como te fue con eso.
p.s. Corrijo creo que /d si esta bien colocado. Los modificadores los suelo usar poco.