Wednesday, August 17, 2011

Formatting CDetailView

CFormatter is used when you're doing some custom formatting to a CDetailView (among other places). Here's the link to the Class Reference on the Yii site:

CFormatter | Class Reference | Yii Framework

Here's an example of using some of the formatting options:

widget('zii.widgets.CDetailView', array(
'data'=>$model,
'attributes'=>array(
'id',
'type',
'title',
array(
'name'=>'content',
'type'=>'ntext',
),
array(
'name'=>'release_date',
'type'=>'text',
'value'=>date_format(new DateTime($model->release_date), 'm-d-Y'),
),
array(
'name'=>'external_link',
'type'=>'url',
),
array(
'label'=>'Image',
'type'=>'image',
'value'=>$model->image->getImgSrc(),
),
),
)); ?>

In this example, I've included a few fields - id, type, and title - in the straightforward, default, manner. These will be formatted as text, by default. But I wanted to include my carriage returns for the content, so instead of simply specifying my content attribute the same way I did 'type' or 'title' I have created an array of options. The first element specifies the name of one of this model's attributes, 'content.' I want the value of 'content' to be formatted as 'ntext.' This will convert line breaks to '
' tags for me. The attribute 'external_link' is formatted as a 'url.'

The model's image is a little trickier. The model I'm displaying with this CDetailView has a relation, 'image,' that joins records out of the images table with details about a particular image. But this main model, itself, only has a foreign key - image_id - to relate to the images table. It's not very interesting to see image_id, to tell you the truth, so I like to display the actual image using the HTML image tag. Doing this within CDetailView requires that I get the details for the Image model that is related to this particular model I'm displaying.

How do we do this? The first step is not to use the 'name' attribute as I have elsewhere; 'name' tells CDetailView to expect to display the attribute for this main model (which would render the image_id integer), not information from a relation (that is, data from the join part of the query). Instead, I use 'label.' This just tells CDetailView to use whatever value I provide for 'label' as the label when displaying the rest of the information. The type has been set to 'image,' which lets CDetailView know to format this using the tag.

Now, here's the crux of it. So far, we have a label and a tag, but we do not have a value to include. That value is important, because it ends up being used as the 'src' attribute within our image tag (). I happen to have a helper method for my Image model that gets the image source so that I can use it in image tags. It just creates a string of the relative path in the app for whatever image is being handled. Now, all I have to do for the value is get the related image for our main model and call the Image method, getImgSrc() on it. (You don't know this, because I didn't mention it, but I have direct access to the image relation because I used 'with' in my query when I loaded this particular model. No great details on this, here, but suffice to say that you can do this when you load your model: instead of simply doing ModelName::model()->findByPk($id), do ModelName::model()->with('somerelation')->findByPk($id). Google "eager loading Yii." Anyway, this is why I can do: $model->image->imageMethod().)

One other thing. Did you notice I used 'text' for my type for the date? There is an actual 'date' type, but I could not get it to work to my liking. The common workaround I've seen is simply to use standard PHP date formatting and just output the result as text. It's a real pain, IMO. If I figure it out, I'll post it.

6 comments:

  1. I struggled to format the content in one of the CDetailView pages in my Yii application and this article really helped. Thanks.

    ReplyDelete
  2. thanx alot, this is article is seriously very useful..

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Great way to format dates and works with bootstrap TbDetailView as well

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Can you please explain this lines $model->release_date i.e what is $model and release_date means?

    ReplyDelete