DooPHP IRC channel


PHPTAL Plugin for DooPHP

Share your tips, snippets and experiences about DooPHP, and discuss about best DooPHP practices.

PHPTAL Plugin for DooPHP

Postby UmbertoKo » Wed May 05, 2010 4:23 pm

Hi!

I love templates but I will also see how does it looking befor I use it. I know genshi from python a very nice xhtml template system with includes & co. For PHP I found an also nice (but without include command) TAL based system: PHPTAL (http://phptal.org/). It is i18n'able (translations) and replaces contents and attributes while running app. (Someone ca develop a template, you extends it by setting any tal: attributes. He/she will see the basic design, you and the visitors the real site. Example "<a href='site2.html' tal:attributes='href string:${domainname}/site2.html' tal:replace="${link_name_from_controller}">site2</a>"). An other thing is, that the cache can be set per file or attribute! But it can also compile every time (in "dev" mode).

I have now an controller TalController.php to use PHPTAL:
Code: Select all
<?php
/**
 * Controller to use PHPTAL, where PHPTAL must be in app/protected/class
 * @author UmbertoKo
 * @license GPL v3
 */
class TalController extends DooController
{
   private $tpl;
   private $print_output = true;
   private $templatepath = '';
   public $__taldebug = array();
   
   function __construct($templatename, $returnmode = true, $outputMode = 0, $encoding = 'UTF-8', $lifetime = 1)
   {
      require_once Doo::conf()->SITE_PATH.'/protected/class/PHPTAL.php';
      $this->templatepath = Doo::conf()->SITE_PATH.'protected/view/'.$templatename.'.html';
      $this->print_output = $returnmode;
      if($outputMode == 0)
      {
         $outputMode = PHPTAL::HTML5;
      }
      try
      {
         $this->tpl = new PHPTAL($this->templatepath);
         $this->tpl->setOutputMode($outputMode);
         $this->tpl->setEncoding($encoding);
         $this->tpl->setTemplateRepository(Doo::conf()->SITE_PATH.'protected/view/');
         $this->tpl->setPhpCodeDestination(Doo::conf()->SITE_PATH.'protected/viewc/');
         $this->tpl->setCacheLifetime($lifetime);
         if(Doo::conf()->DEBUG_ENABLED)
         {
            $this->tpl->setForceReparse(true);
         }
         if(Doo::conf()->APP_MODE == 'dev' || Doo::conf()->DEBUG_ENABLED)
         {
            $this->__taldebug[] = var_export($this->tpl, 1);
         }
      }
      catch (Exception $e)
      {
         echo $e;
      }
   }
   
   public function setVars($vars)
   {
      try
      {
         foreach($vars as $i => $dat)
         {
            $this->tpl->$i = $dat;
         }
         if(Doo::conf()->DEBUG_ENABLED)
         {
            $this->__taldebug[] = var_export($this->tpl, 1);
         }
      }
      catch (Exception $e)
      {
         echo $e;
      }
   }
   
   public function execute()
   {
      if(Doo::conf()->DEBUG_ENABLED)
      {
         $this->tpl->tal_debug_messages = stripslashes(var_export($this->__taldebug, 1));
      }
      $output = $this->tpl->execute();
      if(Doo::conf()->DEBUG_ENABLED)
      {
         $this->__taldebug[] = var_export($this->tpl, 1);
      }
      if($this->print_output == true)
      {
         echo $output;
         return;
      }
      return $output;
   }
}
?>


I use it in this way (from an other controller):
Code: Select all
require_once(dirname(__FILE__).'/TalController.php');
$tpl = new TalController('template_new');
   $body = new TalController('body_template', false);
   $body->setVars(self::$data);
   self::$data['inc'] = $body->execute();
   unset($body);
$tpl->setVars(self::$data);
$tpl->execute();

$tpl is the fist template object, which make "print out" (not return if the 2nd param in constructor is true [default]). execute() runs "echo".
$body ist the 2nd template object to render only a sub-template. It will be returned to a var ('inc'). inc is a part of the main template ('template_new') and will be replaced with this value:
Code: Select all
<div tal:condition="inc">
   ${structure inc}
</div>

Both templates 'body_template.html' and 'template_new.html' must be a valid XHTML and be placed in app/protected/view/.

I don't know if this is the best way, but it works fine. To use is save TalController class in app/protected/controller/ and copy the content of http://phptal.org/files/PHPTAL-1.2.1.zip (content of PHPTAL-1.2.1 folder but not itself) to app/protected/class/. And do not forget "require_once(dirname(__FILE__).'/TalController.php');".

Will know, what do you mean.

UmbertoKo

BTW: Do we have a plugin repository? Or a standard way to commit some?
Last edited by UmbertoKo on Thu May 06, 2010 11:39 am, edited 2 times in total.
UmbertoKo
 
Posts: 13
Joined: Tue Feb 16, 2010 8:48 am

Re: PHPTAL Plugin for DooPHP

Postby UmbertoKo » Wed May 05, 2010 4:24 pm

Under http://phptal.org/manuals.html you will find good documentation in some languages.
UmbertoKo
 
Posts: 13
Joined: Tue Feb 16, 2010 8:48 am

Re: PHPTAL Plugin for DooPHP

Postby RichardM » Thu May 06, 2010 1:36 am

Hi,

Thanks for sharing the code :)

No there is not currently a plug-in repository but we are looking to add one. I will also look to put up the ones I wrote for Twig and Smarty at some point (although I never got all the functionality they offer setup).

Also looking at the way you are making use of the TalController it would be better using a separate class as opposed to a controller or designing it to allow your controllers to extend it. If you created a new class like:
Code: Select all
class ViewPHPTal {
// ...
}


Which would then sit in your protected classes folder for your project rather than the protected controllers folder.

You could then assign it to the $_view property of DooController in your base controller and then have the option to quickly switch between template engines (assuming some of the functions where modified to tie in with those in the other Doo View classes).


Ricard
Note: code samples my not be 100% accurate.
RichardM
 
Posts: 1329
Joined: Sun Aug 30, 2009 6:03 pm
Location: Cumbria, UK

Re: PHPTAL Plugin for DooPHP

Postby UmbertoKo » Thu May 06, 2010 11:48 am

Hi Richard!

This is a good idea... but how do I get access to DooController? It is global accessible? (I think so: as a static class...)

What do you mean with DooController->_view? How does it work? Are there a switch for template engines? Any plugin mechanism for config?

I use Doo as is and this way was the easiest one (because I don't use autoroute).

Thx

Umberto
UmbertoKo
 
Posts: 13
Joined: Tue Feb 16, 2010 8:48 am

Re: PHPTAL Plugin for DooPHP

Postby RichardM » Thu May 06, 2010 1:50 pm

Hi,

I think the problem is you have misunderstood the purpose of a controller in the Model View Controller design pattern. The controller should just include the code used to process a specific user action and call the relevant business logic associated with this. Depending on how you choose to implement the pattern this logic would either reside in your Model's or in separate business logic classes. Additionally you would use separate classes for additional functionality you might want. For example in my apps I have some utility classes like MyAppDebugging, MyAppSomeSharedFunctions etc... which you can then use anywhere. I also have a MyAppView which extends DooBasicView and defines a number of additional block tags I can use in my templates.

I would suggest you create a new file protected/class/view/TalView.php
Code: Select all
class TalView {
   public __construct(...) {
       // Code to initialise Tal here
       // I would probably move the template name from here to put in the execute / render function
   }

   public renderView($templateName, ...) {
       // Code to render a given view
       // Would be more or less the code in the execute function()
       // But I would allow the template name to be passed in here (if possible so you can use the same view handler for multiple views being rendered)
   }

   public function setVariables($variables) {
       // This would be your setVars code()
   }

   // You might also add here overriding functions to enable / disable features
}


Then you create a BaseController for your application in
protected/controller/base/BaseController.php
Code: Select all
Doo::loadCore('DooController');
class BaseController extends DooController {

         private $data = array();

         public function __construct() {
      parent::__construct();
                // Load you custom view handler
      Doo::loadClass('view/TalView');
                // Initialise your view handler
      $this->_view = new TalView(...);
   }

        public function set($key, $value) {
             $this->data[$key] = $value;
        }

        public function renderView($view) {
              $this->_view->setVariables($data);
              $this->_view-> renderView($view);
        }
}


Now for each controller you want to have using the Tal engine for its views you can do
Code: Select all
Doo::loadController('base/BaseController');
class MyController extends BaseController {

     public function test() {
           $this->renderView('test');
     }

}


I am looking at a way to provide a range of view engines (which will all be interchangeable) for the major template engines around so you can later just set a global config variable and pick any of them to use (and just have to dump there library files for the one your using into say /myapp/third-party/php-tal/..., /myapp/third-party/smarty/ etc..) so that you can switch between them (albeit with the limitation each uses there own template tags and provide there own additional functionality (hence I've not worked out the logistics of it yet).

Anyway hope that helps clarify what I was suggesting.


Richard
Note: code samples my not be 100% accurate.
RichardM
 
Posts: 1329
Joined: Sun Aug 30, 2009 6:03 pm
Location: Cumbria, UK

Re: PHPTAL Plugin for DooPHP

Postby UmbertoKo » Thu May 06, 2010 3:28 pm

Hi,

I understood it not right. Jep, view renderer must not be a Controller (but I know also view controller from other languages).

I will try this way.

Best

Umberto
UmbertoKo
 
Posts: 13
Joined: Tue Feb 16, 2010 8:48 am

Re: PHPTAL Plugin for DooPHP

Postby UmbertoKo » Thu May 06, 2010 4:00 pm

Now looks better...
proteted/class/TalView.php
Code: Select all
<?php
/**
 * PHPTAL view / render class
 * @author UmbertoKo
 * @license LGPL (same as PHPTAL) http://www.gnu.org/licenses/lgpl.txt
 */

require_once 'phptal/PHPTAL.php';

class TalView
{
   private $tpl;
   private $print_output = true;
   private $templatepath = '';
   public $__taldebug = array();
   
   /**
    * TalView is a view renderer class, which use PHPTAL (as pear or from "phptal" subdirectory of this file)
    * @param String $templatename (optional) name of template to use (without path and ".html"). name will be extendet to "$templatename.html"
    * @param boolean $returnmode (optional) if true print out, else return as a string (good for parsing sub-templates). default print out
    * @param int $outputMode (optional) output structure mode. one of : XML, XHTML, HTML5 (see PHPTAL constants). default XHTML
    * @param string $encoding (optional) charset encoding for template (default 'UTF-8')
    * @param int $lifetime (optional) count of days to cache templates. default is 1
    */
   public function __construct($templatename = '', $returnmode = true, $outputMode = PHPTAL::XHTML, $encoding = 'UTF-8', $lifetime = 1)
   {
      if(!empty($templatename))
      {
         $this->templatepath = dirname(__FILE__).'/../view/'.$templatename.'.html';
      }
      $this->print_output = $returnmode;
      if($outputMode == 0)
      {
         $this->outputMode = PHPTAL::HTML5;
      }
      try
      {
         if($this->templatepath)
         {
            $this->tpl = new PHPTAL($this->templatepath);
         }
         else
         {
            $this->tpl = new PHPTAL();
         }
         $this->tpl->setOutputMode($outputMode);
         $this->tpl->setEncoding($encoding);
         $this->tpl->setTemplateRepository(dirname(__FILE__).'/../view/');
         $this->tpl->setPhpCodeDestination(dirname(__FILE__).'/../viewc/');
         $this->tpl->setCacheLifetime($lifetime);
         if(Doo::conf()->DEBUG_ENABLED)
         {
            $this->tpl->setForceReparse(true);
         }
         if(Doo::conf()->APP_MODE == 'dev' || Doo::conf()->DEBUG_ENABLED)
         {
            $this->__taldebug[] = var_export($this->tpl, 1);
         }
      }
      catch (Exception $e)
      {
         echo $e;
         return false;
      }
      return true;
   }
   
   /**
    * set charset encoding
    * @param String encoding
    */
   public function setEncoding($encoding)
   {
      return $this->tpl->setEncoding($encoding);
   }
   
   /**
    * set output mode
    * @param int output mode
    */
   public function setOutputMode($outputMode)
   {
      return $this->tpl->setOutputMode($outputMode);
   }
   
   /**
    * set cache lifetime
    * @param int lifetime in days
    */
   public function setLifetime($lifetime)
   {
      return $this->tpl->setCacheLifetime($lifetime);
   }
   
   /**
    * set return mode = print output
    */
   public function setReturnModeEcho()
   {
      return $this->print_output = true;
   }
   
   /**
    * set return mode = return output
    */
   public function setReturnModeRetrun()
   {
      return $this->print_output = false;
   }
   
   /**
    * set template vars
    * @param array $vars array of vars to use
    */
   public function setVars($vars)
   {
      try
      {
         foreach($vars as $i => $dat)
         {
            $this->tpl->$i = $dat;
         }
         if(Doo::conf()->DEBUG_ENABLED)
         {
            $this->__taldebug[] = var_export($this->tpl, 1);
         }
      }
      catch (Exception $e)
      {
         echo $e;
         return false;
      }
      return true;
   }
   
   /**
    * set template vars
    * @param String $templatename filename of template to render
    */
   public function renderView($templatename = '')
   {
      if(empty($this->templatepath) && !empty($templatename))
      {
         $this->tpl->setTemplate($templatename);
         $this->templatepath = $templatename;
         $this->tpl->setTemplateRepository(dirname(__FILE__).'/../view/');
         $this->tpl->setPhpCodeDestination(dirname(__FILE__).'/../viewc/');
      }
      elseif(empty($this->templatepath) && empty($templatename))
      {
         echo "template is mising";
         return false;
      }
      if(Doo::conf()->DEBUG_ENABLED)
      {
         $this->tpl->tal_debug_messages = stripslashes(var_export($this->__taldebug, 1));
      }
      try
      {
         $output = $this->tpl->execute();
      }
      catch (Exception $e)
      {
         echo $e;
         return false;
      }
      if(Doo::conf()->DEBUG_ENABLED)
      {
         $this->__taldebug[] = var_export($this->tpl, 1);
      }
      if($this->print_output == true)
      {
         echo $output;
         return true;
      }
      return $output;
   }
}
?>


in BaseController in __construct()
Code: Select all
      require_once(Doo::conf()->SITE_PATH .'/protected/class/TalView.php');
      $this->_view = new TalView();


and in my function
Code: Select all
      $body = new TalView(self::$data['body_template'], false);
      $body->setVars(self::$data);
      self::$data['inc'] = $body->renderView();
      unset($body);
      $this->view()->setVars(self::$data);
      $this->view()->renderView('template_new.html');


The difference between templatename in TalView constructor is: constructor will extend a "word" to a full path with ".html" extension. renderView() needs a full file name with extension. (Any may want to use original .zpt).

PHPTAL can be now a PEAR (in standard include path) or as subdirectory phptal in protected/class/

I hope, this is a convention conform.

Best

Umberto
Last edited by UmbertoKo on Fri May 07, 2010 7:30 am, edited 1 time in total.
UmbertoKo
 
Posts: 13
Joined: Tue Feb 16, 2010 8:48 am

Re: PHPTAL Plugin for DooPHP

Postby RichardM » Thu May 06, 2010 4:34 pm

Hi,

Looks okay to me. Only thing I would ask is that you change the license for the code you have posted up to be the same license as those used for all other DooPHP files. Otherwise the 2 are not really compatible from my understanding as GPL is so viral.


Richard
Note: code samples my not be 100% accurate.
RichardM
 
Posts: 1329
Joined: Sun Aug 30, 2009 6:03 pm
Location: Cumbria, UK

Re: PHPTAL Plugin for DooPHP

Postby UmbertoKo » Thu May 06, 2010 7:20 pm

Hi,

Yes, you have right. It should be v2. I use v3 as default, because its opener...

Best

Umberto
UmbertoKo
 
Posts: 13
Joined: Tue Feb 16, 2010 8:48 am

Re: PHPTAL Plugin for DooPHP

Postby RichardM » Thu May 06, 2010 8:03 pm

Hmm...where did you find it being listed as GPL at all?

DooPHP is released under the new BSD license. See: http://www.doophp.com/license


Richard
Note: code samples my not be 100% accurate.
RichardM
 
Posts: 1329
Joined: Sun Aug 30, 2009 6:03 pm
Location: Cumbria, UK

Next

Return to Tips & Tricks

Who is online

Users browsing this forum: No registered users and 0 guests

cron