Monday, January 5, 2009

Superficial impression of Zend Framework

It is huge, compared with other frameworks such as CakePHP or CodeIgnitor.

You can use it as a library without following its MVC architecture design. For example, Zend_Validate class family can save you a lot of work on input validation.

Naturally, huge framework comes with huge document - Programmer's reference guide.

Sometimes you need to head into the source code to figure out what really happened.

Despite its huge size, I think it is still easy to learn, although it may not be easier than any other frameworks.

Sunday, January 4, 2009

Integrate Smarty with Zend Framework

I collected some information regarding this topic.

The first one is probably the easiest approach to use Smarty in Zend framework.
require('Zend.php');

include 'smarty/Smarty.class.php';
$smarty = new Smarty();
$smarty->template_dir = 'resources/templates';
$smarty->compile_dir = 'resources/templates_c';
$smarty->plugins_dir = array(SMARTY_DIR . 'plugins', 'resources/plugins');
//may be some more smarty setup

//register this smarty
Zend::register('smarty', $smarty);

//use it in action controller
class IndexController extends Zend_Controller_Action
{
function index()
{
$smarty = Zend::registry('smarty');
$smarty->assign('title', 'Test');
$smarty->display('index.tpl');
}
}

However, you have to handle view logic in your action controllers.

The second option is to extend Zend_View_Abstract
class Templater extends Zend_View_Abstract
{
protected $_path;
protected $_engine;

public function __construct()
{
$config = Zend_Registry::get('config');

require_once('Smarty/Smarty.class.php');

$this->_engine = new Smarty();
$this->_engine->template_dir = $config->paths->templates;
$this->_engine->compile_dir = sprintf('%s/tmp/templates_c',
$config->paths->data);

$this->_engine->plugins_dir = array($config->paths->base .
'/include/Templater/plugins',
'plugins');
}

public function getEngine()
{
return $this->_engine;
}

public function __set($key, $val)
{
$this->_engine->assign($key, $val);
}

public function __get($key)
{
return $this->_engine->get_template_vars($key);
}

public function __isset($key)
{
return $this->_engine->get_template_vars($key) !== null;
}

public function __unset($key)
{
$this->_engine->clear_assign($key);
}

public function assign($spec, $value = null)
{
if (is_array($spec)) {
$this->_engine->assign($spec);
return;
}

$this->_engine->assign($spec, $value);
}

public function clearVars()
{
$this->_engine->clear_all_assign();
}

public function render($name)
{
return $this->_engine->fetch(strtolower($name));
}

public function _run()
{ }
}
And we need to set up view renderer in bootstrap file
// setup the view renderer
$vr = new Zend_Controller_Action_Helper_ViewRenderer();
$vr->setView(new Templater());
$vr->setViewSuffix('tpl');
Zend_Controller_Action_HelperBroker::addHelper($vr);

An alternative is to implement Zend_View_Interface
class App_View implements Zend_View_Interface
{
/**
* Smarty object
* @var Smarty
*/
protected $_smarty;

/**
* Constructor
*
* @param string $tmplPath
* @param array $extraParams
* @return void
*/
public function __construct($tmplPath = null, $extraParams = array())
{
require_once ('Smarty/Smarty.class.php');
$this->_smarty = new Smarty;

if (null !== $tmplPath) {
$this->setScriptPath($tmplPath);
}

foreach ($extraParams as $key => $value) {
$this->_smarty->$key = $value;
}
$config = Zend_Registry::get('config');
$this->_smarty->compile_dir = sprintf('%s/templates_c', $config->paths->data);
$this->_smarty->plugins_dir = '';
$this->base_url = $config->paths->baseurl;
}

/**
* Return the template engine object
*
* @return Smarty
*/
public function getEngine()
{
return $this->_smarty;
}

/**
* Set the path to the templates
*
* @param string $path The directory to set as the path.
* @return void
*/
public function setScriptPath($path)
{
if (is_readable($path)) {
$this->_smarty->template_dir = $path;
return;
}

throw new Exception('Invalid path provided');
}

/**
* Retrieve the current template directory
*
* @return string
*/
public function getScriptPaths()
{
return array($this->_smarty->template_dir);
}

/**
* Alias for setScriptPath
*
* @param string $path
* @param string $prefix Unused
* @return void
*/
public function setBasePath($path, $prefix = 'Zend_View')
{
return $this->setScriptPath($path);
}

/**
* Alias for setScriptPath
*
* @param string $path
* @param string $prefix Unused
* @return void
*/
public function addBasePath($path, $prefix = 'Zend_View')
{
return $this->setScriptPath($path);
}

/**
* Assign a variable to the template
*
* @param string $key The variable name.
* @param mixed $val The variable value.
* @return void
*/
public function __set($key, $val)
{
$this->_smarty->assign($key, $val);
}

/**
* Retrieve an assigned variable
*
* @param string $key The variable name.
* @return mixed The variable value.
*/
public function __get($key)
{
return $this->_smarty->get_template_vars($key);
}

/**
* Allows testing with empty() and isset() to work
*
* @param string $key
* @return boolean
*/
public function __isset($key)
{
return (null !== $this->_smarty->get_template_vars($key));
}

/**
* Allows unset() on object properties to work
*
* @param string $key
* @return void
*/
public function __unset($key)
{
$this->_smarty->clear_assign($key);
}

/**
* Assign variables to the template
*
* Allows setting a specific key to the specified value, OR passing
* an array of key => value pairs to set en masse.
*
* @see __set()
* @param string|array $spec The assignment strategy to use (key or
* array of key => value pairs)
* @param mixed $value (Optional) If assigning a named variable,
* use this as the value.
* @return void
*/
public function assign($spec, $value = null)
{
if (is_array($spec)) {
$this->_smarty->assign($spec);
return;
}

$this->_smarty->assign($spec, $value);
}

/**
* Clear all assigned variables
*
* Clears all variables assigned to Zend_View either via
* {@link assign()} or property overloading
* ({@link __get()}/{@link __set()}).
*
* @return void
*/
public function clearVars()
{
$this->_smarty->clear_all_assign();
}

/**
* Processes a template and returns the output.
*
* @param string $name The template to process.
* @return string The output.
*/
public function render($name)
{
return $this->_smarty->fetch($name);
}

/**
* get smarty template dir
*
* @return string template dir
*/
public function getScriptPath()
{
return $this->_smarty->template_dir;
}//end getScriptPath()
}


There is one problem with this method: all template files have to be placed in one directory. What if we want to put template files in different folders? Say, i have two modules, and their templates are placed in two folders named with the module names?

The key is the value of template_dir. To work around, we can specify template_dir at action controller.

class App_ControllerAction extends Zend_Controller_Action
{
public $db;
public function init()
{
//set smarty templete dir
$module = $this->getRequest()->getModuleName();
$path = Zend_Registry::get('config')->paths->templates;
if (empty($module) === false) {
$this->view->setScriptPath($path . '/' . $module);
}
}
}

Share two FREE books download websites

http://www.ebookee.com/

http://www.pdfchm.net/

The second website specializes in IT books. I am not sure if they are legal but, hey, they are there and you do can download books from them. And these books may cost you hundreds of bucks if you buy the print version from amazon or any book stores.

Wednesday, December 24, 2008

singleton discussions

Why I Hate Singletons
http://www.ds-o.com/archives/77-Why-I-Hate-Singletons.html

Singletons are not evil
http://www.mattberther.com/2004/05/27/singletons-are-not-evil/

Why Singletons are Evil
http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx

Thursday, December 18, 2008

OOP Principles

Below principles are extracted from the excellent PHP book: PHP In Action.

1. THE OPEN-CLOSED PRINCIPLE
A class should be open to extend, closed to modification. A refactoring technique is also regarded in this principle: Replace conditional with polymorphism.

In real world: when a new requirement comes up, what a programmer usually do is, open the source code, find the related part, put if (condition) {//do the new requirement}

2. THE SINGLE-RESPONSIBILITY PRINCIPLE
a class that tries to do everything will have to change frequently because
some responsibility it has needs to be updated. A class should have only one reason to change.

In real world: any other template engines except smarty can allow developers put business logic into it?

3. THE DEPENDENCY-INVERSION PRINCIPLE
GoF tell us: program to an interface, not an implementation.

4. LAYERED DESIGNS

Friday, December 12, 2008

read list

I list some books which i am reading and about to read.

1. PHP Objects, Patterns, Practices
2. PoEA
3. High Performance Mysql 2nd edition (i read the 1st one and feel good. Wonder the difference in 2nd edition)
4. Symbian S60 Programming a tutorial guide
5. Symbian Effective C++
6. Common Design Patterns for Symbian

Monday, December 8, 2008

Good and Bad PHP Code

Today I read a blog about good and bad php code. http://www.sitepoint.com/blogs/2007/05/25/good-and-bad-php-code/

When I asked this question to myself, what is good php code, I surprisingly find out that my brain is blank! However, when I try to ask in the other way, what is bad php code, I can give tons of examples. Below is some of them.

0. Variable is not initiated.
1. Not using isset to check if a variable is initiated.
2. Not checking data type
3. Global variables everywhere
4. Static methods everywhere
5. Long functions (function should be short & simple enough that you even think unit test is not required)
6. Long parameters
7. Duplicate codes
8. Low efficient coding style
9. huge class
10. No memory management concept in mind (Yes, even PHP we need to think of that!)
11. Implement large project without MVC architecture.
12. Put business logic in presentation logic(Especially for smarty users)
13. Like to use too many if, else, switch to control the logic
14. Without security concept in mind (sql injection, string filter)
15. poor DB modelling and SQL statements, e.g. using too many Mysql Fucntions which could be done in PHP, using IN in sql Query (Although this is not PHP code)