Yii 1.1: pcsimpleslugbehavior

Simple behavior to create slugs and parse URLs that expect those slugs to get the unique id for model
6 followers

This is a simple behavior component.

Installation

Unpack the package and place at /protected/components

Usage

In the model where you'd want to use, declare this behavior via its behvaiors() method, as follows:

public function behaviors() {
  return array(
    'slugmaker' => array(
      'class' => 'PcSimpleSlugBehavior',
      // 'sourceIdAttr' => the 'id' attribute name in this model. Default value = 'id'
      // 'sourceStringPrepareMethod' => If defined, will be used to get the base slug string text. Use it if you need some small manipulation of data in the model object in order to 'get' the base slug string. For example, if you need to concatenate 'first_name' and 'last_name' fields together.
      // 'sourceStringAttr' => the 'main string attribute' from which the slug will be built. Typically 'title', which is the default as well.
      // 'maxChars' => Maximum allowed slug total length. resulted slug will be trimmed to this value if longer than this value (*with* the prepended 'id-'...)
      // 'avoidIdPrefixing' => Setting this to true (default = false) will enable you to generate and parse URLs without the ID of the model record. WARNING: you need to carefully think before choosing this method as if not well thought, it could be used in an environment where there could be two or more records with same slug! 
    )
  );
}

Then, in the code you can do as follows:

// the following will generat the slug for you:
$model->generateUniqueSlug()
// get id of article from slug
$dummy = MyModel::model();
$id = $dummy->getIdFromSlug($slug_fetched_from_url);
$my_model_obj = MyModel::model()->findByPk($id);

Resources

Change Log

  • v1.6 20 March 2012: Added support for 'id-less' slugs. Use with caution! (see comment above)
  • v1.5 20 March 2012: Please ignore this version.
  • v1.4 16 Aug 2012: bug fix: fixed support for 'base slug generation' (in model class).
  • v1.3 12 Aug 2012: Added attribute sourceStringPrepareMethod. See documentation above on how to use it.
  • v1.2 7 Aug 2012:
    • added createBaseSlug() which is good for creating non-primary-key related slugs. For example, if you want to slug'ify a parameter in the middle of the URL.
    • Fixed the lower-casing to handle all strings as UTF8 - mb_strtolower() on an string that contains umlaut within created a bug...
  • v1.1 17 July 2012: Added 'lowercaseUrl' option that will makes the created slug all lowercase (MB safe).

Total 10 comments

#15900 report it
Boaz at 2013/12/28 03:15am
@masdib.banget

I'm not sure I understood you fully but in any case, I think your question is more a general question about clean URLs. Please see this part of the guide for more information. I also advise to ask such questions in the relevant forum. If the question is still relevant for this extension then please rephrase and I'll do my best to answer here.

#15898 report it
masdib.banget at 2013/12/27 09:50pm
How to use extension?

I have url : http://localhost/yiiLuarpulau/master/jam-kerja note: master : module How do I refer to "jam-kerja" to go to a particular controller "jamkerja". thanks..

#15643 report it
Boaz at 2013/12/03 04:45am
@Programmer Thailand

You do not have to save the slug in the model. Why should you? Instead, consider:

  • When viewing a model, actionView() that is, see "comment_13880":http://www.yiiframework.com/extension/pcsimpleslugbehavior/#c13880 .
  • When creating a model, its likely that you'd like the user to be redirected to the page where he/she can view the model they just created. For this redirection, you need to use generateUniqueSlug(), and perform redirection to the url using that slug, as in (continuing the line given in comment 13880):
if ($model->save()) {
    $this->redirect(array("view", "slug" => $model->generateUniqueSlug()));
}
#15641 report it
Programmer Thailand at 2013/12/03 03:55am
How to use in create action?

How to use in create action? not have a primary key value how to get the primary key before save?

$model->slug = $model->generateUniqueSlug();
            if ($model->save()){
}
#13886 report it
Boaz at 2013/07/04 08:34am
@tehmaestro

Thanks for sharing.

#13881 report it
tehmaestro at 2013/07/04 03:45am
@Boaz

Thank you very much. I managed to figure out the actionView function myself. I'm trying to built a multi language website, so I did some modifications to your script. I needed for it to be able to look into relations, so:

New config parameter "relation". In the model:

public $name;
....
.....
 
'relation' => 'categoryLang',
'sourceStringAttr' => 'name',

So, in your script, I checked for the relation, which defaults to false:

$relation = false; 
....
 
if($this->relation)
    $this->slug = $this->createBaseSlug($this->owner->{$this->relation}->{$this->sourceStringAttr});
    else 
    $this->slug = $this->createBaseSlug($this->owner->{$this->sourceStringAttr});

In order to be able to generate a slug, I found that "hasAttribute" checks whether a model has the attribute column in the database .. which would have failed, because my column is in my relation table categoryLang. So I used :

if (!property_exists($this->owner, $this->sourceStringAttr)) {
                throw new CException ("requested to prepare a slug for " .
                        get_class($this->owner) .
                        " (id=" . $this->owner->getPrimaryKey() .
                        ") but this model doesn't have an attribute named " . $this->sourceStringAttr .
                        " from which I'm supposed to create the slug. Don't know how to continue. Please fix it!"
                );
            }

I know this might not be perfect but it works. I used this language behavior http://www.yiiframework.com/extension/yii-language-behavior/ , so that's why I need another table, categoryLang, which holds all my language versions of "name", and will hold all the "slug" versions.

Thank you very much, once again.

#13880 report it
Boaz at 2013/07/04 02:37am
@tehmaestro

Yes. Here's an example.

The URL rule in config/main.php:

// edu/schools/<some-nice-slug> is the cool URL. It is mapped to education 
// 'module' (education is the id of the module. the module class name can be 
// different), SchoolController controller class, and actionView method in it.
'edu/schools/<slug:.+>' => 'education/school/view',

The actionView method will look as follows (its a real but slightly altered working method):

public function actionView($slug) {
  $dummy = School::model();
  // get id of school from slug
  $id = $dummy->getIdFromSlug($slug);
  /* @var School $model */
  $model = School::model()->findByPk((int)$id);
 
  if ($model === null) {
    Yii::log("School view requested with slug = $slug but no such school found!", CLogger::LEVEL_INFO, __METHOD__);
    throw new CHttpException(404, Yii::t("EducationModule.general", 'The requested page does not exist.'));
  }
}
#13877 report it
tehmaestro at 2013/07/03 03:50pm
urlManager rule

Hey, thank you very much for the extension. However, do you have an example of a urlManager rule to make it all work and modify the displayed URL ? Thank you!

#13469 report it
Srinivasan at 2013/05/30 04:53am
How to use "getIdFromSlug"

Ya I got it from souce

$id = $dummy->getIdFromSlug($slug_fetched_from_url,**false**);
#13468 report it
Srinivasan at 2013/05/30 04:50am
How to use "getIdFromSlug"

Hi,

Very useful extension.

But I unable to get attribute "id" via "getIdFromSlug" when 'avoidIdPrefixing' => true;

Please help me...

Leave a comment

Please to leave your comment.

Create extension