我正试图扩展一个特质。我的意思是创建一个特征,重新定义一些不同特征的方法。
这是我的代码(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之前,如果您尝试两次定义相同的属性,则traits会抛出致命错误。因此,由于我$timestamps
在HasTimestamps
和ExtendHasTimestamps
再次通过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没有回答我的问题,因为我正在尝试使用特征来覆盖另一个特征,而不是仅仅向我需要使用此代码的每个类添加方法。
答案 0 :(得分:1)
在我看来,你真的不需要首先扩展这个特性。我只是覆盖子类中使用的特征中的方法,然后调用特征中的parent
方法。
<?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 :: setCreatedAtExtendHasTimestamps :: setCreatedAt