Thinking about Models

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Thinking about Models

Post by matthijs »

One thing I've been thinking about this week is Models. At first that doesn't sound very interesting, you know you have a thing and a few methods to deal with that thing, insert(), delete(), findby(). But once you think about having more flexibility and more functionality then that it can be quite challenging.

I'm superficially familiar with some of the design patterns like Datamapper, Active record, etc to know it can get quite complex.

The problem I have had with designing my model layers is that at first you write down what pieces of data you have. Then you define their relationships. You start coding a few db classes. But then at some point in time you realize the relationships between the different kinds of data should be changed. Now you can throw all you models in the garbage. There should be better ways.

The thing that got me thinking about it was the thread about onion2k's idea about a photo gallery and how to deal with data. Do you place images (things) in groups/categories/sets/etc etc? As soon as you think traditionally ( a photo goes in an album, each album can have many tags or can be in certain categories, etc) you limit your models to be in a certain way. But as onion2k said, if you let go of that idea and only deal with tags, you might get much more flexibility.

Also take email for example. If you look at gmail, there's basically only Labels. An email arriving is labeled Inbox. An email sent is labeled Sent. You can give as many labels as you want to any email. You can create new labels. You are free to use as many labels as you want on all messages.

And that could work for more situations. Like a blog for example. Traditionally you have Posts, Comments, Categories, Tags and Authors. With certain fields. And certain (limited) relationships. But some people would like to have other sorts of posts, or use posts for other content-type (video, podcasts, etc). Maybe people would like to use other relationships between the different kinds of data. Now what if you just start with a single piece of data, and use only labels. If you label it "Post", it can be used in the traditional sense as a blog post. But you also Label it with "Henry" as the author. And as "PHP" as some sort of category. So you have a lot of flexibility, but without having a specific set of tables and relationships between those tables, which are hard or impossible to change.

So, is that something more people use? Are there certain problems with an approach like this?
blueyon
Forum Commoner
Posts: 76
Joined: Tue Oct 30, 2007 9:53 am

Re: Thinking about Models

Post by blueyon »

This is what I have found about models. Models are not ORM's, Datamapper, Active record etc.. and should not be mixed up.

Models should not be complex.

You will never get the flexibility of raw SQL when using ORM's , Active record, datamappers.

Remember models are not just related to a database they are doing all the nitty gritty calculations and business logic. They could be reading multiple XML feeds and returning the data as an array.

Unfortunately most frameworks out there have decided to write their own orm languages. Its just not required and over complicates things. Its best to just use:

Code: Select all

 
<?php
$product_info = $model->get('product')->getById(1);
 
$model->get('product')->insert($request->getData());
 
$model->get('product')->update(1, $request->getData());
 
$products = $model->get('product')->getByCategoryId(1);
 
class ModelProduct extends Model {
    function getById($product_id) {
        return $this->db->query("SELECT * FROM product WHERE product_id = '" . (int)$product_id . "'");
    }
 
    function insert($data) {
        $this->db->query("INSERT INTO product SET name = '" . $this->db->escape(@$data['name']) . "'");
    }
    
    function update($product_id, $data) {
        $this->db->query("INSERT INTO product SET name = '" . $this->db->escape(@$data['name']) . "' WHERE product_id = '" . (int)$product_id . "'");
    }   
    
    // etc..
}
?>
 
Look at phpdoctrine for example. It might have taken whoever wrote it ages and they still can not can the full flexability thats available when using raw SQL.
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Re: Thinking about Models

Post by matthijs »

Thanks for your reply. There's certainly something valuable in what you say. But I think that we are talking about a slightly different thing. Related and overlapping maybe, but let me explain it a bit more.

What I'm trying to figure out is a better way to organize my models and relationships between them.

The problem is, that when I have defined a few sets of specific Models with each their own specific fields in a db table, and all those specific table related in some way (one-to-one, on-to-many, many-to-many) and at some point I need to change one thing, I have to throw it all around. It's hard to add or remove or change something when everything is so tightly coupled.

So what I was thinking about for example is have a more general table with "stuff". Call it "Meta". Now I can store more kinds of data in that same table. Take a blogging app. I have a table posts. But also that table Meta. And in that table I could place anything.

Code: Select all

 
id  postid  name  value
1   1    Author   James
2   1    Category  PHP
3   1    Category  Code
4   2    Author   Henry
5   2    Category   CSS
6   2    Kind   Blogpost 
7   1    Kind   Page
 
This way, when at some point I decide I to add "Tags" to my blogging app, I just insert them in that table. No need to change anything to the structure of my tables.

However, writing this makes me realize that as soon as I need more info on one kind of item, say Authors, I'm back to adding another table..... This idea probably only works for more simple models. But I think it can work and simplify in some situations. Like the Gmail example I gave.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Thinking about Models

Post by Christopher »

blueyon wrote:This is what I have found about models. Models are not ORM's, Datamapper, Active record etc.. and should not be mixed up.
Do you realize that the example you showed is the TableDataGateway pattern? ;) :)

Those patterns are certainly all ones that can be applied to creating Models. What I agree with you about is that using a single library for all Models is not the right way to go (like only using Doctrine or Rail's everything is ActiveRecord) . I also agree that TableDataGateway is really good for most situations (it is the main solution in Skeleton). Each Model in the Domain should implement the appropriate pattern(s) to solve that problem.
(#10850)
blueyon
Forum Commoner
Posts: 76
Joined: Tue Oct 30, 2007 9:53 am

Re: Thinking about Models

Post by blueyon »

arborint wrote:
blueyon wrote:This is what I have found about models. Models are not ORM's, Datamapper, Active record etc.. and should not be mixed up.
Do you realize that the example you showed is the TableDataGateway pattern? ;) :)

Those patterns are certainly all ones that can be applied to creating Models. What I agree with you about is that using a single library for all Models is not the right way to go (like only using Doctrine or Rail's everything is ActiveRecord) . I also agree that TableDataGateway is really good for most situations (it is the main solution in Skeleton). Each Model in the Domain should implement the appropriate pattern(s) to solve that problem.
Yes i suppose it does look like one. I should have used a more complicated example.

I don't think the tablegateway pattern is a good idea as a model. The problem for tablegateway pattern is that it limits the model to one table.

Also I think the tablegateway pattern normally has some SQL in the parent class that helps you cut down on the amount of code. This is bad because models are not their just to manipulate databases.

Models are there to just get the data or preform a task they don't have to follow any other pattern or stucture.

It could be:

$customers = $model->get('customer')->getByBirthdayToday();

$quotes = $model->get('report')->getStockQuotesFromXmlFeed();

$model->get('order')->process(1);

An Order process example could be adding the information about the order into a database then reducing the stock from the products table and then dispatching emails.

Using "$model->get" means you can use any method any model class thought the site. This is the whole point of making components reusable thoughout the site.
Post Reply