Ayuda con encadenar en PHP (Method Chaining)

Iniciado por LuffyFF, 19 Junio 2015, 06:29 AM

0 Miembros y 1 Visitante están viendo este tema.

LuffyFF

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 (php) [Seleccionar]
$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
$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
$email = $objeto->Forms->Campo("email")->ValidarEmail(); //Lo mismo pero para validar Email();. Tiene que devolver el valor de email
echo $nombre . " " . $apellido . " " . $email;


Practicamente lo que quiero hacer es esto
Código (php) [Seleccionar]
$objecto
$objecto->a();
$objecto->a()->b();
$objecto->a()->c();



Salu2

Usuario Invitado

#1
En cada método, devuelve el mismo objeto modificado. Por ejemplo:

Código (php) [Seleccionar]

<?php

class User {
    private 
$names;
    private 
$lastnames;
    private 
$age;
    
    public function 
__construct() {
        
$names "";
        
$lastnames "";
        
$age 0;
    }
    
    public function 
setNames($names) {
        
$this->names $names;
        return 
$this;
    }
    
    public function 
setLastnames($lastnames) {
        
$this->lastnames $lastnames;
        return 
$this;
    }
    
    public function 
setAge($age) {
        
$this->age $age;
    }
    
}


Ejemplo de uso:

Código (php) [Seleccionar]
$user = new User();
$user->setLastnames("Johansson")->setNames("Scarlett")->setAge(32);



O en cualquier orden. La clave es devolver la referencia misma $this.
"La vida es muy peligrosa. No por las personas que hacen el mal, si no por las que se sientan a ver lo que pasa." Albert Einstein

LuffyFF

No entendiste bien o quizás no me explique bien. Eso sí se hacerlo.


Lo que quiero hacer es...
Código (php) [Seleccionar]
$objecto->a();
$objecto->a()->b();
$objecto->a()->c();


O sea un ejemplo
Código (php) [Seleccionar]

$nombre = $objecto->obtener("nombre"); //Sin validacion pero asignar el valor del campo nombre sobre $nombre o sea $nombre = $_POST[$campo];
$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




Actualmente estoy usando

Código (php) [Seleccionar]
namespace Forms;

class Forms {
private $temporal_var, $Validate;


function __construct() {
$this->Validate = new Forms\Validate($this);
}
function Field($caption, $field) {
$this->temporal_var = $_POST[$field];
return $this;
}
function Validate($type = false) {
if($type=="Email") { return $this->Validate->Email(); }
else if($type=="Numbers") { return $this->Validate->Numbers(); }
else if($type=="AlphaNumerics") { return $this->Validate->AlphaNumerics(); }
else if($type=="Password") { return $this->Validate->Password(EMPTY_PASSWORD, SHORT_PASSWORD, NUMBER_PASSWORD, LETTER_PASSWORD, CAPITAL_PASSWORD); }
else { return $this->Validate->CheckIfEmpty(); }
}
function Get() {
return $this->temporal_var;
}
}


Hasta ahora todo bien. Pero lo logro de esta forma
Código (php) [Seleccionar]
$form = new Forms();
$nombre_validado = $form->Field("Primer nombre", "nombre")->Validate(); //Esto si funciona y valida y asigna el valor del campo a $nombre_validado
$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 (php) [Seleccionar]
$form = new Forms();
$nombre_validado = $form->Field("Primer nombre", "nombre")->Validate(); //Esto si funciona y valida y asigna el valor del campo a $nombre_validado
$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 (php) [Seleccionar]
$sql->select("table"); //Selecciona todo de la tabla "table" y devuelve los resultados del select * from table
//Pero quiero que se pueda encadenar también
$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

#!drvy

#3
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();

Que se reduce básicamente a:

Código (php) [Seleccionar]
class Chaining {

   protected $string = '';

   public function a(){
       $this->string .= 'a';
       return $this;
   }

   public function b(){
       $this->string .= 'b';
       return $this;
   }

   public function __toString(){
       return $this->string;
   }

}





Código (php) [Seleccionar]
$chain = new Chaining();
$a = $chain->a();
echo $a;

Código (log) [Seleccionar]
a



Código (php) [Seleccionar]
$chain = new Chaining();
$a = $chain->a()->b()->a();
echo $a;

Código (log) [Seleccionar]
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