1

我被卡住了,因为 Php 本身不允许扩展多个类,我正在使用 laravel 模型与数据交互,并希望使用 2 个不同的包来扩展它的功能。

我正在尝试使用Ardent验证器和Revisionable来维护更新历史记录,但我不确定如何在我的模型中扩展这两个类。

任何帮助将不胜感激。

4

3 回答 3

1

As you know, PHP doesn't support multiple inheritance and unfortunately, this is a PHP deficiency and a problem created by ardent and revisionable package developers. Take Sentry as an example, you can use whatever implementation of Eloquent you want, you just have set the one you need in config.php. Laravel unfortunately has its hands tied, since it is the base class of all those packages. In my opinion.

So you have some options:

1) File an issue on both packages git repositories and hope that one of them changes to support inheritance not only from \Eloquent, but any of the user's classes, extending Eloquent Model abstract class.

You can even change the code of one of those packages and send a pull request to the repository. If it's a good change you probably will see it happening.

2) Use the repository pattern, by creating a class extended from Eloquent, having both of your packages as dependency and, inside it, calling whatever you need from those packages. This will not be a piece of cake, because Eloquent is a complex class and, if you use __call(), you'll have to map all methods you need to forward to your packages, so you don't risk breaking Eloquent's own dynamic calls:

use Ardent;
use Revisionable;

class User extends Eloquent {

    private $ardent;

    privave $revisionable;

    public function __construct(Ardent $ardent, Revisionable $revisionable)
    {
        $this->ardent = $ardent;

        $this->revisionable = $revisionable;
    }

    public function doWhatever() 
    {
        return $this->ardent->do();
    }

    public function __call($name, $arguments)
    {
        if($this->isArdentMethod($name))
        {
            return call_user_func_array(array($this->ardent,$name), $arguments);
        }
        else
        if($this->isRevisionableMethod($name))
        {
            return call_user_func_array(array($this->revisionable,$name), $arguments);
        }
        else
        {
            return parent::__call($name, $arguments);
        }
    }
}

Note that this call

return parent::__call($name, $arguments);

Ensures that all of your calls will be redirected to your Eloquent class, if they are not meant to be executed by one of the others.

As a matter of fact you could even choose one of those, like Ardent as your main class:

class User extends Ardent {}

And just have revisionable as a dependency:

public function __construct(Revisionable $revisionable)

And then forward just revisionable calls to the injected dependency. Because, in the end, those classes are all Eloquent and you can have many Eloquent models pointing to the same tables.

If you look at Revisionable source code you'll that the only call you really have to think of is save(), because it overrides it from Eloquent, all the other you can just call Ardent's.

I know it sounds like a bit too much, but it's doable.

于 2014-02-22T16:55:11.537 回答
1

最近,我一直在努力使 Revisionable 成为一个特征。

因此,您将能够做到use这一点,如下所示:

class User extends Ardent {
    use \Venturecraft\Revisionable\RevisionableTrait;
}

它目前在 dev 分支中,但在将其合并到 master 之前,我希望得到一些帮助来测试它:

https://github.com/VentureCraft/revisionable/issues/36

[编辑]这现在在主分支中,可供公众使用。

于 2014-02-25T05:54:20.723 回答
0

正如您所说,PHP 不支持多重继承,因此您没有太多选择。尽管它很丑,但你可能不得不求助于这样的东西它使用了__call()魔法方法。

于 2014-02-22T16:37:54.120 回答