扩展特质与自身冲突

时间:2017-09-12 17:30:15

标签: php traits

我正试图扩展一个特质。我的意思是创建一个特征,重新定义一些不同特征的方法。

这是我的代码(PHP 5.6和Laravel 5.4):

namespace App\Traits;

use Illuminate\Database\Eloquent\Concerns\HasTimestamps;

trait ExtendHasTimestamps
{
    use HasTimestamps {
        HasTimestamps::setCreatedAt as parentSetCreatedAt;
        HasTimestamps::setUpdatedAt as parentSetUpdatedAt;
    }

    public function setCreatedAt($value) {
        if ($value !== '') return $this;
        return $this->parentSetCreatedAt($value);
    }

    public function setUpdatedAt($value) {
        if ($value !== '') return $this;
        return $this->parentSetUpdatedAt($value);
    }
}

当我在模型中使用ExtendHasTimestamps时出现问题,它与HasTimestamps冲突,因为Eloquent\Modeluse HasTimestamps。在PHP 7之前,如果您尝试两次定义相同的属性,则traits会抛出致命错误。因此,由于我$timestampsHasTimestampsExtendHasTimestamps再次通过use HasTimestamps定义trait HasTimestamps { protected $timestamps = true; //problematic property } trait ExtendHasTimestamps { use HasTimestamps; // add validation then call HasTimestamps method } class Model { use HasTimestamps; } class MyModel extends Model { use ExtendHasTimestamps; //everything breaks } ,因此它会中断。

简而言之:

Eloquent\Model

有没有办法让PHP说服它真的是同一个东西,它可以阻止与自身发生冲突,或者通知我正在使用的类(HasTimestamps的扩展名)来停止使用{ {1}}赞成我的特质?

This question没有回答我的问题,因为我正在尝试使用特征来覆盖另一个特征,而不是仅仅向我需要使用此代码的每个类添加方法。

1 个答案:

答案 0 :(得分:1)

在我看来,你真的不需要首先扩展这个特性。我只是覆盖子类中使用的特征中的方法,然后调用特征中的parent方法。

演示:https://3v4l.org/2DqZQ

<?php

trait HasTimestamps
{
    protected $timestamps = true;

    public function setCreatedAt($value)
    {
        echo 'HasTimestamps::setCreatedAt'.PHP_EOL;
        return $this;
    }

    public function setUpdatedAt($value)
    {
        echo 'HasTimestamps::setUpdatedAt'.PHP_EOL;
        return $this;
    }
}

trait ExtendHasTimestamps
{
    public function setCreatedAt($value)
    {
        echo 'ExtendHasTimestamps::setCreatedAt'.PHP_EOL;

        if ($value !== '') return $this;

        return parent::setCreatedAt($value);
    }

    public function setUpdatedAt($value)
    {
        echo 'ExtendHasTimestamps::setUpdatedAt'.PHP_EOL;

        if ($value !== '') return $this;

        return parent::setUpdatedAt($value);
    }
}

class Model
{
    use HasTimestamps;
}

class MyModel extends Model
{
    use ExtendHasTimestamps;
}

(new MyModel)->setCreatedAt('');

echo PHP_EOL;

(new MyModel)->setCreatedAt('time');
  

ExtendHasTimestamps :: setCreatedAt
  HasTimestamps :: setCreatedAt

     

ExtendHasTimestamps :: setCreatedAt