扩展一个特质与其自身发生冲突。
扩展一个特质与其自身发生冲突。
我正在尝试扩展一个特征。也就是说,创建一个重新定义另一个特征的几个方法的特征。
这是我的代码(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\Model
有use HasTimestamps
。在PHP 7之前,如果您尝试两次定义相同的属性,特征将抛出致命错误。因此,由于我通过use HasTimestamps
在HasTimestamps
和ExtendHasTimestamps
中都定义了$timestamps
,所以它会出错。
简而言之:
trait HasTimestamps { protected $timestamps = true; //有问题的属性 } trait ExtendHasTimestamps { use HasTimestamps; // 添加验证,然后调用HasTimestamps方法 } class Model { use HasTimestamps; } class MyModel extends Model { use ExtendHasTimestamps; //一切都崩溃了 }
有没有办法说服PHP它实际上是相同的东西,并且它可以停止与自身冲突,或者通知我正在使用的类(扩展自Eloquent\Model
)停止使用HasTimestamps
而改用我的特征?
这个问题的出现原因是由于在一个子类中,同时使用了两个trait,并且这两个trait中都重写了同一个方法。这导致了冲突,无法调用原始的方法。
解决方法是在子类中使用一个新的trait来覆盖原有的方法,并在其中调用父trait的方法。
以下是示例代码:
setCreatedAt(''); echo PHP_EOL; (new MyModel)->setCreatedAt('time');
输出结果为:
ExtendHasTimestamps::setCreatedAt HasTimestamps::setCreatedAt ExtendHasTimestamps::setCreatedAt
在这个例子中,我们使用了两个trait:`HasTimestamps`和`ExtendHasTimestamps`。`HasTimestamps`中定义了`setCreatedAt`方法,而`ExtendHasTimestamps`中也重写了`setCreatedAt`方法。
为了解决冲突,我们在子类`MyModel`中使用了`ExtendHasTimestamps`trait,并在其中重写了`setCreatedAt`方法。在这个方法中,我们首先调用了父trait的`setCreatedAt`方法,然后再执行自己的代码。
通过这种方式,我们成功地解决了trait冲突的问题,并能够调用原始的方法。