php中可以使用mixin吗

发布于 2024-11-26 19:01:21 字数 54 浏览 0 评论 0原文

我开始了解mixins。所以我的疑问是,是否可以在php中使用mixins?如果是,那么如何?

I came to know about mixins.So my doubt is, is it possible to use mixins in php?If yes then how?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

寻找一个思念的角度 2024-12-03 19:01:21

使用 PHP 5.4 中引入的 Trait

<?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();
?>

打印 Hello World!

http://php.net/manual/en/language.oop5.traits.php

Use Trait introduced in 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();
?>

which prints Hello World!

http://php.net/manual/en/language.oop5.traits.php

三寸金莲 2024-12-03 19:01:21

从 PHP 5.4 开始,这个答案已过时。 请参阅 Jeanno 的回答,了解如何使用特征


这实际上取决于您想要从 PHP 获得什么级别的 mixins。 PHP 处理单继承和抽象类,这可以帮助您大部分工作。

当然,mixin 最好的部分是它们是可互换的片段,添加到任何需要它们的类中。

要解决多重继承问题,您可以使用 include 来引入代码片段。在某些情况下,您可能需要转储一些样​​板代码才能使其正常工作,但这肯定有助于保持程序干燥。

示例:

class Foo
{
  public function bar( $baz )
  {
    include('mixins/bar');
    return $result;
  }
}

class Fizz
{
  public function bar( $baz )
  {
    include('mixins/bar');
    return $result;
  }
}

它不像将类定义为 class Foo mixin Bar 那样直接,但它应该可以帮助您完成大部分工作。有一些缺点:您需要保留相同的参数名称和返回变量名称,您需要传递依赖于上下文的其他数据,例如 func_get_args_array__FILE__

This answer is obsolete as of PHP 5.4. See Jeanno's answer for how to use traits.


It really depends on what level of mixins you want from PHP. PHP handles single-inheritance, and abstract classes, which can get you most of the way.

Of course the best part of mixins is that they're interchangeable snippets added to whatever class needs them.

To get around the multiple inheritance issue, you could use include to pull in snippets of code. You'll likely have to dump in some boilerplate code to get it to work properly in some cases, but it would certainly help towards keeping your programs DRY.

Example:

class Foo
{
  public function bar( $baz )
  {
    include('mixins/bar');
    return $result;
  }
}

class Fizz
{
  public function bar( $baz )
  {
    include('mixins/bar');
    return $result;
  }
}

It's not as direct as being able to define a class as class Foo mixin Bar, but it should get you most of the way there. There are some drawbacks: you need to keep the same parameter names and return variable names, you'll need to pass other data that relies on context such as func_get_args_array or __FILE__.

心奴独伤 2024-12-03 19:01:21

PHP 的 Mixins (PHP 本身并不实现 Mixins,但这个库会有所帮助)

Mixins for PHP (PHP does not implement Mixins natively, but this library will help)

写下不归期 2024-12-03 19:01:21

“php5 mixin”的第一个谷歌结果: http://www.sitepoint.com/forums/php-application-design-147/ruby-like-mixins-php5-332491.html

第一个谷歌结果“php mixin”:http://www.advogato.org/article/470.html

简短回答:是的,但不是原生的(显然,正如 @mchl 所指出的那样)。检查一下。

更长的答案:如果您使用 runkit,请查看 runkit_method_copy(): "复制一个方法从一个班级到另一个班级。”

First google result for "php5 mixin": http://www.sitepoint.com/forums/php-application-design-147/ruby-like-mixins-php5-332491.html

First google result for "php mixin": http://www.advogato.org/article/470.html

Short answer: yes, but not natively (yet, evidently, as @mchl notes). Check those out.

Longer answer: if you're using runkit, checkout runkit_method_copy(): "Copies a method from class to another."

原来是傀儡 2024-12-03 19:01:21

我基于 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"

编辑:

  1. 由于 PHP 克隆很浅,添加了 __clone 支持。
  2. 另外,请记住,在 mixin 中 unset 不起作用(或者至少我没有设法使其起作用)。因此,像 unset($this->__self->someValue); 这样的操作不会取消 Node 上的值。不知道为什么,理论上它应该有效。很有趣 unset($this->__self->someValue); var_dump(isset($this->__self->someValue)); 将正确生成 false,但是从 Node 范围访问该值(如 < code>Node->someValue) 仍会产生 true。那里有一些奇怪的巫毒。

I based mixins functionality on the blog entry found at 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"

EDIT:

  1. As PHP clone is shallow, added __clone support.
  2. Also, bear in mind that unset WON'T work (or at least I've not managed to make it work) within the mixin. So - doing something like unset($this->__self->someValue); won't unset the value on Node. Don't know why, as in theory it should work. Funny enough unset($this->__self->someValue); var_dump(isset($this->__self->someValue)); will produce correctly false, however accessing the value from Node scope (as Node->someValue) will still produce true. There's some strange voodoo there.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文