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):
$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
$objecto
$objecto->a();
$objecto->a()->b();
$objecto->a()->c();
Salu2
En cada método, devuelve el mismo objeto modificado. Por ejemplo:
<?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:
$user = new User();
$user->setLastnames("Johansson")->setNames("Scarlett")->setAge(32);
O en cualquier orden. La clave es devolver la referencia misma $this.
No entendiste bien o quizás no me explique bien. Eso sí se hacerlo.
Lo que quiero hacer es...
$objecto->a();
$objecto->a()->b();
$objecto->a()->c();
O sea un ejemplo
$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
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
$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í
$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
$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
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:
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;
}
}
$chain = new Chaining();
$a = $chain->a();
echo $a;
a
$chain = new Chaining();
$a = $chain->a()->b()->a();
echo $a;
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