Foro de elhacker.net

Programación => PHP => Mensaje iniciado por: LuffyFF en 19 Junio 2015, 06:29 am



Título: Ayuda con encadenar en PHP (Method Chaining)
Publicado por: LuffyFF en 19 Junio 2015, 06:29 am
Tengo un problema que me está matando la cabeza...

Estoy intentando hacer un sistema de validación con encadenación (method chaining) en PHP para mi framework en PHP

Lo que quiero hacer es lo siguiente (revisar comentarios en PHP):

Código
  1. $nombre = $objeto->Forms->Campo("nombre")->Validar(); //Validar si "nombre" está vacío o no. Si está vacío se agrega a un array dedicado a los campos vacios. Tiene que devolver el valor del campo nombre
  2. $apellido = $objeto->Forms->Campo("apellido"); //Este no hace falta validar si está vacío o no, así que no hace falta Validar(); Este es el que me da problema. No sé como se hace para que no se necesite pasar ->Validar(); Tiene que devolver el valor de campo apellido
  3. $email = $objeto->Forms->Campo("email")->ValidarEmail(); //Lo mismo pero para validar Email();. Tiene que devolver el valor de email
  4. echo $nombre . " " . $apellido . " " . $email;

Practicamente lo que quiero hacer es esto
Código
  1. $objecto
  2. $objecto->a();
  3. $objecto->a()->b();
  4. $objecto->a()->c();


Salu2


Título: Re: Ayuda con encadenar en PHP (Method Chaining)
Publicado por: Usuario Invitado en 19 Junio 2015, 14:13 pm
En cada método, devuelve el mismo objeto modificado. Por ejemplo:

Código
  1. <?php
  2.  
  3. class User {
  4.    private $names;
  5.    private $lastnames;
  6.    private $age;
  7.  
  8.    public function __construct() {
  9.        $names = "";
  10.        $lastnames = "";
  11.        $age = 0;
  12.    }
  13.  
  14.    public function setNames($names) {
  15.        $this->names = $names;
  16.        return $this;
  17.    }
  18.  
  19.    public function setLastnames($lastnames) {
  20.        $this->lastnames = $lastnames;
  21.        return $this;
  22.    }
  23.  
  24.    public function setAge($age) {
  25.        $this->age = $age;
  26.    }
  27.  
  28. }

Ejemplo de uso:

Código
  1. $user = new User();
  2. $user->setLastnames("Johansson")->setNames("Scarlett")->setAge(32);


O en cualquier orden. La clave es devolver la referencia misma $this.


Título: Re: Ayuda con encadenar en PHP (Method Chaining)
Publicado por: LuffyFF en 19 Junio 2015, 14:28 pm
No entendiste bien o quizás no me explique bien. Eso sí se hacerlo.


Lo que quiero hacer es...
Código
  1. $objecto->a();
  2. $objecto->a()->b();
  3. $objecto->a()->c();

O sea un ejemplo
Código
  1. $nombre = $objecto->obtener("nombre"); //Sin validacion pero asignar el valor del campo nombre sobre $nombre o sea $nombre = $_POST[$campo];
  2. $nombre = $objecto->obtener("nombre")-validar(); //Lo mismo que arriba pero usando el mètodo de validar(); para validar sabiendo si está vacío o no
  3.  



Actualmente estoy usando

Código
  1. namespace Forms;
  2.  
  3. class Forms {
  4. private $temporal_var, $Validate;
  5.  
  6.  
  7. function __construct() {
  8. $this->Validate = new Forms\Validate($this);
  9. }
  10. function Field($caption, $field) {
  11. $this->temporal_var = $_POST[$field];
  12. return $this;
  13. }
  14. function Validate($type = false) {
  15. if($type=="Email") { return $this->Validate->Email(); }
  16. else if($type=="Numbers") { return $this->Validate->Numbers(); }
  17. else if($type=="AlphaNumerics") { return $this->Validate->AlphaNumerics(); }
  18. else if($type=="Password") { return $this->Validate->Password(EMPTY_PASSWORD, SHORT_PASSWORD, NUMBER_PASSWORD, LETTER_PASSWORD, CAPITAL_PASSWORD); }
  19. else { return $this->Validate->CheckIfEmpty(); }
  20. }
  21. function Get() {
  22. return $this->temporal_var;
  23. }
  24. }

Hasta ahora todo bien. Pero lo logro de esta forma
Código
  1. $form = new Forms();
  2. $nombre_validado = $form->Field("Primer nombre", "nombre")->Validate(); //Esto si funciona y valida y asigna el valor del campo a $nombre_validado
  3. $nombre_sin_validar = $form->Field("Primer nombre", "nombre")->Get(); //Esto lo use como alternativa pero mi idea no es usarlo sino que quiero que no se use ->Get();. Pero bueno, esta encadenada lo que hace es no validar nada pero si asignar el valor del campo a $nombre_sin_validar

Lo que quiero lograr es que el código quede así
Código
  1. $form = new Forms();
  2. $nombre_validado = $form->Field("Primer nombre", "nombre")->Validate(); //Esto si funciona y valida y asigna el valor del campo a $nombre_validado
  3. $nombre_sin_validar = $form->Field("Primer nombre", "nombre"); //Sin el ->Get, y que no valide y que devuelva como return el valor del cacmpo y a su vez que se peuda encadenar

Sé que se puede hacer porque lo he visto en varios Object Relational Mappings, y en varios frameworks como Laravel, CakePHP, PHPixie.

O sea, otro ejemplo serìa con Object Relatonal Mapping
Código
  1. $sql->select("table"); //Selecciona todo de la tabla "table" y devuelve los resultados del select * from table
  2. //Pero quiero que se pueda encadenar también
  3. $sql->select("table")->where("id", 1); //Selecciona donde "id" sea 1 en la tabla "table" y devolver el resultado de select * from table where id = 1


Salu2


Título: Re: Ayuda con encadenar en PHP (Method Chaining)
Publicado por: #!drvy en 21 Julio 2015, 17:28 pm
No se si se aplica exactamente a como lo quieres, y tampoco se si es lo que usa Laravel pero existe el metodo magico __toString(); (http://php.net/manual/es/language.oop5.magic.php#object.tostring)

Que se reduce básicamente a:

Código
  1. class Chaining {
  2.  
  3.    protected $string = '';
  4.  
  5.    public function a(){
  6.        $this->string .= 'a';
  7.        return $this;
  8.    }
  9.  
  10.    public function b(){
  11.        $this->string .= 'b';
  12.        return $this;
  13.    }
  14.  
  15.    public function __toString(){
  16.        return $this->string;
  17.    }
  18.  
  19. }



Código
  1. $chain = new Chaining();
  2. $a = $chain->a();
  3. echo $a;
Código
  1. a


Código
  1. $chain = new Chaining();
  2. $a = $chain->a()->b()->a();
  3. echo $a;
Código
  1. aba



Básicamente lo que hace es detectar cuando se produce una salida en vez de seguir encadenamiento y simplemente cumple lo que le digas. Espero que te sirva.

Saludos