Я пытаюсь расширить черту. Под этим я подразумеваю создание черты, которая переопределяет несколько методов для другой черты.
Это мой код (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 черты выдают фатальную ошибку, если вы пытаетесь определить одно и то же свойство дважды. Так как я определяю $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
}
Есть ли способ убедить PHP в том, что это действительно одно и то же и может перестать конфликтовать с самим собой, или сообщить классу, с которым я работаю (расширение Eloquent\Model
) прекратить использование HasTimestamps
в пользу моей черты?
Этот вопрос не отвечает на мой, потому что я пытаюсь использовать черту, чтобы перезаписать другую черту, а не просто добавлять методы в каждый класс, где мне нужно использовать этот код.
Мне кажется, что вам не нужно расширять черту в первую очередь. Я просто переопределил бы методы в признаке, используемом в вашем дочернем классе, а затем вызвал бы 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 :: setCreatedAtExtendHasTimestamps :: setCreatedAt
Других решений пока нет …