En PHP 5 (y sup) contamos con un método llamado __call(…) que se invoca justo cuando PHP se da cuenta que llamamos un método de clase que NO EXISTE o NO ESTÁ DEFINIDO. Gracias a esto, podemos emular sobrecarga de métodos, con lo cual el código es mucho más claro y auto-documentado.
Para aquellos que no sepan que es sobrecarga de métodos, en lenguajes fuertemente tipados, como Java, o C++ podemos tener un método que haga distintas cosas segun el TIPO o CANTIDAD de parémetros que le pasemos.
ejemplo en PHP podriamos tener :
$o = new testClass();
$p = new Class2();
var_dump($o->getAll());
var_dump($o->getAll($p));
var_dump($o->getAll($p, 'Hola'));
Como vemos el metodo getAll(…) está invocado 3 veces con distintos tipos y cantidades de paramnetros. Entonces decimos que esta sobrecargado
El concepto es devolverTodos pero con distintos condicionamientos o de distintas maneras.
Para emular esto podriamos definir la clase testClass de la siguiente manera:
class TestClass extends Model {
/** se ejecuta justo cuando no exite el metodo de clase */
private function __call($method_name, $arguments) {
//la lista de metodos sobrecargados
$accepted_methods = array("getAll", "test");
if(!in_array($method_name, $accepted_methods)) {
trigger_error("Metodo $method_name no existe", E_USER_ERROR);
}
//metodo sin argumentos
if(count($arguments) == 0) {
$this->$method_name();
//metodo con 1 argumento
} elseif(count($arguments) == 1) {
$this->${$method_name.'1'}($arguments[0]);
//metodo con 2 argumentos
} elseif(count($arguments) == 2) {
$this->${$method_name.'2'}($arguments[0], $arguments[1]);
//error +de 2 parametros, metodo no definido
} else {
return false;
}
}
function getAll(){
/** algoritmo sin parametros **/
}
function getAll1($p1){
/** algoritmo con 1 parametro **/
}
function getAll2($p1, $p2){
/** algoritmo con 2 parametro **/
}
function test(){
/** algoritmo sin parametros **/
}
function test1($p1){
/** algoritmo con 1 parametro **/
}
function test2($p1,$p2){
/** algoritmo con 2 parametro **/
}
/* ........ mas definiciones */
}
Como ves, en la clase nunca puedo poner dos funciones con el mismo nombre, pero la funcion __class despacha al método correcto segun la cantidad de parametros recibidos.
No es lo mas top , pero es lo que hay por ahora ….
Hola hermano, no se si ya haya salido otra mejor manera de hacer sobrecarga, algo que no sea emulado y más natural como se hace en java por ejemplo. Bueno en todo caso tu código, tal cual está no funciona. Ya lo hice funcionar checa el código comentado:
<?php
class TestClass{
/** se ejecuta justo cuando no exite el metodo de clase */
function __call($method_name, $arguments) {
//la lista de metodos sobrecargados
$accepted_methods = array("getAll", "test");
if(!in_array($method_name, $accepted_methods)) {
trigger_error("Metodo $method_name no existe», E_USER_ERROR);
}
if(count($arguments)==0){
/*$this->$method_name();*/ /*No se por que, pero si lo dejas así y declaras getAll()
y test() por más que llames las funciones con parametros
siempre entrará a la función sin parametros, eso me pasó a mí*/
$this->{$method_name.’0′}();//Concatené un 0, declare getAll0() y test0() y santo remedio
}else if(count($arguments)==1){
$this->{$method_name.’1′}($arguments[0]);/*Los $ antes de los {$metod_name están de más,
Los tuve que quitar para que funcionara*/
}else if(count($arguments)==2){
$this->{$method_name.’2′}($arguments[0], $arguments[1]);
}else{
return false;
}
}
//Imprimí contenido en todas las funciones para probar que funcionara
function getAll0(){//Como mencione lo nombré como getAll0() y no como getAll()
echo» metodo getAll() sin parámetros»;
}
function getAll1($p1){
echo» metodo getAll() con 1 parámetro»;
}
function getAll2($p1, $p2){
echo» metodo getAll() con 2 parámetros»;
}
function test0(){//Como mencione lo nombré como test0() y no como test()
echo» metodo test() sin parámetros»;
}
function test1($p1){
echo» metodo test() con 1 parámetro»;
}
function test2($p1,$p2){
echo» metodo test() con 2 parámetros»;
}
}
$sc = new TestClass();
$sc->getAll();
$sc->getAll(1);
$sc->getAll(1,2);
$sc->test();
$sc->test(1);
$sc->test(1,2);
?>
No se si sea más óptimo o no pero yo por mi cuenta lo modifiqué el function __call() y creí que era mejor usar switch en vez de if else if … Y me quedó así:
function __call($method_name, $arguments) {
//la lista de metodos sobrecargados
$accepted_methods = array(«getAll», «test»);
if(!in_array($method_name, $accepted_methods)) {
trigger_error(«Metodo $method_name no existe», E_USER_ERROR);
}
else switch($counter = count($arguments)){
case 0:
$this->{$method_name.$counter}();
break;
case 1:
$this->{$method_name.$counter}($arguments[0]);
break;
case 2:
$this->{$method_name.$counter}($arguments[0], $arguments[1]);
break;
default:
return false;
}
}
Si, lo sustituyes en el otro código debe funcionar. Tengo las dos versiones funcionando, tengo los archivos .php, por si los quieres te los mando. Aunque creo que con un simple copy – paste, será más que suficiente.
Hay algo más que quisera comentar, ya después de corregirlo, me di cuenta que en las funciones que se utiliza el return, no devuelve el valor, entra correctamente, comprobé que los valores llegan como deberían llegar y se pueden hacer operaciones con ellos, pero no se por qué razón no devuelve el valor, si guardas el retorno en una variable, es como si no hubieses guardado nada. Si gustas te puedo pasar un ejemplo de eso.
Excelente mejora. Gracias.
Lo voy a chequear, pero no deberia ser asi. EL metodo __call simplemente se INVOCA cuando el metodo al que llamas (normalmente) no existe, entonces este metodo se las arregla para saber que quieres hacer, y simplemente lo deribas.-
No olvides dentro del metodo __call poner un return tambien!!!!!!
Aquí es donde te das cuenta que php es una basura…
Subjetivo comentario. Ya que lenguajes como JAVA , C++ , PARA WEB son lenguajes que requieren de mas tiempo, y los costos no lo pagan, con PHP puedes desarrollar applicaciones de embergadura (FACEBOOK) a tiempos reducidos y costos menores. Lo cual supera ppor lejos la eleccion del lenguaje a estos primeros.
Hola, aunque es un tema antiguo quisiera participar con otra alternativa.
Tal y como está planteado el problema se pueden utilizar argumentos alternativos (http://php.net/manual/es/functions.arguments.php) para simular una sobre carga de la función o métodos.
Buen aporte, gracias!!