扩展一个特质与其自身发生冲突。

11 浏览
0 Comments

扩展一个特质与其自身发生冲突。

我正在尝试扩展一个特征。也就是说,创建一个重新定义另一个特征的几个方法的特征。

这是我的代码(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之前,如果您尝试两次定义相同的属性,特征将抛出致命错误。因此,由于我通过use HasTimestampsHasTimestampsExtendHasTimestamps中都定义了$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而改用我的特征?

0
0 Comments

这个问题的出现原因是由于在一个子类中,同时使用了两个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冲突的问题,并能够调用原始的方法。

0