Laravel源码中为何有大量依赖于class的trait

最近在阅读 laravel 源码,发现有不少 trait 引用了下级 class 的方法和属性,我觉得这种设计是有问题的,trait 如果依赖于 class 的方法,如何保证其复用性,例如:8.* 版本中的 Illuminate\Http\Concerns\InteractsWithInput:

namespace Illuminate\Http\Concerns;

trait InteractsWithInput
{
    public function input($key = null, $default = null)
    {
        return data_get(
        //getInputSource方法在当前trait中不存在
        $this->getInputSource()->all() + $this->query->all(), $key, $default);
    }
}
namespace Illuminate\Http;
class Request extends SymfonyRequest implements Arrayable, ArrayAccess
{
    use Concerns\InteractsWithContentTypes,
    Concerns\InteractsWithFlashData,
    Concerns\InteractsWithInput,
    Macroable;
    //getInputSource定义在这里
    protected function getInputSource()
    {
        if ($this->isJson()) {
        return $this->json();
    }
    return in_array($this->getRealMethod(), ['GET', 'HEAD']) ? $this->query : $this->request;
    }
}

这样的问题在源码里能看到几处,很不理解,不知道这么设计是什么原因

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
最佳答案

我觉得 Trait 有的时候不是保证代码的复用,像这里很明显是在分割逻辑,让代码更加清楚。

很多时候一些代码无法复用,抽象出 interface 会觉得完全没有必要,但是写在同一类里面,会让代码非常臃肿。这种情况用这种方式去切割逻辑,让代码干净清楚一点,我觉得是可行。

前提条件就是 无法复用,一旦想要复用,这种 Trait 会增加调用者的心智包袱,最后得不偿失。

3年前 评论
phinche (楼主) 3年前
讨论数量: 3

我觉得 Trait 有的时候不是保证代码的复用,像这里很明显是在分割逻辑,让代码更加清楚。

很多时候一些代码无法复用,抽象出 interface 会觉得完全没有必要,但是写在同一类里面,会让代码非常臃肿。这种情况用这种方式去切割逻辑,让代码干净清楚一点,我觉得是可行。

前提条件就是 无法复用,一旦想要复用,这种 Trait 会增加调用者的心智包袱,最后得不偿失。

3年前 评论
phinche (楼主) 3年前

我觉得也是为了拆分逻辑,

可以看下 Illuminate\Database\Eloquent\Model 引用的这些 Trait

这些 Trait 其他地方都不会用到,

他们不仅会调用 Model 里的属性和方法,有些地方还会相互调用其他 Trait 里的属性和方法。

abstract class Model implements ...
{
    use Concerns\HasAttributes,
        Concerns\HasEvents,
        Concerns\HasGlobalScopes,
        Concerns\HasRelationships,
        Concerns\HasTimestamps,
        Concerns\HidesAttributes,
        Concerns\GuardsAttributes,
        ForwardsCalls;
    ...
3年前 评论