I'm making a site that has a lot of different categories, each with their own controller/model/views.
Example site categories: Dining, Movies, Nightlife, Sports...etc
My Controllers: restaurants, theaters, events, articles, cities, users... and more
I also have a site homepage that pulls data from all of them to populate little boxes on the page. And, each category has it's own homepage that also could pull data from different categories - for instance, on the "Movies" homepage, it might also pull in restaurants and sporting events that are nearby the theaters and maybe a few recent articles from the articles model... etc etc - there is a lot of category-overlap.
How do I set this up? The sporting event isn't tied to the movie at all, so I can't imagine any hasMany/belongsTo type relationships - but I still need to access the data. And especially on the homepage, which really has no table at all, but needs to pull data from all of the above.
Your problem is too big to cover in its entirety. I'll address accessing multiple models across different controllers. This can be done in several ways.
by relationship:
$this->Event->City->find(); // relationship to City exists in Event Model
by adding it to the $uses property in your controller:
var $uses = ('City');
by loading into the method as needed:
function some_method() {
App::import('Model', 'City');
$this->City->find();
Each has its own benefits. You should read more about Models in the CakePHP Book. If you have a large amount of relationhships, you should check out LazyModel for lazy loading your models.
Sounds like you need to implement components to handle the various categories. The component will provide the access for the category box for any given page (which will be different from the category home page).
Then I would implement an element called 'category' that you can pass the information to from the component. I would also make all components export similar data. This will keep it simplified but still provide the flexibility you are looking for.
In summary, create components for each category:
DiningComponent
NighlifeComponent
etc.
Pass the output to the category element to be displayed on the page.
At first glance maybe you don't see another model that is overarching, but the idea that you are calling them "categories" means they have to be a category of something, possibly activities. The new model may be pretty thin, but I would maybe suspect something like appearance scheduling to be involved with the activity model, so you can give it a beginning and ending publish date. If you don't want to call it an "activity", maybe something generic like "contentItem" would give you somewhere to control global attributes. Another exercise would be to compare your existing models and look for duplicate attributes. What are those duplicate attributes describing?
You could use the loadModel function if there is no relation between two controllers
$this->loadModel('Foo');
$this->Foo->Bar();
When there is a relation of course, you can do
$this->Foo->Bar->Baz();
This is probably what you want
How to build a dashboard for your cakephp application
To understand more about the data models in CakePHP you can use http://cakeApp.com a online schema builder.
Related
I started to develop a little Content Management System for two languages (de, en) that starts to grow bigger.
In that context, I have Posts and Pages (a bit like WordPress or actually just like WordPress). But I am also planning to add further content types like Reviews, Courses, Tutorials (Recipes) and maybe even E-Books that are purchasable.
All these objects would have in common that they are contentable, so they will be shown on the front end with their dedicated urls, like /posts/{slug} for posts, /{slug} for pages, /reviews/{slug} for reviews and so on.
On the backend, this means an auto save and revision system is offered for these content types.
So, this would leave us will the following options:
Single Table Inheritance (we would need to live with many null values) - not supported officially by Laravel, but there is a package.
Multi Table Inheritance (which is not supported in Laravel either)
Polymorphism which is supported
CMS solution (like craft CMS), which basically breaks up the logic in elements, entries, fields and so on, alternative approach would be drupal's node approach - out of scope I believe (I dont have 6-9 months time to write a CMS from the scratch)
Have on Table per Model and try to use as much logic as possible between the models by using Traits (current status, I don't like it that much...).
After some googling, searching here on stackoverflow and looking at other projects, I am thinking of the following structure:
contents table:
id
site_id
title
... (some more columns that are shared among all models)
contentable_type
contentable_id
posts
id
pages
id
home
courses
id
name
featured
difficulty
free
So, these tables would be linked to the contents table through a belongsTo relationship, and the content model would define the morphable relationship.
class Content extends Eloquent {
public function contentable(){
return $this->morphTo();
}
}
class Post extends Eloquent (or Content) {
public function content(){
return $this->morphOne('Content', 'contentable');
}
}
Working with models would mean you would always have to load the content relationships.
Sorting & Ordering must be performed by joins.
And when creating, of course, we have to first create the content type model and then save and attribute it to a content model.
I never implemented a system with that kind of (sub) logic before, and it feels a bit odd to me to have a posts table with just an id (same would be true for other content types e.g. "abouts" in case they don't have extra columns), but I think it would be the "Laravel way" to solve this issue, right?
I believe STI wouldn't work for this case, and it is also a bit against Laravel's Eloquent pattern.
Has somebody already experiences with this approach? Am I on the right track here?
Note: I got inspired by the discussion here: How can I implement single table inheritance using Laravel's Eloquent?
In case anyone finds this question. I finally decided against this approach, basically because I believe it is not worth the efforts (and also most of the packages won’t work out of the box).
It is a much better approach to use Traits et cetera to reuse as much logic as possible and follow the Eloquent ORM approach.
Apologise if it sounds a dumb question, but if I never ask, I'll never learn. I have been recently working with the MVC implementing pattern, and I'm still learning stuff, so please be patient with me.
I've been recently working on a multi-languages website that uses a custom MVC framework for a client. In some places I'd need to display some information from more than one table, like an article (from the articles table), the name of the languages that this article is written in (from the languages table), the languages that this article is not yet written in (from the languages table also), and the author (from the authors table).
I have a model for the articles, a model for the languages, and a model for the authors, and each has its own controller.
If I only query articles tables only or the authors tables only, there is no issue, but the confusion comes when I want to display information from this different tables into a single view.
How I should do that?
Instantiate a language model object and an author model object in the article controller and call their related functions to get the data and then combine/merge their data with the data from the article model (all in the article controller as mentioned)?
Instantiate the language model and the author model in the article model and call their functions to get their data, then combine/merge the their data with the data from the article model itself?
Do a join or nested select in the article model to get the data from multiple tables, and not interact with any other model, even if that mean some queries will be repeated in more than on model?
Another approach?
What is the best way do that?
This can be done in several ways:
- Create a view (a virtual table of MySQL) which using join, nested select or whatever you want to achieve all necessary information and create a model on top of this view in MVC (this model can only retrieve info from the view not alter it, however)
- Use repository pattern. A repository wrap many models and you can implement business logic (which might be CRUD on multiple models/tables) here. The controller simply use the repository instead of model.
In summary the model, repository should wrapping all the business logic of its own never let the controller do these stuff.
Regards,
Is there any point in having both? I followed a Zend tutorial which told me to create a user model but can't I just model the user in the DB model class?
Thanks
It's part and parcel of the concept of "separation of concerns" http://en.wikipedia.org/wiki/Separation_of_concerns
Your model class takes care of business logic, validation, variable manipulation etc and your db model class should just handle dealing with the database, that way if you need to replace the db model it wont affect the main model as much, and if you replace the main model it wont affect the db model as long as the right parameters are passed into it.
Yes, you can model your user in Application_Model_DbTable_User (DbTable class) and it will work fine as long as all of the data you need is in that one table.
At some point you will likely start working with objects that should be represented in more then one table. This is when you will discover the need for a different way to do things.
A better simple example of where a mapper and domain object might matter:
The mp3 file.
At it simplest a single music file should probably be represented by at least 3 db tables:
album: a table representing the album the song comes from
artist: the artist that recorded the song
track: the information about the track itself
each artist can have multiple albums, each album will have one artist and will have multiple tracks, each track will belong to one album and one artist (different versions will be different tracks).
As you can see the database stucture of even a simple mp3 collection can become very complex very quickly. In most cases even a simple user record will spread across multiple tables depending upon how much and what kind of data is being persisted.
For some help in understanding how and why to implement mappers and models I found these resources very helpful.
Building a Domain Model, covers what a domain model is and how to build one in PHP.
Adding Mappers to a Domain Model, adds mapper function to the same domain model.
Survive the Deepend, A Zend Framework starter that focuses on models and testing.
The first two links are done in plain PHP but are still very helpful.
To understand my confusion/question, let me first give a quick overview of the site I'm building: The site has a homepage, and 7 category pages, each with the same/similar layout.
On most category homepages (eg "Dining"), you can do a search (ie a search for restaurants), which will take you to a results page. This will have the same/similar layout as the... "Theaters" search result page...etc etc.
So - although there are a lot of sections, there are not a lot of page layouts.
Question: I'm not sure if I should create separate controllers for each, and just use the same CSS for them? Or if I can use the same view file, but populate each content area on the page differently based on the url/action..etc?
They'll all reference different & multiple tables in the database - for instance, restaurants will reference the restaurants table, the cuisines table, the zip_codes table...etc. Theaters might reference the "movies" table, the zip_codes table...etc etc etc
But - I also want an admin tool for some - ie "restaurants/edit" or "theaters/edit" ...etc - not ALL the pages will have admin for that specific url - ie "outdoors" might just be "businesses/edit" or something generic... I don't know - I'm confused as you can tell.
Any help is GREATLY appreciated. I've read a lot about the technical things to do w/ CakePHP, but I can't find any good resources for general project structures for varying scenarios.
You can answer this yourself. Suppose you implement separate controllers, models and views for each, how do they differ? If they only differ in the table names and labels/strings that they use, then you can use just one generic controller. But, if they are different in other ways (e.g. the Restaurants model has a totally different relationship structure than a Movie model) then use separate controllers.
To prevent too many repetition between controllers and view files when you do use separate controllers, try to push functionality in a common base controller (e.g. AppController, of create your own base controller based on AppController that your MoviesController and RestaurantsController and so on will derive from). Push generic view code into elements.
A word about CSS: Of course you can (and should) reuse that. It's mostyly separate from the view. Just use sensible class names and id's in your views and the CSS will be easy to reuse.
If you are still unsure, I'd go with separate controllers. It may be more work but it will be cleaner and easier to debug. Use the above suggestions to avoid repetition.
-group elements that will share among all site in a layout (ie. site css, site common js library)
-make a view for each of your category(page) (ie. dining page, theater page, restaurants page) and put there page only stuff (ie. theater js, theater includes) there
- in theory, every vew should have a controller and model, so you have to make them separate.
anyway url like "restaurants/edit" or "theaters/edit" actually means model "restaurant", operation "edit" in your controller file.
I suggest you read the blog tutorial from cakephp site, you that should answer all your confusion
i dont quite understand this pattern.
from what i have read, it looks like one model = one table (if you are using database to store data).
so if i've got a table called tags, i should have a tags model. and with a threads table i create a threads model.
then i got a tags controller and a threads controller right?
so what if i've got a tags_threads_map table for a many-to-many relationship.
should i have a tags_threads_map model eg. in which i get all threads containing a tag? should i have a tags_threads_map controller too?
would be great if someone could explain or give me a good breif tutorial on this.
the most tutorials just give a simple 1:1:1 example.
To fully understand MVC or any software design pattern, you really need to have a go at implementing it and see what your results are.
That said, MVC does not prescribe that one model = one table. In fact, a model could be backed by a number of tables, or even data originating in something other than a relational database (e.g. a web service, flat files, a key-value store or a graph database for example).
I would suggest that creating models and views that represent meaningful aggregates of related tables is probably a good approach. For example, to use the timeworn example of an Order and OrderLine table, an Order model might encapsulate operations on data that will ultiamtely end up in either the Order table or the OrderLine table.
Adhering to strict 1-to-1 mapping of table to Model, View and Controller will only result in an explosion of classes, some of which may not be doing much individually. Better to build Models and Controllers that are more focused on achieving some task identified by the business requirements, rather than just being a projection of the data model.
So the idea is less "one model = one table" and more that you don't want code that manages the data to be interleaved with code that manages the operations on data or code that handles user interaction. If you have some sort of persistance layer that handles mapping of objects to a database, that's enough to have a rudimentary model. If you have some separate code on top of that that does something algorithmic with that data, that's a controller. If you have a way of rendering the data for user consumption, that's a view.
Best example that comes to mind is a spreadsheet: the data in the spreadsheet is your model. If you have expressions in your sheet that manipulate the data, that can be seen as a controller. If you see the data in tabular form, or in a graph, those are two views. The views don't muck with the data or how it's calculated - they format it for your eyes. The controller doesn't format the data for your eyes - it creates / changes / calculates the data. The important part is separating out the concepts so you can, for example, write algorithms that don't care how data is stored, and views that don't care how data is calculated.
In my opinion, it's better to think of a model as a model of an object type, not of one specific table.
Generally, your MVC framework would handle your many-to-many relationships by definitions from within the models for tags and threads.
And you definitely don't need a controller for every model; controllers are generally more closely related to views (though there are usually multiple views to one controller).
This seems like it's too general of a question to be able to be answered to your satisfaction here.
A model can be more dynamic than that. For example, if you have a blog, and a blog has tags, your model might be called Blog and it can have a collection of Tags.
A model can be anything that stores the data. In the web app I'm working on there are several tables for contacts, their addresses which groups they belong to and so on. It's probably best to split them up by types, I should have made a group model but you don't strictly have to do this.
MVC relates to 3d games quite well, MVC is not only for information systems. Consider this:
In 3d graphics the model is map, the polygons and their positions and colours. The view is the camera from which the scene is viewed, a position, zoom and direction. The controller interprets the keyboard and mouse and manipulates both the camera(view) and scene(model).
If this were a shooter game then if:
A user pushes the forward button, the controller moves the camera forward.
A user pushes the throw grenade button, controller adds a grenade to the scene.
The view is presentation, the model is storage/structure and the controller is an in between which tells the view what to display and how to display it based on the state of the system.
Generally you put all the formatting in a view, data in models and logic into controllers.