Yii2 URLs with published year, month, and slug -


i creating blog using yii2 have post urls year, month, , slug of post. have slug working validate against not sure how tell sluggable behavior take year , month consideration when generating unique slugs.

in post table have slug (based on post title) , published_at datetime. have following setup retrieves given post based on year, month, , slug.

the urlmanager has '/<year:\d{4}>/<month:\d{2}>/<slug>' => 'post/view', , in controller following:

public function actionview($year, $month, $slug) {     $model = $this->findmodel($year, $month, $slug);      return $this->render('view', [         'model' => $model,     ]); } ... protected function findmodel($year, $month, $slug) {     $model = post::find()         ->where(['slug' => $slug])         ->andwhere(['from_unixtime(publish_at, "%m")' => $month])         ->andwhere(['from_unixtime(publish_at, "%y")' => $year])         ->one();     if ($model !== null) {         return $model;     } else {         throw new notfoundhttpexception('the requested post not exist.');     } } 

currently, post model defines following behavior.

'sluggablebehavior' => [     'class' => sluggablebehavior::classname(),     'attribute' => 'title',     'immutable' => true,     'ensureunique' => true, ], 

how can edit behavior in evaluates year, month, , slug when determining uniqueness?

do perhaps needs store year , month in database rather dynamically pulling them out of published_at datetime (which doing during find())?

short answer

i created columns year , month publish_at field not need evaluated on fly. year , month stored in own column, uniquevalidator property set on sluggablebehavior follows

'uniquevalidator' => ['targetattribute' => ['publish_year', 'publish_month', 'slug']], 

with targetattribute set uniquevalidator, behavior take 3 fields consideration when determining if slug unique.

long answer

in case else wants implement similar, here various pieces went making solution work.

post.php (model)

this ensures when slug generated, uses publish_year , publish_month fields evaluate whether or not slug unique

public function behaviors() {     return [         'sluggablebehavior' => [             'class' => sluggablebehavior::classname(),             'attribute' => ['title'],             'immutable' => true,             'ensureunique' => true,             'uniquevalidator' => ['targetattribute' => ['publish_year', 'publish_month', 'slug']],         ],     ]; } 

the following rule ensure if user manually enters slug, still evaluated against year , month uniqueness

public function rules() {     return [         ....         [['slug'], 'unique', 'targetattribute' => ['publish_year', 'publish_month', 'slug'],     ]; } 

i allow users enter date publishing , populate year , month based on enter. important piece note here parent implementation of beforevalidate needs after setting these values set when sluggablebehavior executes. if user did not set publish_at datetime, current time used (the user can change later need make kind of assumption date have year , month check against).

public function beforevalidate() {     $publish_at = ($this->publish_at) ? $this->publish_at : time();     $this->publish_year = date('y', $publish_at);     $this->publish_month = date('m', $publish_at);      // invoke parent implementation     parent::beforevalidate();      return true; } 

web.php (config)

the urlmanager needs following rule direct posts correction controller/action

'/<year:\d{4}>/<month:\d{2}>/<slug>' => 'post/view', 

postcontroller.php (controller)

finally, controller needs know data find proper post

public function actionview($year, $month, $slug) {     $model = $this->findmodel($year, $month, $slug);      return $this->render('view', [         'model' => $model,     ]); } 

this not every last line of code needed make function (for example, findmodel needs find proper post year, month, , slug rather id usual) should @ least pointed in right direction when trying accomplish similar.


Comments

Popular posts from this blog

javascript - How to get current YouTube IDs via iMacros? -

c# - Maintaining a program folder in program files out of date? -

emulation - Android map show my location didn't work -