mvc | Dmytro Shteflyuk's Home https://kpumuk.info In my blog I'll try to describe about interesting technologies, my discovery in IT and some useful things about programming. Mon, 07 Sep 2015 23:43:35 +0000 en-US hourly 1 https://wordpress.org/?v=6.7.1 Exploring Zend_Controller class of Zend Framework https://kpumuk.info/php/exploring-zend_controller-class-of-zend-framework/ https://kpumuk.info/php/exploring-zend_controller-class-of-zend-framework/#comments Thu, 27 Apr 2006 22:19:56 +0000 http://kpumuk.info/php/exploring-zend_controller-class-of-zend-framework/ Zend Framework team works with gusto on the Zend Framework, great framework for building powerful web-applications in PHP. But too many peoples are confused with its seeming complexity. In this post I will try to explain architecture of most useful part (in my opinion) of Zend Framework – Zend_Controller. For a start, let’s look at […]

The post Exploring Zend_Controller class of Zend Framework first appeared on Dmytro Shteflyuk's Home.]]>
Zend Framework team works with gusto on the Zend Framework, great framework for building powerful web-applications in PHP. But too many peoples are confused with its seeming complexity. In this post I will try to explain architecture of most useful part (in my opinion) of Zend Framework – Zend_Controller.

For a start, let’s look at the following diagram.

Zend_Controller workflow

On this picture you can see workflow of the program based on the Zend Framework. Let’s examine what happens when user requested page.

  1. Script runs Zend_Controller_Front.
  2. Router object will be called to build Zend_Controller_Dispatcher_Token object which contains information about controller, action and params. Before starting routing process routeStartup() method of plugins will be executed to notify plugins that the router is starting up. routeShutdown() method of plugins will be called to notify plugins that the router is shutting down. It’s possible to replace Zend_Controller_Dispatcher_Token returned by router here.
  3. dispatchLoopStartup() method of plugins will be called to notify plugins that the dispatch loop is starting up.
  4. Dispatch loop will be started. Zend_Controller_Dispatcher is repeatedly called until all actions have been dispatched sequentially. This means that you can build chain of actions for execution several operations (for example, authenticate user and forward flow to user’s private area on the server without round-trip.) Before each iteration preDispatch() and after each one postDispatch() methods of plugins will be called to notify plugins that a dispatch iteration occurs.
  5. On each dispatch iteration Zend_Controller_Dispatcher will instantiate Zend_Controller_Action object and will call it’s method run().
  6. Zend_Controller_Action object will call method corresponding to action in Zend_Controller_Dispatcher_Token object. In this class you can use protected method _forward() to set next action to execute without round-trip (in this case dispatch iteration will be repeated again for new action).
  7. dispatchLoopShutdown() method of plugins will be called to notify plugins that the dispatch loop is shutting down.

All notifications to plugins are executed through Zend_Controller_Plugin_Broker which maintains plugins list. This class just forwards all notifications to all plugins in the list.

For example, let’s imagine that user requested following URL: http://somehost.com/products/save/id/10. After saving product with id=10 in database, it’s necessary to show message like “Product has been saved in the database”. Message box is implemented in MessagesController‘s method named showMessageAction(). In this case workflow will be like following:

  1. Script runs Zend_Controller_Front.
  2. Router object will parse requested URL and will extract following information:
    • controllerproducts
    • actionsave
    • paramsid = 10

    Based on this data it will construct Zend_Controller_Dispatcher_Token.

  3. Dispatch loop will be started. Zend_Controller_Dispatcher‘s dispatch() method will be called for Zend_Controller_Dispatcher_Token constructed on previous step.
  4. Dispatcher will instantiate ProductsController object and call it’s run() method. This method will call own method saveAction().
  5. saveAction() method will save product in database. Then it will call method _forward() in following way: $this->forward("messages", "showMessage", array("msg" => "Product has been saved in the database"));.
  6. Dispatch loop isn’t finished because flow was forwarded to another action. Zend_Controller_Dispatcher will be called again with new action.
  7. showMessageAction does not need to forward to another action, therefor workflow will be finished.

To get more detailed information refer to the official manual.

The post Exploring Zend_Controller class of Zend Framework first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/exploring-zend_controller-class-of-zend-framework/feed/ 12
Zend Framework: Using Smarty as template engine https://kpumuk.info/php/zend-framework-using-smarty-as-template-engine/ https://kpumuk.info/php/zend-framework-using-smarty-as-template-engine/#comments Wed, 08 Mar 2006 14:41:17 +0000 http://kpumuk.info/php/zend-framework-using-smarty-as-template-engine/ Zend Framework’s View class has very bad capability for extending. It contains template variables but does not allow to access them, it has array with different pathes (templates, filters), but does not allow to add another type or access them. Therefor only way to use Smarty with Zend Framework is to abandon Zend_View and manipulate […]

The post Zend Framework: Using Smarty as template engine first appeared on Dmytro Shteflyuk's Home.]]>
Zend Framework’s View class has very bad capability for extending. It contains template variables but does not allow to access them, it has array with different pathes (templates, filters), but does not allow to add another type or access them. Therefor only way to use Smarty with Zend Framework is to abandon Zend_View and manipulate Smarty object directly.

First we need to create Smarty object. I do it in index.php after including Zend.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
require('Zend.php');

include 'smarty/Smarty.class.php';
$smarty = new Smarty();
$smarty->debugging = false;
$smarty->force_compile = true;
$smarty->caching = false;
$smarty->compile_check = true;
$smarty->cache_lifetime = -1;
$smarty->template_dir = 'resources/templates';
$smarty->compile_dir = 'resources/templates_c';
$smarty->plugins_dir = array(
  SMARTY_DIR . 'plugins',
  'resources/plugins');

I don’t like global variables therefor I’ve added Smarty object into Zend Framework’s registry:

1
Zend::register('smarty', $smarty);

Using is pretty simple. Just initialize Smarty variables in your Controller class and display template:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class IndexController extends Zend_Controller_Action
{
  function index()
  {
    $smarty = Zend::registry('smarty');
    $smarty->assign('title', 'Test');
    $smarty->display('index.tpl');
  }

  function noRoute()
  {
    $smarty = Zend::registry('smarty');
    $smarty->display('error404.tpl');
  }
}

As you can see Smarty integration with Zend Framework is very simple task. Zend_View has ability to use your own filters and helper functions, but with Smarty you don’t need them because Smarty has its own plugins, filters, modifiers. Just forget about Zend_View and use best template engine for PHP in the world!

Books recommended

The post Zend Framework: Using Smarty as template engine first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/zend-framework-using-smarty-as-template-engine/feed/ 54
Zend Framework: Router for subdirectory-based site https://kpumuk.info/php/zend-framework-router-for-subdirectory-based-site/ https://kpumuk.info/php/zend-framework-router-for-subdirectory-based-site/#comments Wed, 08 Mar 2006 10:36:57 +0000 http://kpumuk.info/php/zend-framework-router-for-subdirectory-based-site/ I started discovering of Zend Framework and was confronted with a problem. When I’ve placed my test sample into site’s subdirectory (http://localhost/test/), default router tried to find TestController which is not exists of course and routed me to IndexController/noRoute. It’s not good for me. I decided to create my own router. There some inconsistence in […]

The post Zend Framework: Router for subdirectory-based site first appeared on Dmytro Shteflyuk's Home.]]>
I started discovering of Zend Framework and was confronted with a problem. When I’ve placed my test sample into site’s subdirectory (http://localhost/test/), default router tried to find TestController which is not exists of course and routed me to IndexController/noRoute. It’s not good for me. I decided to create my own router.

There some inconsistence in Zend Framework (maybe because this is first release). To create my own router I need to develop class which implements Zend_Controller_Router_Interface interface:

1
2
3
4
5
6
7
8
9
10
11
interface Zend_Controller_Router_Interface
{
    /**
     * Processes an HTTP request and routes to a Zend_Controller_Dispatcher_Action object.  If
     * no route was possible, an exception is thrown.
     *
     * @throws Zend_Controller_Router_Exception
     * @return Zend_Controller_Dispatcher_Action|boolean
     */

    public function route();
}

Zend_Controller_Front uses this interface in following way:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Zend_Controller_Front
{
  // ...
  /**
   * Dispatch an HTTP request to a controller/action.
   */

  public function dispatch()
  {
    // ...
    $action = $this->getRouter()->route($this->getDispatcher());
    // ...
  }
}

Fine joke from Zend Framework’s developers. Front controller passes dispatcher to router, but router interface does not receive it. :-) Simplest way to avoid PHP error message is to define parameter which has default value null. Here my router class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/** Zend_Controller_Router_Interface */
require_once 'Zend/Controller/Router/Interface.php';

/** Zend_Controller_Dispatcher_Interface */
require_once 'Zend/Controller/Dispatcher/Interface.php';

/** Zend_Controller_Router_Exception */
require_once 'Zend/Controller/Router/Exception.php';

/** Zend_Controller_Dispatcher_Action */
require_once 'Zend/Controller/Dispatcher/Action.php';

class SubDirectoryRouter implements Zend_Controller_Router_Interface
{
  public function route(Zend_Controller_Dispatcher_Interface $dispatcher = null)
  {
    // SubDirectoryRouter: what's the path to where we are?
    $pathIndex = dirname($_SERVER['SCRIPT_NAME']);

    // SubDirectoryRouter: remove $pathIndex from $_SERVER['REQUEST_URI']
    $path = str_replace($pathIndex, '', $_SERVER['REQUEST_URI']);
    if (strstr($path, '?')) {
      $path = substr($path, 0, strpos($path, '?'));
    }
    $path = explode('/', trim($path, '/'));

    /**
     * The controller is always the first piece of the URI, and
     * the action is always the second:
     *
     * http://zend.com/controller-name/action-name/
     */

    $controller = $path[0];
    $action     = isset($path[1]) ? $path[1] : null;

    /**
     * If no controller has been set, IndexController::index()
     * will be used.
     */

    if (!strlen($controller)) {
      $controller = 'index';
      $action = 'index';
    }

    /**
     * Any optional parameters after the action are stored in
     * an array of key/value pairs:
     *
     * http://www.zend.com/controller-name/action-name/param-1/3/param-2/7
     *
     * $params = array(2) {
     *              ["param-1"]=> string(1) "3"
     *              ["param-2"]=> string(1) "7"
     * }
     */

    $params = array();
    for ($i=2; $i<sizeof($path); $i=$i+2) {
      $params[$path[$i]] = isset($path[$i+1]) ? $path[$i+1] : null;
    }

    $actionObj = new Zend_Controller_Dispatcher_Action($controller, $action, $params);

    if (!$dispatcher->isDispatchable($actionObj)) {
      /**
       * @todo error handling for 404's
       */

      throw new Zend_Controller_Router_Exception('Request could not be mapped to a route.');
    } else {
      return $actionObj;
    }
  }
}

Sample usage:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
require('Zend.php');

Zend::loadClass('Zend_Controller_Action');
Zend::loadClass('Zend_Controller_Front');
Zend::loadClass('Zend_Filter');
Zend::loadClass('Zend_InputFilter');
Zend::loadClass('Zend_View');

Zend::loadClass('SubDirectoryRouter');

$controller = Zend_Controller_Front::getInstance();
$controller->setControllerDirectory('controllers');

$router = new SubDirectoryRouter();
$controller->setRouter($router);

$controller->dispatch();

To make it work you need to place SubDirectoryRouter to the SubDirectoryRouter.php file and put it under include path.

The post Zend Framework: Router for subdirectory-based site first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/zend-framework-router-for-subdirectory-based-site/feed/ 12
Zend releases first version of Zend Framework https://kpumuk.info/php/zend-releases-first-version-of-zend-framework/ https://kpumuk.info/php/zend-releases-first-version-of-zend-framework/#comments Sat, 04 Mar 2006 11:18:24 +0000 http://kpumuk.info/php/zend-releases-first-version-of-zend-framework/ Finally in the end Zend has released first version of the Zend Framework project. Zend Framework is a high quality and open source framework for developing Web Applications and Web Services. Built in the true PHP spirit, the Zend Framework delivers ease-of-use and powerful functionality. It provides solutions for building modern, robust, and secure websites. […]

The post Zend releases first version of Zend Framework first appeared on Dmytro Shteflyuk's Home.]]>
Finally in the end Zend has released first version of the Zend Framework project.

Zend Framework is a high quality and open source framework for developing Web Applications and Web Services.

Built in the true PHP spirit, the Zend Framework delivers ease-of-use and powerful functionality. It provides solutions for building modern, robust, and secure websites.

First I have observed is it really has powerful functionality. Framework includes classes for working with databases, RSS-feeds, remote HTTP-servers, Web-forms data, JSON, mail, different Web-services (include classes for Amazon, Flickr, and Yahoo), MVC implementation, and also facilities for generating PDF-documents and logging.

This is very serious framework, but I doubt efficiency of it. I don’t want to get just another PEAR library. I will look it more precisely in the near future.

You can download it here.

The post Zend releases first version of Zend Framework first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/zend-releases-first-version-of-zend-framework/feed/ 8