PHP | 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
Correct Last-Modified header processing https://kpumuk.info/php/correct-last-modified-header-processing/ https://kpumuk.info/php/correct-last-modified-header-processing/#comments Mon, 10 Apr 2006 20:54:25 +0000 http://kpumuk.info/php/correct-last-modified-header-processing/ This is quick post about Last-Modified header. Please imagine following situation: you have image stored in your database and you need to send it to the browser on some request. But image extraction from database takes some time, and if there are more than one image you Web-server’s productivity will decrease dramatically. Is this case […]

The post Correct Last-Modified header processing first appeared on Dmytro Shteflyuk's Home.]]>
This is quick post about Last-Modified header. Please imagine following situation: you have image stored in your database and you need to send it to the browser on some request. But image extraction from database takes some time, and if there are more than one image you Web-server’s productivity will decrease dramatically. Is this case you need to implement caching functionality in your application. All images can be changed therefor you need to have ability to check image modified date (for example, this date can be stored in same database).

Every browser has its own cache, and if you will send right Cache-Control header, your image will be cached for some time. After cache time expiring browser will send request to your application to get fresh version of image. But if your image was not updated you can send 304 code in response to tell browser about this. Look at the following code snippet:

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
// --- Your code ---

// You need past following before any output

// here you need to select modified date from DB in UNIX timestamp format
// (same as time() function in PHP or UNIX_TIMESTAMP() function in MySQL)
$date = time();

$last_modified = gmdate('D, d M Y H:i:s', $date) . ' GMT';
// did the browser send an if-modified-since request?
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
  // parse header
  $if_modified_since = preg_replace('/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE']);

  if ($if_modified_since == $last_modified) {
    // the browser's cache is still up to date
    header('HTTP/1.0 304 Not Modified');
    header('Cache-Control: max-age=86400, must-revalidate');
    exit;
  }
}

header('Cache-Control: max-age=86400, must-revalidate');
header('Last-Modified: ' . $last_modified);

// --- Your code ---

In this code I check HTTP_IF_MODIFIED_SINCE request variable which will be sent by browser when cache is expired. If image was not modified, special header will be sent. Default cache period in this sample is 24 hours (86400 seconds). This is very simple and powerful issue which can be used in your Web-application as-is to increase perfomance.

Hint: you can create static-like URLs using following lines in .htaccess file (mod_rewrite):

1
2
RewriteEngine On
RewriteRule ^image_([0-9]+).php$ getimage.php?image=$1 [L]

In this case your images will have URLs like http://example.com/image_10.php, and all request will be redirected to getimage.php with parameter image=10.

Useful links

The post Correct Last-Modified header processing first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/correct-last-modified-header-processing/feed/ 12
Zend Framework: Thoughts about Zend_Config https://kpumuk.info/php/zend-framework-thoughts-about-zend_config/ https://kpumuk.info/php/zend-framework-thoughts-about-zend_config/#comments Fri, 10 Mar 2006 08:48:44 +0000 http://kpumuk.info/php/zend-framework-thoughts-about-zend_config/ In Zend Framework’s mailing list discussion about Zend_Config class is in full swing. I have my own ideas about this class and I will try to explain their here. I need something that can load and save configuration into different storages (for example, XML, database or plain text like INI-files), it’s necessary to have ability […]

The post Zend Framework: Thoughts about Zend_Config first appeared on Dmytro Shteflyuk's Home.]]>
In Zend Framework’s mailing list discussion about Zend_Config class is in full swing. I have my own ideas about this class and I will try to explain their here. I need something that can load and save configuration into different storages (for example, XML, database or plain text like INI-files), it’s necessary to have ability to change every parameter of storage (for example, file name, database tables or even database structure), it will be able if I can extend storage system with my own storage strategies.

First I’ll try to imagine how user’s code will look:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Zend::loadClass('Config');

// Use default XML-persistence engine
$config = new Config('config.xml');

// Use plain text storage engine
Zend::loadClass('Config_Text_Storage');
$persistance = new Config_Text_Persistance('config.ini');
$config->setPersistance($persistance);

echo 'Host: ' . $config->database->host->value . '<br/>';
echo 'Port: ' . $config->database->host->port . '<br/>';
echo 'Database: ' . $config->database->name . '<br/>';
echo 'User: ' . $config->database->user . '<br/>';
echo 'Password: ' . $config->database->password . '<br/>';

I think configuration representation in memory will be objects tree. Config will be user friendly class with several simple functions like load, save configuration, change persistance engine, access root node of configuration object.

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
/** Exception for Config class. */
require_once 'Config/Exception.php';

/** Exception for Config class. */
require_once 'Config/Persistance/Interface.php';

class Config
{
  private $_persistance = null;

  private $_rootNode = null;

  /**
   * Create configuration object. You can pass string argument with
   * path to XML configuration file.
   *
   * @param string $xmlConfigPath
   */

  public function __construct($xmlConfigPath = null)
  {
    require_once 'Config/XML/Persistance.php';
    $this->_persistance = new Config_XML_Persistance($xmlConfigPath);

    if ($xmlConfigPath) $this->load();
  }

  /** Save configuration. */
  public function save()
  {
    $this->checkPersistanceAssigned();
    $this->_persistance->save();
  }

  /** Load configuration */
  public function load()
  {
    $this->checkPersistanceAssigned();
    $this->_persistance->load();
    $this->_rootNode = $this->_persistance->getRootNode();
  }

  /**
   * Get config variable with $name name.
   *
   * @param string $name
   * @return mixed
   */

  public function __get($name)
  {
    return $this->_rootNode->__get($name);
  }

  /**
   * Set persistance object.
   *
   * @param Config_Persistance_Interface $persistance
   */

  public function setPersistance(Config_Persistance_Interface $persistance)
  {
    $this->_persistance = $persistance;
  }

  /** Check if persistance object has been assigned. */
  private function checkPersistanceAssigned()
  {
    if (!$this->_persistance) throw new Config_Exception('No configuration persistance object assigned');
  }
}

Configuration nodes are very easy to code:

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
<?php

class Config_Node
{
  private $_values;

  public function __construct($root = null)
  {
    $this->_values = $root;
  }

  public function __get($name)
  {
    if (array_key_exists($name, $this->_values) === false)
      throw new Config_Exception('No config node "' . $name . '" defined.');

    if (is_object($this->_values[$name])
      && sizeof($this->_values[$name]->_values) == 1
      && array_key_exists('value', $this->_values[$name]->_values))
    {
      return $this->_values[$name]->__get('value');
    }

    return $this->_values[$name];
  }

  public function __set($name, $value)
  {
    $this->_values[$name] = $value;
  }
}

Now I’ll try to develop simplest strategy for XML-based storage.

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
/** Exception for Config_XML_Persistance class. */
require_once 'Config/XML/Exception.php';

/** Interface Config_Persistance_Interface. */
require_once 'Config/Persistance/Interface.php';

/** Configuration node class Config_Node. */
require_once 'Config/Node.php';

class Config_XML_Persistance implements Config_Persistance_Interface
{
  private $_xmlConfigFile = null;
  private $_rootNode = null;

  public function __construct($xmlConfigFile = null)
  {
    $this->_xmlConfigFile = $xmlConfigFile;
  }

  /** Load configuration from XML file. */
  public function load()
  {
    if (!$this->_xmlConfigFile)
      throw new Config_XML_Exception('Config file name is not assigned.');

    $dom = new DOMDocument();
    $dom->preserveWhiteSpace = false;
    $dom->load($this->_xmlConfigFile);

    $this->_rootNode = $this->populateConfig($dom->documentElement);
  }

  /** Save configuration to XML file. */
  public function save()
  {
    throw new Config_XML_Exception('save() function is not implemented for this persistance type.');
  }

  /** Returns root configuration node. */
  public function getRootNode()
  {
    return $this->_rootNode;
  }

  /**
   * Read nodes starting from $root and fill Config_Node objects.
   * Returns root Config_Node object.
   *
   * @param DomNode $root
   * @return Config_Node
   */

  private function populateConfig($root)
  {
    $configNode = new Config_Node();
    foreach ($root->attributes as $attribute)
      $configNode->__set($attribute->name, $attribute->nodeValue);

    foreach ($root->childNodes as $node)
    {
      if ($node->nodeType === 1)
        $configNode->__set($node->tagName, $this->populateConfig($node));
      else
        $configNode->__set('value', $node->nodeValue);
    }
    return $configNode;
  }
}

Here simple configuration XML-file:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>

<config>
  <database type="mysql">
    <host port="3306">localhost</host>
    <name>test</name>
    <user>root</user>
    <password>123456</password>
  </database>
</config>

You can see one obscure aspect of the configuration node class. Please look at host node of configuration: we have an attribure and text node in it. What about ambiguity? How we can access text node? We can’t do following:

1
2
$host = $config->database->host;
$host = $config->database->host->port;

My solution for this problem is pseudo-variable value:

1
2
$host = $config->database->host->value;
$host = $config->database->host->port;

If there are no attributes, pseudo-variable value will be used by default.

You can download my configuration classes here.

The post Zend Framework: Thoughts about Zend_Config first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/zend-framework-thoughts-about-zend_config/feed/ 5
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
How to force Zend Studio to use Russian language interface https://kpumuk.info/php/how-to-force-zend-studio-to-use-russian-language-interface/ https://kpumuk.info/php/how-to-force-zend-studio-to-use-russian-language-interface/#comments Tue, 07 Mar 2006 05:12:59 +0000 http://kpumuk.info/php/how-to-force-zend-studio-to-use-russian-language-interface/ By default Zend Studio does not allow to change interface language to Russian. I found simple trick to do so. Go to the config folder (config_5.0 for Zend Studio 5.0 and config_5.1 for 5.1 version). This folder usually placed under c:Documents and Settings<Your Current User>ZDE. Then open desktop_options.xml file and find following strings: 123<customized_property ID="desktop.language"> […]

The post How to force Zend Studio to use Russian language interface first appeared on Dmytro Shteflyuk's Home.]]>
By default Zend Studio does not allow to change interface language to Russian. I found simple trick to do so. Go to the config folder (config_5.0 for Zend Studio 5.0 and config_5.1 for 5.1 version). This folder usually placed under c:Documents and Settings<Your Current User>ZDE.

Then open desktop_options.xml file and find following strings:

1
2
3
<customized_property ID="desktop.language">
    <locale language="en" country="" variant=""/>
</customized_property>

You need just to change language attribute to ru and country attribute to RU. That’s All!

The post How to force Zend Studio to use Russian language interface first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/how-to-force-zend-studio-to-use-russian-language-interface/feed/ 36
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
AJAX-enabled Smarty plugins Part 2: ajax_form https://kpumuk.info/php/ajax-enabled-smarty-plugins-part-2-ajax_form/ https://kpumuk.info/php/ajax-enabled-smarty-plugins-part-2-ajax_form/#comments Tue, 21 Feb 2006 07:47:28 +0000 http://kpumuk.info/ajax/ajax-enabled-smarty-plugins-part-2-ajax_formajax-%d0%bf%d0%bb%d0%b0%d0%b3%d0%b8%d0%bd%d1%8b-%d0%b4%d0%bb%d1%8f-smarty-%d1%87%d0%b0%d1%81%d1%82%d1%8c-2-ajax_form/ In my previous post I’ve described several simple AJAX plugins. Now I’ll show how to use one of them — ajax_form — in real applications. I think this is the most powerful plugin therefor I’ll dwell on it more elaborately. Most of Web-forms has variuos validation mechanisms. Simplest way is to process form on the […]

The post AJAX-enabled Smarty plugins Part 2: ajax_form first appeared on Dmytro Shteflyuk's Home.]]>
In my previous post I’ve described several simple AJAX plugins. Now I’ll show how to use one of them — ajax_form — in real applications. I think this is the most powerful plugin therefor I’ll dwell on it more elaborately.

Most of Web-forms has variuos validation mechanisms. Simplest way is to process form on the server and parse result on client, where return data can be in following format:

1
2
true;User was registered successfully;http://example.com/login/
false;Please enter your name;Entered passwords doesn't match

Result string can be splitted on client and results can be shown in some part of page. Process function may looks like following (it’s part of smarty_ajax):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var SmartyAjax = {
  onSubmit: function(originalRequest) {
    var results = originalRequest.responseText.split(";");

    if (results[0] == "true") {
      SmartyAjax.Messages.set(results[1],
        SmartyAjax.Messages.MT_WARNING)
    } else {
      SmartyAjax.Messages.clear();
      SmartyAjax.Messages.setType(SmartyAjax.Messages.MT_ERROR);
      for (var i = 1; i < results.length; i++) {
        SmartyAjax.Messages.add(results[i]);
      }
    }
  }
}

This function uses several functions from SmartyAjax.Messages object which depends on following HTML elements:

1
2
3
4
<div id="messages">
  <p id="messages-title"></p>
  <ul id="messages-list"></ul>
</div>

To manage messages I’ve created Smarty template parts/warnings.tpl. You can use it in your PHP file in simple way:

1
2
3
4
// is messages contains warning (or error)
$t->assign('messages_warning', true);
// array of messages
$t->assign('messages', array('Please provide your account information'));

Another thing we need to examine is message which informs user about processing AJAX request. There is SmartyAjax.Process object in the sample which has two methods: hide() and show() which can be used to hide and display message. They are depends on HTML-element with id=”ajax-process”. It’s necessary to add “position: absolute” style because of this messages will be shown in top-right corner of screen independing on scroll position.

ajax_form is simple to use:

1
2
3
{ajax_form method="post" id="form_register"}
Any form-element can be placed here
{/ajax_form}

Possible parameters:

  • url – URL for AJAX-query (when no URL was specified current one will be used)
  • method – query method (by default get, can be get or post)
  • params – URL-encoded parameters
  • id – form ID
  • callback – JavaScript function which will be called when query will be completed

Example can be found here, and full sources can be downloaded here.

The post AJAX-enabled Smarty plugins Part 2: ajax_form first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/ajax-enabled-smarty-plugins-part-2-ajax_form/feed/ 52
AJAX-enabled Smarty plugins https://kpumuk.info/php/ajax-enabled-smarty-plugins/ https://kpumuk.info/php/ajax-enabled-smarty-plugins/#comments Sat, 18 Feb 2006 23:49:25 +0000 http://kpumuk.info/ajax/ajax-enabled-smarty-pluginsajax-%d0%bf%d0%bb%d0%b0%d0%b3%d0%b8%d0%bd%d1%8b-%d0%b4%d0%bb%d1%8f-smarty/ Today I’ve created simple AJAX-enabled plugins for Smarty. I don’t try to develop powerful reach-applications framework. I can give you only idea how to integrate AJAX-technology into Smarty. But if you have any offers how to improve anything I’ve described or if you just want to leave feedback please post you comments on my site. […]

The post AJAX-enabled Smarty plugins first appeared on Dmytro Shteflyuk's Home.]]>
Today I’ve created simple AJAX-enabled plugins for Smarty. I don’t try to develop powerful reach-applications framework. I can give you only idea how to integrate AJAX-technology into Smarty. But if you have any offers how to improve anything I’ve described or if you just want to leave feedback please post you comments on my site.

In my practice I need several things from AJAX: to update some nodes in DOM, to send forms without post-back, to retrieve some values or to perform server-side calculation (maybe using database or other server-side resources). It’s necessary to write tons of JavaScript to implement my requirements in spite of using cool JavaScript library Prototype.

I decided to integrate Smarty with AJAX. There are three Smarty plugins has been created: ajax_update, ajax_call, ajax_form. Below all this plugins will be described.

ajax_update

This Smarty function can be used for update some parts of web-page.

Sample usage:

1
2
<a href="#" onclick="{ajax_update update_id='intro_content'
  function='update_intro' params='page=about'}"
>About</a>

Possible parameters:

  • url – URL for AJAX-query (when no URL was specified current one will be used)
  • method – query method (by default get, can be get or post)
  • update_id – ID of HTML element for update
  • function – function which will be called
  • params – URL-encoded parameters

ajax_call

This Smarty function can be used for call PHP function on server side and retrieve its output.

Sample usage:

1
2
<a href="#" onclick="{ajax_call function='calculate'
  params_func='calc_params' callback='calc_cb'}"
>Calculate</a>

Possible parameters:

  • url – URL for AJAX-query (when no URL was specified current one will be used)
  • method – query method (by default get, can be get or post)
  • function – function which will be called
  • params – URL-encoded parameters
  • callback – JavaScript function which will be called when query will be completed
  • params_func – JavaScript function used when you need custom parameters calculated on client side

ajax_form

This Smarty block can be used for submit Web-forms without post-back.

Sample usage:

1
2
3
{ajax_form method="post" id="form_register"}
Any form-element can be placed here
{/ajax_form}

Possible parameters:

  • url – URL for AJAX-query (when no URL was specified current one will be used)
  • method – query method (by default get, can be get or post)
  • params – URL-encoded parameters
  • id – form ID
  • callback – JavaScript function which will be called when query will be completed

Samples

These plugins are quite simple and I think everyone can create even better than mine. I’ve just wanted to show you idea how integration can be done. Working examples can be found here. Also you can download full sources.

The post AJAX-enabled Smarty plugins first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/ajax-enabled-smarty-plugins/feed/ 71
dBug – Impoved var_dump for PHP https://kpumuk.info/php/dbug/ https://kpumuk.info/php/dbug/#comments Thu, 09 Feb 2006 17:17:31 +0000 http://kpumuk.info/php/dbug/ Today I found very useful tool for PHP – dBug. I think every PHP-programmer uses var_dump or print_r functions for debugging purpose very often. dBug displays structured information about your variables like these functions but in more suitable way (in colored tabular format). Full features list with the examples of work can be found on […]

The post dBug – Impoved var_dump for PHP first appeared on Dmytro Shteflyuk's Home.]]>
Today I found very useful tool for PHP – dBug. I think every PHP-programmer uses var_dump or print_r functions for debugging purpose very often. dBug displays structured information about your variables like these functions but in more suitable way (in colored tabular format).

Full features list with the examples of work can be found on original site.

dBug - Impoved var_dump for PHP

The post dBug – Impoved var_dump for PHP first appeared on Dmytro Shteflyuk's Home.]]>
https://kpumuk.info/php/dbug/feed/ 5