扩展特征与自身冲突
Extending a trait conflicts with itself
我正在尝试扩展特征。我的意思是创建一个特征,为不同的特征重新定义几个方法。
这是我的代码(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 会抛出致命错误。因此,由于我在 HasTimestamps
中定义了 $timestamps
,并且借助 use HasTimestamps
通过 ExtendHasTimestamps
再次定义了 $timestamps
,因此它中断了。
简而言之:
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
}
有没有办法让 PHP 相信它确实是同一件事并且它可以停止与自己发生冲突,或者通知 class 我正在使用(的扩展Eloquent\Model
) 停止使用 HasTimestamps
来支持我的特质?
This question 没有回答我的,因为我正在尝试使用一个特征来覆盖另一个特征,而不是仅仅向每个 class 我需要使用它的地方添加方法代码.
在我看来,您实际上并不需要首先扩展特征。我会简单地重写 child class 中使用的特征中的方法,然后调用特征中的 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::setCreatedAt
ExtendHasTimestamps::setCreatedAt
我正在尝试扩展特征。我的意思是创建一个特征,为不同的特征重新定义几个方法。
这是我的代码(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 会抛出致命错误。因此,由于我在 HasTimestamps
中定义了 $timestamps
,并且借助 use HasTimestamps
通过 ExtendHasTimestamps
再次定义了 $timestamps
,因此它中断了。
简而言之:
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
}
有没有办法让 PHP 相信它确实是同一件事并且它可以停止与自己发生冲突,或者通知 class 我正在使用(的扩展Eloquent\Model
) 停止使用 HasTimestamps
来支持我的特质?
This question 没有回答我的,因为我正在尝试使用一个特征来覆盖另一个特征,而不是仅仅向每个 class 我需要使用它的地方添加方法代码.
在我看来,您实际上并不需要首先扩展特征。我会简单地重写 child class 中使用的特征中的方法,然后调用特征中的 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