Jump to content
Larry Ullman's Book Forums

Yii Organisation Question (Again)


Recommended Posts

I'm back Larry!

 

In my Yii journey I've created a model and controller for a particular table. What I wanted to do was on my index page list the latest 10 records, so in my model i created the following function:

public function latestRecords()
{
 $command = Yii::app()->db->createCommand();
 $latestResults = $command->select('id, title, des')
 ->from('item_detail')
 ->limit(10)
 ->order('id DESC')
 ->queryAll();

}

 

Firstly is that the best way + place to put such a query. I always thought keeping DB queries was better in the model?

 

My other question is how do you go about including the results of this query in the visible index file, i.e not a file that relates directly to this model? Do I need to set the $model inside the view for the index page?

 

In my column1.php which i am using in my physical index page I am currently instantiating a new object of the ItemDetail(); is that wrong or too much code in a view?

Edited by Jonathon
Link to comment
Share on other sites

To further this solution I did some reading and web research and I went for this approach:

 

alter the siteController.php to:

 // limits query for index page results to 10
 $Criteria = new CDbCriteria();
 $Criteria->limit = 10;
 // renders the view file 'protected/views/site/index.php'
 // using the default layout 'protected/views/layouts/main.php'
 $this->render('index', array(
	    'ItemDetails' => ItemDetail::model()->findAll($Criteria),
    ));

 

Then inside the index.php view I was able to go:


<?php foreach($ItemDetails as $ItemDetail):?>
   <tr>
       <td><?php echo $ItemDetail->title;?></td>
       <td><?php echo $ItemDetail->des;?></td>
   </tr>
<?php endforeach;?>

 

So I guess in this particular case I didn't have to alter my model after all.

 

My next progression is to be able to load this data in my column1.php not index.php as that's where I need it.

Link to comment
Share on other sites

Right, I have definitely progressed with my learning of Yii. The guide is useful, but I do like very clear instructions for things, so in parts I find the guide too vague. Basically in my model I have this code:

 

public function latestRecords()
{
 $command = Yii::app()->db->createCommand();
 $latestResults = $command->select('id, title, des')
 ->from('item_detail')
 ->limit(10)
 ->order('id DESC')
 ->queryAll();
return $latestResults;
}

 

Then in my SiteController inside actionindex I call:

  $this->render('index', array('latestItems' => ItemDetail::model()->latestItems()));

 

So I gather that this renders the index.php view file and then loads then allows me to use the my custom method inside my model to return and use the variable "latestItems" inside my index.php view. This works which I'm happy about, because I was definitely missing something previously.

 

So inside my index.php view this code generates my results with html formatting:

		 <table width="100%">
<?php  foreach($latestItems as $item): ?>

		    <tr>
			    <td><a href=""><?php echo $item['title']; ?></a></td>
			    <td><a class="none" href="">London</a></td>
			    <td><a class="none"><?php echo $item['des']; ?></a></td>
			    <td><a class="button" href=""><?php echo $item['id']; ?></a></td>
		    </tr>		  
<?php endforeach; ?>		   
		    </table>

 

Does this look right Larry? I don't want to be doing something wrong from the get go.

 

My only real question now, is how to I allow tha variable $latestItems to be used in my column1.php layout file? As my Home page, uses the index.php view but it then pulls in the column1.php file to complete the page make up.

 

Happy New Year People :)

Link to comment
Share on other sites

I think finally I have figured out a way to do this - Widgets!

 

I took everything out of the sitecontroller.php and just left it as

public function actionIndex()
{
 // renders the view file 'protected/views/site/index.php'
 // using the default layout 'protected/views/layouts/main.php'
 $this->render('index');
}

 

Then I created a widget component and used this code

class latestItemsWidget extends Cwidget {
public function run() {

// pulls the last 10 items from DB
 $latestItemsResults = ItemDetail::model()->latestItem();

 $this->render('latestItems', array('latestItemsResults' => $latestItemResults));
}
}

 

Then created the view for this widget

<?php if($latestItemsResults) :?>
<?php foreach($latestItemsResults as $item): ?>
<tr>
	<td><a href=""><?php echo $item['title']; ?></a></td>
	<td><a class="none" href="">London</a></td>
	<td><a class="none"><?php echo $item['des']; ?></a></td>
	<td><a class="button" href="path/to/specifics<?php echo $item['id']; ?>">View</a></td>
</tr>		  
<?php endforeach; ?>
<?php endif; ?>

 

Then inside the column1.php layout file

  <?php $this->widget('latestitemsWidget') ?>

 

Does that seem about right Larry?

Link to comment
Share on other sites

Hey Jonathon,

 

Apologies for not getting to this sooner; busy with holidays and such. Looking at this thread, first, as for where you define a function that runs a specific query, I would suggest that if the particular query is only used in one place, then the custom query can be written in that controller. If the query will be used in multiple places, then I would add it to the model. Second, I would only do a widget if you really need to create a re-usable component. If the widget is the only thing on a page, then it'd be better off with a standard view, which wouldn't add the overhead of a widget.

Link to comment
Share on other sites

That's no problem Larry, I hope you had a nice holiday!

 

Yes the query is only run and used on the actual home page. So I should move this function query from the model and put it in the corresponding controller code. Again the widget was only in the home page too. I was using this inside my column1.php layout file

<?php $this->beginContent('//layouts/main'); ?>

 

and this inside my index.php view

 

<?php $this->layout='column1'; ?>

 

to merge the index.php view and the column1.php layout file as my home page. Should I also make the column1.php layout file into a view?

 

How would I render, both the index.php view file + an additional view file and be able to use the result set from the query inside the secondary view file.

 

I had problems making

/ pulls the last 10 items from DB
 $latestItemsResults = ItemDetail::model()->latestItem();

 $this->render('latestItems', array('latestItemsResults' => $latestItemResults));
	}

 

$latestItemsResults available to anything but the index.php view.

Link to comment
Share on other sites

I have moved the items in column1.php into a secondary index-2.php view and pulled in the views together like so:

$model = ItemDetail::model()->latesItems();
$outputView2 = $this->renderPartial('index-2', array('model' => $model), true);
$this->render('index', array('model' => $model, 'outputView2' => $outputView2));

 

Just need to sort out my layout and i'll be happy for the index page (in terms of layout) :D

 

Thanks Larry, much as I was elated that i'd finally got it to work I would rather being doing it more efficiently then burdening my server with calls.

Link to comment
Share on other sites

As for the function as query, if you put it in the model, then every use of that model needs to define that function, including, say, inserting or updating an instance of that model. If only a single page uses that function/query, then it's a lot of extra overhead for one purpose. So it's a matter of finding the right balance.

 

You would use a widget if every page that used a certain layout needed that content. If you only have one page that uses that content, it should go directly in that page's view (IMHO).

 

To render multiple view files in one page, use renderPartial.

 

Glad you're making progress!

Link to comment
Share on other sites

Thanks Larry for your help. I am slowly making progress, I feel like the Yii Docs are helpfull, but they could be so much more helpful if they had more examples. For instance I don't suspect that what I'm doing on my home page is particularly unique, but there are so many questions regarding views and layouts and including several of either or both. It is a big shift from including a generic $conn file or header, to including multiple files when you aren't really sure how they fit together and nothing seems to be as it first seems.

 

I made a mistake above, I moved the code from my model and created that method that gets the last 10 records inside my siteController.php then inside the actionIndex() I called $model = $this->latestResults();

 

I have got everything as I wanted now, to anyone else who may be interested I have

 

Index.php (View)

<?php $this->layout='home'; // bring in home.php to home page ?>
<?php $this->pageTitle=Yii::app()->name; ?>
<?php Yii::app()->clientScript->registerCoreScript('jquery'); // bring in jquery for various things?>
<?php echo $outputView2; ?>

 

Index-2.php (View)

HTML Stuff and
<?php if($model) :?>
<?php foreach($model as $jitem): ?>
<tr>
	<td><a href=""><?php echo $item['title']; ?></a></td>
	<td><a class="none" href="">London</a></td>
	<td><a class="none"><?php echo $item['des']; ?></a></td>
	<td><a class="button" href="<?php echo $item['id']; ?>">View</a></td>
</tr>		  
<?php endforeach; ?>
<?php endif; ?>
Some more markup

 

I also made a new layout as this isn't my default layout

 

Home.php (Layout)

<?php $this->beginContent('//layouts/main'); ?>
HTML MARKUP
<?php
// calls index-2.php view
echo $content;
?>
Slightly more markup
<?php $this->endContent(); ?>

  • Upvote 1
Link to comment
Share on other sites

 Share

×
×
  • Create New...