'afterUpdate', ActiveRecord::EVENT_AFTER_INSERT => 'afterInsert', ]; } public function afterInsert() { $this->addSlug(); } public function afterUpdate() { if (!$this->owner->{$this->slugAttribute}) { $this->addSlug(); } } private function addSlug() { /** @var ActiveRecord $owner */ $owner = $this->owner; if (!$this->isNewSlugNeeded()) { $slug = $owner->{$this->slugAttribute}; } else { if ($this->relation) { $attribute = $owner->{$this->relation}->{$this->attribute}; $slug = $this->generateSlug($attribute); $slug = $this->makeUnique($slug); } else { $attribute = $owner->{$this->attribute}; $slug = $this->generateSlug($attribute); $slug = $this->makeUnique($slug); } } $owner->{$this->slugAttribute} = $slug; $owner->save(); } protected function generateSlug($attribute) { return Inflector::slug($attribute); } protected function isNewSlugNeeded() { if (empty($this->owner->{$this->slugAttribute})) { return true; } if (!empty($this->owner->{$this->slugAttribute}) && !$this->slugIfEmpty) { return true; } return false; } protected function makeUnique($slug) { $uniqueSlug = $slug; $iteration = 0; while (!$this->validateSlug($uniqueSlug)) { $iteration++; $uniqueSlug = $this->generateUniqueSlug($slug, $iteration); } return $uniqueSlug; } protected function generateUniqueSlug($baseSlug, $iteration) { return $baseSlug . '-' . ($iteration + 1); } protected function validateSlug($slug) { /* @var $validator UniqueValidator */ /* @var $model ActiveRecord */ $validator = Yii::createObject(array_merge( [ 'class' => UniqueValidator::class, ] )); $model = clone $this->owner; $model->clearErrors(); $model->{$this->slugAttribute} = $slug; $validator->validateAttribute($model, $this->slugAttribute); return !$model->hasErrors(); } }