I hope I can be forgiven for asking so many questions recently. I’m new to Yii, and although I’ve read the documentation, including the API, definitive guide, and many of the cookbook topics, I’m not always sure which piece of this sizable (and impressive, I might add) library will best solve the issues I am encountering.
So, I am helping to build this application that displays information about schools, and one of the "problems" is that for each school (represented by a single record in a single table), there are multiple related tables that may or may not have corresponding records in them. Most of these tables are related to the school table in a "has_one/belongs_to" manner.
The issue I’m encountering is that we have fatal errors from PHP when our view file tries to access properties of related models (e.g. echo $school->otherModel->someProperty) that have not been instantiated (because of the lack of a corresponding record).
The hack I came up with for this is extremely messy and goes a little something like this:
-
Rewrite the school controller’s loadModel() method so that after the school::model()->findByPk() method is called, I can
-
loop through each of the items in the school’s relations() array, and
-
if the type of the item is not "object" (resulting from the HAS_ONE relationship) or "array" (from a HAS_MANY relationship),
-
instantiate a new object $item, and
-
Loop through each of the $item’s attributes, and if it is one of the attributes I want to display,
-
assign a default value to it (like "Data not available").
This solution works (sort of), but it is really ugly, and I’d like to find a much cleaner way to ensure that there are no “blank spaces” in my view file resulting from printing out attribute values that are null.
If anyone has any suggestions for a cleaner solution, I am all ears. If you live near me (Florida), I will even buy you a beer!
Thanks!
Tom
p.s. Here is my hack, to satisfy morbid curiosity:
public function loadModel()
{
if($this->_model===null)
{
if(isset($_GET['id']))
$this->_model=School::model()->with(
'admission',
'degree',
'enrollment',
'financialaid',
'graduation',
'insurers',
'lenders',
'testscore',
'tuition'
)->findbyPk($_GET['id']);
if($this->_model===null)
throw new CHttpException(404,'The requested page does not exist.');
}
// Loop through School model's related models, and if no corresponding
// object was created (i.e. there is no corresponding record in the
// database), then instantiate an empty instance of each missing model.
// This is designed to prevent PHP fatal errors when the view
// attempts to access properties of related models for which there
// may be no corresponding records in the database.
foreach(array_keys($this->_model->relations()) as $child)
{
$type = gettype($this->_model->$child);
if ($type != 'object' && $type != 'array')
{
$this->_model->$child = new $child; // e.g. if school doesn't have a (whatever), create one;
Yii::trace("Type of \$child is: " . gettype($child));
// Loop through $child's attributes and set value to
// application "data not available" string
if ($child != 'Lender' && $child != 'Insurance')
{
foreach($this->_model->$child->getAttributes() as $key=>$value)
{
if ($key != 'school_id' && (!stristr($key, 'Period')))
{
$this->_model->$child->setAttribute($key, CActiveRecordExtended::NA);
}
}
}
}
}
return $this->_model;
}