2009-10-16 26 views
16

¿Cómo escribo una función que puede aceptar un número ilimitado de parámetros?Función de PHP con un número ilimitado de parámetros

Lo que estoy tratando de hacer es crear una función dentro de una clase que envuelve la siguiente:

$stmt->bind_param('sssd', $code, $language, $official, $percent); 
+0

no se puede hacer sin esfuerzos laboriosos. Sugeriría construir una consulta de la manera habitual, o pasar a PDO si quieres declaraciones nativas preparadas a toda costa. Tienen bindValue, te importa –

+0

Gracias por la información. Desafortunadamente PDO parece ser excesivo, con aún más esfuerzo y repetición, en comparación con simplemente escribir mis propias cosas simples. –

+0

Para cosas simples puedes usar una lib de mi información de usuario.Sin embargo es muy simple. –

Respuesta

4

Lo anterior sugiere todos son buenos, pero no creo que será adecuado para su situación.

$stmt->bind_param('sssd', $code, $language, $official, $percent); 

Si desea envolver esta función, tendrá que pasar referencias a las variables de argumentos originales para la función bind_param. No creo que func_get_args() te dé esto, sino que te da valores. Por lo tanto, no será posible utilizar estos para pasar a la función principal. Luché con un problema similar cuando intentaba extender mysqli_stmt y nunca llegué a una solución satisfactoria.

Esto no es realmente una respuesta a su pregunta Me temo, solo una advertencia de que otros argumentos pueden no funcionar en su aplicación particular de una cantidad arbitraria de argumentos.

+1

De hecho. La última vez que revisé (más de un año atrás) no había forma de ajustar/extender 'bind_param()' porque 'func_get_args()' no devolverá las referencias. –

23

¿Ha echado un vistazo a func_get_args, func_get_arg y func_num_args

Así, por ejemplo:

function foo(){ 
    if (func_num_args() > 0){ 
     var_dump(func_get_args()); 
    } 
} 

o:

function bind_param(){ 
    if (func_num_args() <= 1){ 
     return false; //not enough args 
    } 
    $format = func_get_arg(0) 
    $args = array_slice(func_get_args(), 1) 

    //etc 
} 

EDITAR
Con respecto al comentario de Todds Ewan:
que no tienen ninguna profundo conocimiento de la API se crea el envoltorio para, pero otra alternativa puede ser la de hacer algo con funciones de encadenamiento para que sus miradas interfaz resultantes algo así como:

$var->bind()->bindString($code) 
      ->bindString($language) 
      ->bindString($official) 
      ->bindDecimal($percent); 

Qué preferiría el uso de func_get_args como el código es probablemente más fácil de leer y más importante aún menos probable que cause errores debidos a la falta de una variable de formato.

+0

Uso func_get_args de vez en cuando. Sufre de hacer que sea difícil ver de un vistazo cuáles son las entradas del método. Además, introduce un bloque de sintaxis fea en tu código. Recomendaría este enfoque solo como último recurso. Prefiere la refactorización de objetos del parámetro. –

+0

Estoy de acuerdo contigo en que es una mala forma de hacer argumentos variables. He agregado una idea alternativa a mi respuesta – Yacoby

+0

Me gusta más la propuesta de "encadenar funciones" que func_get_args. Conozco este diseño como una interfaz FLUENT. Se logra teniendo bindString(), bindDecimal() etc. do "return $ this;" como su última línea. La interfaz FLUENT es una excelente opción para los tipos de fábrica cetain. –

0

Hay una función llamada func_get_args() que es una matriz de todos los argumentos pasados ​​a la función.

Ejemplo de PHP.net

function foo() 
{ 
    $numargs = func_num_args(); 
    echo "Number of arguments: $numargs<br />\n"; 
    if ($numargs >= 2) { 
     echo "Second argument is: " . func_get_arg(1) . "<br />\n"; 
    } 
    $arg_list = func_get_args(); 
    for ($i = 0; $i < $numargs; $i++) { 
     echo "Argument $i is: " . $arg_list[$i] . "<br />\n"; 
    } 
} 

foo(1, 2, 3); 

El resultado del ejemplo sería:

Número de argumentos: 3
segundo argumento es: 2
Argumento 0 es: 1
Argumento 1 es : 2
Argumento 2 es: 3

5

Uso func_get_args():

function my_func() { 
    $args = func_get_args(); 
    foreach ($args as $arg) { 
    echo "Arg: $arg\n"; 
    } 
} 
+0

Esto no funciona si los parámetros no están establecidos, y luego se pasan por referencia, para establecerse dentro de la función. func_get_args intenta acceder a la variable unset que arroja un error. – Danack

2

En 5 parámetros, este diseño está comenzando a exhibir el AntiPattern "Too Many Parameters".Esto sugiere la refactorización llamada Parameter Object, un objeto o estructura con miembros de datos que representan los argumentos que se deben pasar. Sin embargo, evite convertirlo en Magic Container.

Véase también Introduce Parameter Object refactorización en refactoring.com.

0

Las respuestas con func_get_args() funcionarán bien para parámetros que no sean de referencia. Sin embargo, hay un truco para que los parámetros pasados ​​por referencia funcionen. Además, no es técnicamente una función que acepta parámetros ilimitados, sino simplemente un número arbitrariamente grande, digamos cien.

Lo que puede hacer, es definir una función que tome una gran cantidad de argumentos, y que de manera predeterminada sean nulos. Luego, dentro de esa función, agregue cada referencia no nula a una matriz, que luego se usaría para llamar a * bind_param() * usando * call_user_func_array() *.

function my_bind_param(&$stmt, $types, &$arg1, &$arg2 = null, &$arg3 = null, ...) 
{ 
    $vars = array($types); 
    $vars[] = $arg1; 

    if ($arg2 != null) 
     $vars[] = &$arg2; 
    if ($arg3 != null) 
     $vars[] = &$arg3; 
    ... 

    if (!call_user_func_array(array($stmt, "bind_param"), $vars)) 
    { 
     if ($stmt->errno == 0) 
      return array(-1, "Unknown error binding parameters."); 
     else 
      return array(-1, "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error); 
    } 

    return array(0, ""); 
} 

El verdadero truco es que no quieres escribir esto a mano. Simplemente crea otro script que genere el cuerpo de esta función (todo entre corchetes) como * my_bind_param_body.php *. Luego, simplemente defina el encabezado de la función en su archivo principal, e incluya el cuerpo en esa definición de función. decir

function my_bind_param(&$stmt, $types, &$arg1, &$arg2 = null, &$arg3 = null, ...) 
{ 
    return include "my_bind_param_wrapper_body.php"; 
} 
8

Anteriormente se debería haber utilizado func_get_args(), pero en el php 5.6, puede utilizar ... operator.

Así, por ejemplo, puede escribir la función que devuelve una suma de todos los números, se envían a la función:

function bind_param(...$params){ 
    var_dump($params); 
} 

Su params es en realidad un conjunto de todos los elementos.

2

Si está usando PHP 5.6 o versión posterior, listas de argumentos pueden incluir el token ... para indicar que la función acepta un número variable de argumentos. Los argumentos se pasarán a la variable dada como una matriz; Simplemente usando ... puede acceder a argumentos variables ilimitados.

por ejemplo:

<?php 
function sum(...$numbers) { 
    $sum = 0; 
    foreach ($numbers as $n) { 
     $sum += $n; 
    } 
    return $sum ; 
} 

echo sum(1, 2, 3, 4, 5); 
?> 

Si está utilizando la versión de PHP < = 5,5 entonces usted puede acceder ilimitada parameterusing los func_num_args(), func_get_arg(), y func_get_args() funciones.

Por ejemplo:

<?php 
function foo() 
{ 
    $numargs = func_num_args(); 
    echo "Number of arguments: $numargs \n"; 
    if ($numargs >= 2) { 
     echo "Second argument is: " . func_get_arg(1) . "\n"; 
    } 
    $arg_list = func_get_args(); 
    for ($i = 0; $i < $numargs; $i++) { 
     echo "Argument $i is: " . $arg_list[$i] . "\n"; 
    } 
} 

foo(1, 2, 3); 
?> 
Cuestiones relacionadas