Jump to content
Larry Ullman's Book Forums

Listdata Textfield Argument, For A Dropdownlist


lrzins
 Share

Recommended Posts

Hi, I've created a drop down list of user's names, that I've concatenated from first_name and last_name in a database table. And it works perfectly! Here's what I've got:

 

User Model:

 

public function getFullName()
{
    return $this->first_name . " " . $this->last_name;
}

 

StudentRecordController, in actionCreate():

 

$students = CHtml::listData(User::model()->with('studentRecords')->findAll(), 'id', 'FullName');

 

And in views/studentRecord/_form.php:

 

<?php echo $form->dropDownList($model, 'user_id', $students, array('empty' => 'Select Student Name')); ?>

 

My question is, how is the getFullName() method called by the third argument to listData, which is 'FullName'? The "get" is parsed out? If I use the full method name instead (getFullName), it does'nt work. And actually fullname, fullName, FuLlNaMe all work.

 

Bear in mind, that with this approach, you have to include the $students array in the render method of the controller and the view.

 

Larry Z.

Link to comment
Share on other sites

I had some trouble with CHtml::listData it would not work correctly in one of my situations. So what i done is create an array manually then the sent the array from the model to the dropdown function in the view and it worked perfectly.

 

For example here was some of my model code:

 

public function getShippingServiceOptions()
{
 $list = array();
 $list['']='Select a shipping service';
 $list['service1']='Economy services from outside US';
 $list['1']='Economy Shipping from outside US (11 to 23 business days)';
 $list['service2']='Standard services from outside US';
 $list['5']='Standard Shipping from outside US (5 to 10 business days)';
 $list['service3']='Expedited services from outside US';
 $list['10']='Expedited Shipping from outside US (1 to 4 business days)';
 $list['econony-services']='Economy Services';
 $services = $this->findAll('type=:type', array(':type'=>'economy-service'));

 foreach($services as $service)
 {
	 $list[$service->id]=$service->description;
 }
return $list;
}

 

I don't think there would be much difference between this and putting together a first name and last name.

  • Upvote 1
Link to comment
Share on other sites

@lrzins: The reason it works is because YII will look for model attributes and by convention require you to have a get-method for it. You can argue both ways if this is a good solution, but currently you just need to know that's how it works. The reason different versions of caps/similar also works, must be because YII applies some String operations there.

  • Upvote 2
Link to comment
Share on other sites

Ah yeah and about the get the root of all yii classes extend from the Ccomponent Class that is where you get or set problem lies.

 

https://github.com/yiisoft/yii/blob/1.1.13/framework/base/CComponent.php

 

/**
* Returns a property value, an event handler list or a behavior based on its name.
* Do not call this method. This is a PHP magic method that we override
* to allow using the following syntax to read a property or obtain event handlers:
* <pre>
* $value=$component->propertyName;
* $handlers=$component->eventName;
* </pre>
* @param string $name the property name or event name
* @return mixed the property value, event handlers attached to the event, or the named behavior
* @throws CException if the property or event is not defined
* @see __set
*/
public function __get($name)
{
$getter='get'.$name;
if(method_exists($this,$getter))
return $this->$getter();
elseif(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
{
// duplicating getEventHandlers() here for performance
$name=strtolower($name);
if(!isset($this->_e[$name]))
$this->_e[$name]=new CList;
return $this->_e[$name];
}
elseif(isset($this->_m[$name]))
return $this->_m[$name];
elseif(is_array($this->_m))
{
foreach($this->_m as $object)
{
if($object->getEnabled() && (property_exists($object,$name) || $object->canGetProperty($name)))
return $object->$name;
}
}
throw new CException(Yii::t('yii','Property "{class}.{property}" is not defined.',
array('{class}'=>get_class($this), '{property}'=>$name)));
}
/**
* Sets value of a component property.
* Do not call this method. This is a PHP magic method that we override
* to allow using the following syntax to set a property or attach an event handler
* <pre>
* $this->propertyName=$value;
* $this->eventName=$callback;
* </pre>
* @param string $name the property name or the event name
* @param mixed $value the property value or callback
* @return mixed
* @throws CException if the property/event is not defined or the property is read only.
* @see __get
*/
public function __set($name,$value)
{
$setter='set'.$name;
if(method_exists($this,$setter))
return $this->$setter($value);
elseif(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
{
// duplicating getEventHandlers() here for performance
$name=strtolower($name);
if(!isset($this->_e[$name]))
$this->_e[$name]=new CList;
return $this->_e[$name]->add($value);
}
elseif(is_array($this->_m))
{
foreach($this->_m as $object)
{
if($object->getEnabled() && (property_exists($object,$name) || $object->canSetProperty($name)))
return $object->$name=$value;
}
}
if(method_exists($this,'get'.$name))
throw new CException(Yii::t('yii','Property "{class}.{property}" is read only.',
array('{class}'=>get_class($this), '{property}'=>$name)));
else
throw new CException(Yii::t('yii','Property "{class}.{property}" is not defined.',
array('{class}'=>get_class($this), '{property}'=>$name)));
}

  • Upvote 1
Link to comment
Share on other sites

Thanks Edward and Antonio, that explains it. As Edward suggested, I moved the code from the controller into the model, and now have:

 

In models/StudentRecord.php

 

public function getStudentNames()
{
    return CHtml::listData(User::model()->with('studentRecords')->findAll(), 'id', 'FullName');
}

 

In models/User.php

 

public function getFullName()
{
    return $this->first_name . " " . $this->last_name;
}

 

And in views/studentRecord/_form.php

 

<?php echo $form->dropDownList($model, 'user_id', $model->getStudentNames(), array('empty' => 'Select Student Name')); ?>

 

I think this is a good way to do it. It's nice to know about the convention of adding "get" to the method names (why and where).

 

Best regards,

Larry Z.

Link to comment
Share on other sites

 Share

×
×
  • Create New...