español - Es posible usar mixins en php
sass vs less 2018 (5)
Llegué a saber acerca de los mixins. Entonces, mi duda es si es posible usar mixins en PHP. Si es así, ¿cómo?
Basé la funcionalidad de mixins en la entrada del blog que se encuentra en jansch.nl .
class Node
{
protected $__decorator_lookup = array();
public function __construct($classes = array())
{
foreach($classes as $class)
if (class_exists($class))
{
$decorator = new $class($this);
$methods = get_class_methods($decorator);
if (is_array($methods))
foreach($methods as $method)
$this->__decorator_lookup[strtolower($method)] = $decorator;
}
else
trigger_error("Tried to inherit non-existant class", E_USER_ERROR);
}
public function __get($name)
{
switch($name)
{
default:
if ($this->__decorator_lookup[strtolower($name)])
return $this->__call($name);
}
}
public function __call($method, $args = array())
{
if(isset($this->__decorator_lookup[strtolower($method)]))
return call_user_func_array(array($this->__decorator_lookup[strtolower($method)], $method), $args);
else
trigger_error("Call to undefined method " . get_class($this) . "::$method()", E_USER_ERROR);
}
public function __clone()
{
$temp = $this->decorators;
$this->decorators = array();
foreach($temp as $decorator)
{
$new = clone($decorator);
$new->__self = $this;
$this->decorators[] = $new;
}
}
}
class Decorator
{
public $__self;
public function __construct($__self)
{
$this->__self = $__self;
}
public function &__get($key)
{
return $this->__self->$key;
}
public function __call($method, $arguments)
{
return call_user_func_array(array($this->__self, $method), $arguments);
}
public function __set($key, $value)
{
$this->__self->$key = $value;
}
}
class Pretty extends Decorator
{
public function A()
{
echo "a";
}
public function B()
{
$this->b = "b";
}
}
$a = new Node(array("Pretty"));
$a->A(); // outputs "a"
$a->B();
echo($a->b); // outputs "b"
EDITAR:
- Como el clon de PHP es superficial, se agrega el soporte __clone.
- Además, tenga en cuenta que no se pudo configurar el trabajo NO (o al menos no he logrado que funcione) dentro de la mezcla. Entonces, hacer algo como
unset($this->__self->someValue);
no desarmará el valor enNode
. No sé por qué, como en teoría debería funcionar. Bastante gracioso sin establecerunset($this->__self->someValue); var_dump(isset($this->__self->someValue));
unset($this->__self->someValue); var_dump(isset($this->__self->someValue));
producirá correctamente el valorfalse
, sin embargo, el acceso al valor desde el alcance delNode
(comoNode->someValue
) seguirá produciendotrue
. Hay un extraño vudú ahí.
Esta respuesta está obsoleta a partir de PHP 5.4. Vea la respuesta de Jeanno para saber cómo usar los rasgos .
Realmente depende del nivel de mixins
que desee de PHP. PHP maneja clases de herencia simple y abstractas, que pueden ayudarlo a lograr la mayor parte del camino.
Por supuesto, la mejor parte de los mixins es que son fragmentos intercambiables agregados a cualquier clase que los necesite.
Para solucionar el problema de la herencia múltiple, puede usar include
para extraer fragmentos de código. Es probable que tenga que volcar un código de repetición para que funcione correctamente en algunos casos, pero sin duda ayudaría a mantener sus programas en SECO.
Ejemplo:
class Foo
{
public function bar( $baz )
{
include(''mixins/bar'');
return $result;
}
}
class Fizz
{
public function bar( $baz )
{
include(''mixins/bar'');
return $result;
}
}
No es tan directo como ser capaz de definir una clase como la class Foo mixin Bar
, pero debería llevarte la mayor parte del camino. Hay algunos inconvenientes: debe mantener los mismos nombres de parámetros y devolver los nombres de las variables, deberá pasar otros datos que se func_get_args_array
en el contexto, como func_get_args_array
o __FILE__
.
Primer resultado de Google para "php5 mixin": http://www.sitepoint.com/forums/php-application-design-147/ruby-like-mixins-php5-332491.html
Primer resultado de Google para "php mixin": http://www.advogato.org/article/470.html
Respuesta corta: sí, pero no de forma nativa (sin embargo, evidentemente, como observa @mchl). Echa un vistazo a esos.
Respuesta más larga: si estás usando runkit , runkit_method_copy()
: "Copia un método de una clase a otra".
Mixins para PHP (PHP no implementa Mixins de forma nativa, pero esta biblioteca ayudará)
Usa el Trait
introducido en PHP 5.4
<?php
class Base {
public function sayHello() {
echo ''Hello '';
}
}
trait SayWorld {
public function sayHello() {
parent::sayHello();
echo ''World!'';
}
}
class MyHelloWorld extends Base {
use SayWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
?>
que imprime Hello World!