Yii 1.1: relation

Relation Widget
26 followers

The Relation widget is used in forms, where the User can choose between a selection of related elements.

It automatically renders a Selectbox or Listbox. Every Type of Relation is supported (even MANY_MANY since 0.8).

Resources

Documentation

The Relation widget is used in forms, where the User can choose between a selection of model elements, that this models belongs to.

Since version 0.8 it is able to handle BELONGS_TO, HAS_ONE and MANY_MANY Relations. The Relation type is detected automatically from the Model 'relations()' section.

The following example shows how to use Relation with a minimal config, assuming we have a Model "Post" and "User", where one User belongs to a Post:

$this->widget('application.components.Relation', array(
   'model' => 'Post',
   'relation' => 'user'
   'fields' => 'username' // show the field "username" of the parent element
  ));

Results in a selectbox in which the user can choose between all available Users in the Database. The shown field of the Table "User" is "username" in this example.

You can choose the Style of your Widget in the 'style' option. Note that a Many_Many Relation always gets rendered as a Listbox, since you can select multiple Elements.

'fields' can be an array or an string. If you pass an array to 'fields', the Widget will display every field in this array. If you want to show further sub-relations, separate the values with '.', for example: 'fields' => 'array('parent.grandparent.description')

Optional Parameters:

You can use 'field' => 'post_userid' if the field in the model that represents the foreign model is called different than in the relation

Use 'foreignField' => 'id_of_user' if the primary Key of the Foreign Model differs from the one given in the relation.

Normally you shouldn´t use this fields cause the Widget get the relations automatically from the relation.

Use 'allowEmpty' to let the user be able to choose no parent. The string assigned to 'emptyString' will be displayed.

With 'hideAddButton' => 'true' you can hide the 'create new Foreignkey' Button generated beside the Selectbox.

Define the AddButtonString with 'addButtonString' => 'Add...'. This string is set default to '+'

When using the '+' button you most likely want to return to where you came. To accomplish this, we pass a 'returnTo' parameter by $_GET. The Controller can send the user back to where he came from this way:

if($model->save())
    if(isset($_GET['returnTo'])) 
      $this->redirect(array(urldecode($_GET['returnTo'])));

Using the 'style' option we can configure if we want our widget to be rendered as a 'Selectbox' (default) or a 'ListBox'.

Use the option 'createAction' if the action to add additional foreign Model options differs from 'create'.

With 'parentObjects' you can limit the Parent Elements that are being shown. It takes an array of elements that could be returned from an scope or an SQL Query.

The parentObjects can be grouped, for example, with 'groupParentBy' => 'city'

Use the option 'htmlOptions' to pass any html Options to the Selectbox/Listbox form element.

hint: ManyMany Records can easily be saved by using the CAdvancedArBehavior Behavior.

Full Example:

$this->widget('application.components.Relation', array(
   'model' => 'Post',
   'field' => 'Userid',
   'style' => 'ListBox',
   'parentObjects' => Parentmodel::model()->findAll('userid = 17'),
   'groupParentsBy' => 'city',
   'relation' => 'user',
   'foreignField' => 'id_of_user',
   'fields' => array( 'username', 'username.group.groupid' ),
  'delimiter' => ' -> ', // default: ' | '
   'returnTo' => 'model/create',
   'createAction' => 'add', // default: 'create'
   'addButtonString' => 'click here to add a new User', // default: ''
   'htmlOptions' => array('style' => 'width: 100px;')
  ));

Change Log

February, 21, 2010

  • Version 0.9
  • Better Name generation for MANY_MANY Field

February, 21, 2010

  • Version 0.8
  • Fixed Bug: get_class($this->foreignModel) instead of tableschema->className
  • Added support for MANY_MANY Relations which gets rendered in a multiple-selectable ListBox

February, 07, 2010

  • Version 0.7
  • added parentGroupBy and parentObjects

February, 02, 2010

  • Version 0.6
  • minor bugfix (get_class instead tableSchema->name)
  • added allowEmpty
  • added emptyString

January 25, 2010

  • Uploaded Version 0.4
  • added getModelData() function for translating . to ->

January 25, 2010

  • Uploaded Version 0.3.
  • Bugfixes
  • htmlOptions
  • 'fields' (array or string)
  • 'style' (Listbox or Selectbox)
  • further Enhancements

January 21, 2010

  • Uploaded Version 0.2.
  • Bugfixes and now support 'returnTo' link (see Documentation)

January 19, 2010

  • Initial release.

Total 9 comments

#14686 report it
xNicox at 2013/09/03 12:40pm
MANY to MANY question

Hi, I'm testing this widget, And I found that the list box doesn't show all the values spected. I have the typical many-to-many relation, from table_a, Table_b, Table_rel_ab. I'm updating or creating a record in table_a, and the listo box of the relation is empty. If I add a record on table_reb_ab, I start seeing data.

Any suggest? Best regards

#12841 report it
Igoru-san at 2013/04/15 12:09pm
Outdated doc about foreignKey

It's now called relatedPk but the author did not update the page, only the code.

#9168 report it
Tpoxa at 2012/07/25 04:37pm
Listbox selected issue

Thanks for this extension but it may help someone

School Model

'owners' => array(self::MANY_MANY, 'User', 'tbl_users_schools(school_id,user_id)')

So listbox will not set already assigned object as selected until I add space between fields in many to many table definition

So it works right this way

'owners' => array(self::MANY_MANY, 'User', 'tbl_users_schools(school_id, user_id)')

#4532 report it
qsrtlwe at 2011/07/17 04:49pm
PK name problem.

Hi! You have a little bug at line 303 It takes “id” as model's PK

if(!$this->_model->$id)
            return array();

and this code fails if schema has different PK name. I made a little fix:

$id = $this->_model->tableSchema->primaryKey;
        if(!$this->_model->$id)
            return array();

Now it works.

#74 report it
thyseus at 2010/09/22 10:20am
relation still active

it is interesting that people still find and use the relation widget.

there is a much-newer version available here:

http://code.google.com/p/gii-template-collection/source/browse/trunk/gtc/components/Relation.php

maybe i find the time and package this some time

#75 report it
thomas.mery at 2010/09/22 09:44am
Using with Many Many and tables with PK other than 'id'

Hi,

thank for the great widget

I have encountered a problem with a relation to a Model which table has a PK which is not 'id'.

I have changed line 405 :

$objects[$relobj->id] = $relobj;

to

$objects[$relobj->{$relobj->getMetadata()->tableSchema->primaryKey}] = $relobj;

It seems to do the trick, would the author comment on this ?

Thanks

#166 report it
balrok at 2010/08/21 10:40am
great extension

would be nice to see the documentation of this updated - i only found the bug mentioned by #1383 after some own research (: but the code is very clear and so that was ok

another bug: the "add new" button assumes the controller sounds the same as the relation-table.. would be nice to have this configurable

@#1545 if you want your selected data displayed then set 'model'=>$model this feature isn't documented (:

and here my code which i use to save my many_many relation.. perhaps this can be done easier <code<?php //before save(): if(isset($_POST['Entrytype'])) { $model->attributes=$_POST['Entrytype']; $model->categories = $this->getListOfManyMany('Category'); $model->save() }

    public function getListOfManyMany($otherClass)
    {
            $thisClass = 'Entrytype';
            $i = 0;
            $arr = array();
            while(true)
            {
                    $i++;
                    $str = 'rel-'.$i.'-'.$thisClass;
                    if (isset($_POST[$str][$otherClass]))
                    {
                            $val = $_POST[$str][$otherClass];
                            if (!empty($val))
                                    $arr[] = $val;
                    }
                    else
                            break;
            }
            return $arr;
    }

sorry for the bad code intendention :s and perhaps someone has a better idea to do this - would be nice to see one here

#439 report it
Orteko at 2010/06/02 03:55am
Saves some time

This in conjunction with the CAdvancedarbehavior extension definitely saves some time.

Would like to see both of them extended further and added to the trunk.

My only issue currently is that I can't get it to use the saved data to display what has been previously selected on update.

#599 report it
Floorian at 2010/04/13 12:02pm
Like the concept

helps to simplify using many-many on display. great features such as returnTo. Overall like where this extension is headed. It will be a time saver as it improves.

minor issues:

  • in documentation returnTo option is actually returnLink and creates a returnTo parameter for _GET

  • in documentation addButtonString does not exist: showAddButton contains the text to display or false to not display

  • data is not showing as selected in my listbox.

Leave a comment

Please to leave your comment.

Create extension