A Good Appraoch For Showing Different Kind Of Content Together

Hy,

I’ve just started with Yii 2 weeks ago. And Yes It Is awesome :)! I’m allmost done with the blog tutorial (nice one) and a lot of other tutorials and youtube video’s. Already I see there are a lot of benefits using this framework.

Now I’m building a website and I doubt what a good approach would be. Simplefied the design is like this:

  • Homepage

  • Blogs

  • Articles

  • Photobooks

Except for the homepage, it all works fine. I’ve used the gii to create models and controllers and customized them later. But on the homepage, I want to show the last 10 items by date. So the last 10 Blogs, Articles and Photobooks together. What would be a good approach to do this?

I can create a table like Content en have a record for each Blog, Article and Photobook and in these 3 tables a foreign key ‘content_id’. Or is their a more simple way with Yii? I saw that it is possible to make relations with the relations() method.

I’m not asking for sourcecode, I would like that to do myself to keep learning, but a designation how this can be done in Yii would be nice.

Thanks in Advance!

Where did you found Yii2? =)

:D

Hi Bjorn, welcome to Yii (1.1.x).

One possible drawbacks of Gii CRUD is that people tend to misunderstand the MVC structure of Yii. In gii-generated CRUD the model is only used in the corresponding views and the controller. But it’s not neccessarily like that. You may use any models in any controllers and views. So if you want some page that uses multiple models, then just do it.

And having done some tutorials, I think it’s a very good time for you to read through the “Definitive Guide” once again.

You can get all those rows in one query.

Example for two tables:

And if I can mention another great resource (Well worth the $$)

http://yii.larryullman.com/

In your site controller, you can

[list=1][][size=2]load up a few dataProviders and use them in a variety of widgets OR[/size][][size=2]fetch the records and iterate over them[/size][/list]

Look at named scopes to filter only recent records.




// Pass these to your view

$recentBlogPosts = Blog::model()->recent()->findAll();

$recentArticles = Article::model()->recent()->findAll();



Matt

Oh, what a nice profile icon!! :D

For future reference:

4120

Bjorn.png

I feel sad afther what happend yesterday. What a tragedy. But this is not the place to go offtopic about it i guess.

So back to the question.

@sensorario: I stole it.

@softark: Indeed, i’m reading the “Definitive Guide” once again and maybe one or two times after that. It makes much more sense now having some tutorials done.

@johnsnails: I try to read as much as I can and maybe will order the ebook you suggested.

@Pathfinder: this approach I would use before I saw Yii and other frameworks. The power of the framework in my opinion is that it’s full OOP and you don’t have to mess around with all kind of loose queries.

@waterloomatt: That’s more what I was looking for. I understand it, but it don’t cover it all. It will give me some lists beside eachother.

Please let me elaborate this:

Say I got the folowing records:

Blogs

blog 1 - 01-01-2013

blog 2 - 05-01-2013

blog 3 - 20-01-2013

Articles

article 1 - 02-01-2013

article 2 - 03-01-2013

article 3 - 30-01-2013

Photobooks

photobook 1 - 04-01-2013

photobook 2 - 04-01-2013

photobook 3 - 29-01-2013

On the homepage I want to show the last 10 items, with title, description, read more url and depending on the type of content a images preview. And in order it would be like this:

Homepage

blog 1 - 01-01-2013

article 1 - 02-01-2013

article 2 - 03-01-2013

photobook 1 - 04-01-2013

photobook 2 - 04-01-2013

blog 2 - 05-01-2013

blog 3 - 20-01-2013

photobook 3 - 29-01-2013

article 3 - 30-01-2013

I’m not sure how to accomplish this in Yii.

Probably I would create a database view that would return:




type ... blog, article or photobook

id ... id of the blog, article or photobook

date ... date

title ... title

desc ... short description



It should be a union of 3 queries … like the one Pathfinder has suggested, but without ‘ORDER’ and ‘LIMIT’.

And I would create an AR model for that view using gii. Sorting and paginating can be dynamically added when you want to retrieve the data using AR methods.

[P.S.] The new icon is quite nice. :)

Thanks so far. I’m gonne read and try some more. I hope to show the final approach in some time, could be interesting for other newbies maybe.

New avatar is a little bit … but it will do for now :lol:

Ok, i’ve been working on other Yii stuff lately, but today I want to take a look on this item.

So I came up with this approach after all:

First a Union query as suggested. In that query I add a ‘type’ column for every table.

I tried to create it with the querybuilder, but I can’t add an identity column as far as I could see:


->select("id,'blog' AS table_type")

So i skipped the querybuilder part and use the createCommand instead.

Then I loop through the results and build an Array with the object depending on the ‘type’. In the view I’ve got an switch again and it works fine like this.


	public function actionIndex()

	{

	

		$recent_items = Yii::app()->db->createCommand("SELECT id,update_time,'article' AS type FROM articles

								UNION SELECT id,update_time,'blog' AS type FROM blogs

								UNION SELECT id,update_time,'photobook' AS type FROM photobooks

								ORDER BY update_time

								LIMIT 0,10")->queryAll();

		$homepage_items = array();

		foreach($recent_items as $item)

		{

			switch($item['type'])

			{

				case 'article':

					$item_obj = Articles::model()->findByPk($item['id']);

				break;

				case 'blog':

					$item_obj = Blogs::model()->findByPk($item['id']);

				break;

				case 'photobook':

					$item_obj = Photobooks::model()->findByPk($item['id']);

				break;								

			}

			$homepage_items[] = array('type'=>$item['type'],'obj'=>$item_obj); 

		}

		

		$this->render('index',array('homepage_items'=>$homepage_items));

	}

To me it seems to be to much the old way I used PHP. I thought it could be done better in Yii, but maybe it don’t has to be more complicated than this?

What do you people think about this?

Suggestions are much appreciated!

I think it’s a decent solution. :)

Probably we could do some performance optimization by retrieving the data all at once, doing something like this:




SELECT 

    id, 

    update_time, 

    article_content as content,

    NULL as image_file

    'article' AS type

FROM articles

UNION

    SELECT id,

    update_time,

    blog_content as content,

    NULL as image_file

    'blog' AS type

FROM blogs

UNION

    SELECT id,

    update_time,

    NULL as content,

    image_file,

    'photobook' AS type

FROM photobooks

ORDER BY update_time

LIMIT 0,10



And passing not an array of objects but an array of records to the view …

But there are pros and cons about this kind of optimization.

I think the current solution of yours is not bad at all.

Tnx for looking into it!

I understand your suggestion for passing the records directly to the view, but I can’t do that because the Objects like Blog and Photobooks also contains a lot of extra info, like attached images and so. The only thing in common is a Title and Description.