Extending your Doctrine Model: Template Classes


Symfony | Technical | Development | Doctrine | January 20, 2011

A lot of times in the past, working with Symfony 1.X and Doctrine 1.X, I got into a problem. According with Model View Controller design pattern, you have to carefully choose what to put in each layer. For example if it is some business logic you have to put that in the Model, if it is some HTML as is in the web case you have to put that in the View and finally if it is some code to manage the view and model, you have to put that in the Controller.

It is easy to read that and say: "Hey I'm going to follow this cool pattern". However, when programming, against the clock it is not so simple. Maybe you put some business logic in the controller or perhaps you put some view related code into the model. The last case used to happen to me a lot of times and I'll show you why.

The Problem

Let's say you have this schema:

 
Employee:
  tableName:    t_employee
  actAs:
    Sluggable:  { fields: [ name ] }
  columns:
    id:         { type: integer  , length: 20 , primary: true, autoincrement: true }
    name:       { type: string   , length: 50                , notnull: true       }
    web:        { type: string   , length: 255                                     }
    photograph: { type: string   , length: 255                                     }
 

Here we got an Employee entity with three attributes: name, web and photograph.

In your templates you are going to use surely these two statements:

 
link_to($employee->getName(), $employee->getWeb(), array('title' => $employee->getName()))
 

This shows the name of the employee as a link to his web page.

 
link_to(image_tag($employee->getPhotograph()), $employee->getWeb(), array('title' => $employee->getName()))
 

This shows the photograph of the employee as a link to his web page.

Because you are going to use this two statements a lot let's put them in a place where its reuse is guarantee:

 
class Employee extends BaseEmployee
{
  public function getLinkToWeb()
  {
    return link_to($employee->getName(), $employee->getWeb(), array('title' => $employee->getName()));
  }
 
  public function getLinkToWebWithPhotograph()
  {
    return link_to(image_tag($employee->getPhotograph()), $employee->getWeb(), array('title' => $employee->getName()));
  }
}
 

Now you can reuse this code for all your templates ... Wrong!!!!!

We were talking about separating of concerns with MVC pattern and you mix view code with the model. The idea behind the model is to have just the logic related to the data and no more. Imagine you are going to use your model with a different markup than HTML, then these functions will make  no sense at all.

Now you know the problem I had.

 

The Solution: Template classes

It would be great if all these methods could continue in the model classes, but remember: that's wrong. Then let's create an extension of our model to work just with our HTML view.

The How

1.- Create in your project/lib/model the template directory.

2.- Add to the previous directory the EmployeeTemplate.class.html"php">  class EmployeeTemplate extends sfDoctrineTemplateExt { public function getLinkToWeb() { return link_to($employee->getName(), $employee->getWeb(), array('title' => $employee->getName())); }   public function getLinkToWebWithPhotograph() { return link_to(image_tag($employee->getPhotograph()), $employee->getWeb(), array('title' => $employee->getName())); } }  

 

3.- Now, to properly connect your model with the template classes you need: sfDoctrineTemplateExt class

 
/**
 * sfDoctrineTemplateExt
 *
 * @package    symfext
 * @subpackage doctrine
 * @author     Jonathan Olger Nieto Lajo [[email protected]]
 */
abstract class sfDoctrineTemplateExt
{
  protected
    $object = null;
 
  public function __construct(DoctrineRecord $object)
  {
    $this->object = $object;
  }
 
  public function __call($method, $arguments)
  {
    return call_user_func_array(array($this->object, $method), $arguments);
  }
}
 

 

4.- Update your sfDoctrineRecordExt file. As you may know Doctrine gives the advantage of changing the inheritance hierarchy of your model in one level. That is, you can put a class (or many) in the middle of the inheritance hierarchy. In my case, the whole hierarchy would be:

Doctrine_Record_Abstract > Doctrine_Record > sfDoctrineRecord > sfDoctrineRecordExt > BaseEmployee > Employee

 
/**
 * sfDoctrineRecordExt
 *
 * @package    symfext
 * @subpackage doctrine
 * @author     Jonathan Olger Nieto Lajo [[email protected]]
 */
abstract class sfDoctrineRecordExt extends sfDoctrineRecord
{
  /**
   * Returns the corresponding template instance of this model.
   * 
   * @param boolean $force Whether or not the method should force the conversion
   * 
   * @throws RuntimeException If force and the corresponding template class does not exist
   * 
   * @return DoctrineRecord|DoctrineTemplate The result of the conversion
   */
  public function toTemplate($force = true)
  {
    $template_class = $this->getTable()->getComponentName().'Template';
 
    if (class_exists($template_class))
    {
      $template = new $template_class($this);
 
      return $template;
    }
 
    if ($force)
    {
      throw new RuntimeException(sprintf('The "%s" class does not exist. You can\'t convert a sfDoctrineRecordExt to a template without the template class', $template_class));
    }
 
    return $this;
  }
}
 

 

5.- Try your brand new functionality in the showEmployeeSuccess.html"php">  ?php echo $employee->toTemplate()->getLinkToWeb() ?php>  

Or

 
  ?php echo $employee->toTemplate()->getLinkToWebWithPhotograph() ?php>
 

 

Finally, the  model is free from view related code and there is the possibility to reuse methods and functionality on an entity basis.


Comments


coorubcodenda said about 11 days later

bardzo ciekawe, dzieki

Jonah Turnquist said about about 1 month later

To solve the above problem in Yii I would probably create a custom helper class.

"Helper classes: in views we often need some code snippets to do tiny tasks such as formatting data or generating HTML tags. Rather than placing this code directly into the view files, a better approach is to place all of these code snippets in a view helper class. Then, just use the helper class in your view files. Yii provides an example of this approach. Yii has a powerful CHtml helper class that can produce commonly used HTML code. Helper classes may be put in an autoloadable directory so that they can be used without explicit class inclusion."

- https://www.yiiframework.com/doc/guide/1.1/en/basics.best-practices#view

Unmakehah said about 6 months later

haszu jedzenie , https://jedzeniewroclaw.com/co-nam-daje-mila-atmosfera-w-restauracji.html"comment"> Unmakehah said about 6 months later

haszu jedzenie , https://jedzeniewroclaw.com/co-nam-daje-mila-atmosfera-w-restauracji.html"comment"> Unmakehah said about 6 months later

haszu jedzenie , https://jedzeniewroclaw.com/co-nam-daje-mila-atmosfera-w-restauracji.html"comment"> Unmakehah said about 6 months later

haszu jedzenie , https://jedzeniewroclaw.com/co-nam-daje-mila-atmosfera-w-restauracji.html"comment"> Unmakehah said about 6 months later

haszu jedzenie , https://jedzeniewroclaw.com/co-nam-daje-mila-atmosfera-w-restauracji.html"comment"> Unmakehah said about 6 months later

jedzenie lodow na bol gardla , https://restauracjewarszawa.net/smaczne-i-polecane.html"comment"> Unmakehah said about 6 months later

jedzenie lodow na bol gardla , https://restauracjewarszawa.net/smaczne-i-polecane.html"comment"> Unmakehah said about 6 months later

jedzenie lodow na bol gardla , https://restauracjewarszawa.net/smaczne-i-polecane.html"comment"> Unmakehah said about 6 months later

jedzenie lodow na bol gardla , https://restauracjewarszawa.net/smaczne-i-polecane.html"comment"> Unmakehah said about 6 months later

jedzenie lodow na bol gardla , https://restauracjewarszawa.net/smaczne-i-polecane.html"comment"> Unmakehah said about 6 months later

raciborz catering , https://restauracjeopole.com/lokalna-kuchnia.html"comment"> Unmakehah said about 6 months later

raciborz catering , https://restauracjeopole.com/lokalna-kuchnia.html"comment"> Unmakehah said about 6 months later

raciborz catering , https://restauracjeopole.com/lokalna-kuchnia.html"comment"> Unmakehah said about 6 months later

raciborz catering , https://restauracjeopole.com/lokalna-kuchnia.html"comment"> Unmakehah said about 6 months later

raciborz catering , https://restauracjeopole.com/lokalna-kuchnia.html"comment"> Unmakehah said about 6 months later

jedzenie kalorie , https://cateringpoznan.net/roznice-w-cateringu.html"comment"> Unmakehah said about 6 months later

jedzenie kalorie , https://cateringpoznan.net/roznice-w-cateringu.html"comment"> Unmakehah said about 6 months later

jedzenie kalorie , https://cateringpoznan.net/roznice-w-cateringu.html"comment"> Unmakehah said about 6 months later

jedzenie kalorie , https://cateringpoznan.net/roznice-w-cateringu.html"comment"> Unmakehah said about 6 months later

jedzenie kalorie , https://cateringpoznan.net/roznice-w-cateringu.html"comment"> Unmakehah said about 6 months later

pizzerie ursynow , https://jedzeniekrakow.info/dobre-jedzenie-w-centrum.html"comment"> Unmakehah said about 6 months later

pizzerie ursynow , https://jedzeniekrakow.info/dobre-jedzenie-w-centrum.html"comment"> Unmakehah said about 6 months later

pizzerie ursynow , https://jedzeniekrakow.info/dobre-jedzenie-w-centrum.html"comment"> Unmakehah said about 6 months later

pizzerie ursynow , https://jedzeniekrakow.info/dobre-jedzenie-w-centrum.html"comment"> Unmakehah said about 6 months later

pizzerie ursynow , https://jedzeniekrakow.info/dobre-jedzenie-w-centrum.html"comment"> Unmakehah said about 6 months later

bydgoszcz restauracje stary rynek , https://restauracjebydgoszcz.net/19-pysznosci-polskiej-kuchni.html"comment"> Unmakehah said about 6 months later

bydgoszcz restauracje stary rynek , https://restauracjebydgoszcz.net/19-pysznosci-polskiej-kuchni.html"comment"> Unmakehah said about 6 months later

bydgoszcz restauracje stary rynek , https://restauracjebydgoszcz.net/19-pysznosci-polskiej-kuchni.html"comment"> Unmakehah said about 6 months later

bydgoszcz restauracje stary rynek , https://restauracjebydgoszcz.net/19-pysznosci-polskiej-kuchni.html"comment"> Unmakehah said about 6 months later

bydgoszcz restauracje stary rynek , https://restauracjebydgoszcz.net/19-pysznosci-polskiej-kuchni.html"comment"> Unmakehah said about 6 months later

catering torun forum , https://krakowrestauracje.net/jak-oszczedzac-na-wakacje.html"comment"> Unmakehah said about 6 months later

catering torun forum , https://krakowrestauracje.net/jak-oszczedzac-na-wakacje.html"comment"> Unmakehah said about 6 months later

catering torun forum , https://krakowrestauracje.net/jak-oszczedzac-na-wakacje.html"comment"> Unmakehah said about 6 months later

catering torun forum , https://krakowrestauracje.net/jak-oszczedzac-na-wakacje.html"comment"> Unmakehah said about 6 months later

catering torun forum , https://krakowrestauracje.net/jak-oszczedzac-na-wakacje.html"comment"> Unmakehah said about 6 months later

catering w domu , https://jedzeniepoznan.com/jak-zjesc-dobrze-i-niedrogo-1.html"comment"> Unmakehah said about 6 months later

catering w domu , https://jedzeniepoznan.com/jak-zjesc-dobrze-i-niedrogo-1.html"comment"> Unmakehah said about 6 months later

catering w domu , https://jedzeniepoznan.com/jak-zjesc-dobrze-i-niedrogo-1.html"comment"> Unmakehah said about 6 months later

catering w domu , https://jedzeniepoznan.com/jak-zjesc-dobrze-i-niedrogo-1.html"comment"> Unmakehah said about 6 months later

catering w domu , https://jedzeniepoznan.com/jak-zjesc-dobrze-i-niedrogo-1.html"crud_edit">


My Tweets

10 days ago
I'm sooo not looking forward to getting up for work tomorrowwww - cant wait for this thing to work! https://tinyurl.com/67rg4lo
12 days ago
finally this class #semester is finished, new #projects in mind
20 days ago
Mark Zuckerberg Explains His Law Of Social Sharing [Video]https://t.co/sqq10Ehh via@TechCrunchh
about 1 month ago
retomando mi #twitter #notime
about 1 month ago
Inspiring for ANYONE who hates their job and their STUPIDD GD BOSS https://tinyurl.com/3cz3pan
about 1 month ago
How Facebook Can Put Google Out of Businesshttps://t.co/HqDfQGoo via@TechCrunchh
2 months ago
So why not just cut out the middle man? Microsoft.https://techcrunch.com/2011/05/15/samsung-series-5-chromebook/
2 months ago
really like to #design class hierarchies with #compositepattern
3 months ago
Similarly, Microsoft.com started to use jQuery instead of their own ASP.NET Ajax framework. They are still using Windows, for whatever XD
3 months ago
Estudiantes de la PUCP le “voltean” campaña a esposo de Keiko | yoperiodhttps://t.co/ruI9UnmI9Unm@lamulaamula
3 months ago
Reading: Apress.-.Pro.html"https://www.twitter.com/search?q=#php">#php #performance #read
3 months ago
debug_backtrace() is very important on certain situations. #php #debug
3 months ago
@alvarezrodrich felicitaciones!
4 months ago
time to do some #uml diagrams, #classdiagram
4 months ago
hoy es el día,#votaa conciente#peruu
4 months ago
@skoop @funkatron I think someone had a bad day!, #Frameworks are there but you don't have to use them.
4 months ago
making #wireframes for a new #functionality
4 months ago
so much #spam on my #blog =(
4 months ago
learning new topics and tools that I did not use before #rcp
4 months ago
aprendiendo muchos temas y herramientas que no utilizaba antes #rcp
4 months ago
#tweaking httpd.conf #virtualhost
4 months ago
thanks #symfony 1.4, even when i'm not using the entire #framework, yours classes save my life!
4 months ago
integrating with #SOA using #soap
4 months ago
It seems my most #productive working hours are on #sunday #afternoon #evening! XD
4 months ago
#ASOT 500 =)
4 months ago
installing SCA_SDO on #Centos #php
4 months ago
My web service using #soap worked!!!!! #php #SCA #SDO
4 months ago
Working in a new place since last week!, #RCP: Red Científica Peruana, the one which sells the .pe domains in#Perúú ->#happypy
5 months ago
Finally with a new #laptop: #Toshiba =)
5 months ago
@pasku1 Thanks, I will try Pivotaltracker.
5 months ago
@doolphy thanks for your answer doolphy! I'll try you!
5 months ago
@jmasson thanks for your answer! Jira + Confluence is a good combination.
5 months ago
Which is the best project management and collaboration tool right now? #projectmanagement #tool #collaboration
5 months ago
What a #voice! Sied Van Riel feat Nicole McKenna - Stealing Time (Aly & Fila Remix) + #ASOT 497 #trancefamily
5 months ago
working on a situation where #php #traits would be very useful
5 months ago
It is #awesome when you finish doing a lot of changes and nothing is broken =) #TDD #testing
5 months ago
oh, happy birthday! @mtabini o mejor dicho feliz cumpleaños!
5 months ago
why do #IE8 not accept #javascript "const" keyword?
5 months ago
Discovering there is much #more to do with #javascript ... a lot.
5 months ago
Awesome #song!: Cerf, Mitiska & Jaren - Another World (Original Vocal Mix) #ASOT 495 #trancefamily
6 months ago
My legal woman is #PHP, but I have an affair with #Javascript, overall when she wears #jQuery.
6 months ago
This presentation is one of the best I've seen about #unit #testing https://www.slideshare.net/avalanche123/clean-code-5609451
6 months ago
where to do a master on #IT: US or Spain? #survey #php #master plz RT
6 months ago
Bobina feat. Betsie Larkin - You Belong To Me: What a #beautiful voice -> #ASOT 494 #arminvanbuuren
6 months ago
OH NO, IT'S MONDAY -- 2011-02-07 https://t.co/pgaIxe5 via @gojkoadzic
6 months ago
it was not a + b, it was parserInt(a) + parseInt(b) =(, #javascript #fail
6 months ago
The models are complete representations of the system, whereas an #architectural #view focuses only on what is architecturally #significant.
6 months ago
@jmasson that would be great and finally #wikimedia, #drupal, #wordpress and maybe #joomla would push towards the same side, the #php side.
6 months ago
@jmasson Thanks!, #PHP has a bright #future ahead.
6 months ago
A new #blog post about not reinventing the #wheel: /article/symfony2_phpbb4_and_drupal8 #symfony #phpbb #drupal
6 months ago
@giorgiosironi #indeed, that's a very good #question. I think an average of 4 but also depends on how much that #developer work.
6 months ago
It seems the new platform for deploying, managing and scaling PHP apps is https://orchestra.io/ #cool
6 months ago
#Phase project planning vs #iteration project #planning - #project #management
6 months ago
#jeditable with #jquery save my life =)
6 months ago
Amazing #song -> Sied van Riel feat. Nicole McKenna - Stealing Time #ASOT 493 #trancefamily
6 months ago
I simply love "offset" #jquery function =)
6 months ago
I really don't understand why projects like #drupal does not base their components in projects like #doctrine and #symfony
6 months ago
OH NO, IT'S MONDAY -- 2011-01-17 https://t.co/37pr4Bd via @gojkoadzic
6 months ago
@alvarezrodrich me alegra ver q ya borró su cuenta Sr. Rodrich,#twitterr es malo jajja, XD
6 months ago
Acabo de hacerle a mi #brother @diegonl89 un blog para que hable de #actualidad en general: https://www.elgatotechero.com #peru
6 months ago
I just made to my #brother a #blog to talk about current #events in #peru: https://www.elgatotechero.com
6 months ago
Amazing things can be done with #javascript and #css, and of course with the help of #jQuery =)
6 months ago
An architecturally significant element is an element that is important for #understanding the #system.
6 months ago
An architecturally element has a wide impact on the #structure, #performance, #robustness, #evolvability, and #scalability of a #system.
6 months ago
@giorgiosironi Definitely!
6 months ago
Playing with #table #inheritance in #Doctrine
6 months ago
Reading about #RUP, and how addresses the #major difficulties in a new #project.
6 months ago
A new blog #post about #refactoring your queries with #Doctrine: /article/refactoring_queries_with_doctrine #symfony
6 months ago
Yandex in 2010: 43 percent revenue growth https://t.co/cpjT5Jw via @cnet
6 months ago
Going forward!!!!! =) poco a poco llegan los resultados de tanto esfuerzo #fb
6 months ago
Perfect #system with respect to the #requirements but the #wrong system with respect to the #real #problem at the time of #delivery.
6 months ago
Going #forward! =) #fb
6 months ago
A new #blog #post about integrating #Doctrine with #Yii and #Symfony: /article/integrating_doctrine_symfony_vs_yii
6 months ago
@sam_dark Ok thanks!, but I don't understand why in #Yii documentantion use $_GET and $_POST instead of CHttpRequest https://bit.ly/i5emoL