Вы должны использовать загрузчики / инициализаторы Eloquent.
trait Hasher
{
protected $hasher;
protected function initializeHasher()
{
$salt = $this->hashSalt ?? null;
$length = $this->hashLength ?? null;
$chars = $this->hashChars ?? null;
$this->hasher = new Hashids($salt, $length, $chars);
}
}
Реализуя метод в вашей характеристике с именем initialize{traitName}
, Laravel автоматически вызовет его в конструкторе. То же самое происходит, если вы реализуете метод stati c с именем boot{traitName}
, он будет вызываться при первом использовании вашей модели. Вот полное объяснение
Illuminate\Database\Eloquent\Model::__construct
/**
* Create a new Eloquent model instance.
*
* @param array $attributes
* @return void
*/
public function __construct(array $attributes = [])
{
$this->bootIfNotBooted();
$this->initializeTraits();
$this->syncOriginal();
$this->fill($attributes);
}
Здесь важны две вещи: вызов bootIfNotBooted
косвенно запускает этот метод
/**
* Boot all of the bootable traits on the model.
*
* @return void
*/
protected static function bootTraits()
{
$class = static::class;
$booted = [];
static::$traitInitializers[$class] = [];
foreach (class_uses_recursive($class) as $trait) {
$method = 'boot'.class_basename($trait);
if (method_exists($class, $method) && ! in_array($method, $booted)) {
forward_static_call([$class, $method]);
$booted[] = $method;
}
if (method_exists($class, $method = 'initialize'.class_basename($trait))) {
static::$traitInitializers[$class][] = $method;
static::$traitInitializers[$class] = array_unique(
static::$traitInitializers[$class]
);
}
}
}
Вы можете заметить здесь logi c, как я объяснил ранее, вызываются загрузчики и регистрируются инициализаторы (но еще не вызываются). Затем конструктор вызывает это
/**
* Initialize any initializable traits on the model.
*
* @return void
*/
protected function initializeTraits()
{
foreach (static::$traitInitializers[static::class] as $method) {
$this->{$method}();
}
}
И таким образом вызывается каждый ранее зарегистрированный инициализатор.