Posted by

Blog moved to bsagols.com/blog

Hello all,

If you land here, thanks to google mostly… Know that I’ve moved this blog under my personal domain:

http://bsagols.com/blog/

I didn’t do the proper redirection ’cause it costs 12 $ a year and I don’t see the point paying for this (12 $ (a year !) to put 1 line in an .htaccess file ?!).

So please now follow this blog from the new address.

Cheers,

NB: I may trash this wordpress.com instance of the blog after a while…

Zend Framework rewriting rules explained (.htaccess)

blog has moved

I’ve moved my blog under my personal domain:

http://bsagols.com/blog

I didn’t do the proper redirection ’cause it costs 12 $ a year and I don’t see the point paying for this (12 $ (a year !) to put 1 line in an .htaccess file ?!).

Here is the new URL of this post:

bsagols / blog - Zend Framework rewriting rules explained (.htaccess)

Here follows the original post…

- -

Sometimes (often ?!) you just copy / paste some code without taking time to deeply understand it… I use to do this when I’m running out of time (always ?!)…

This way of doing things is not perennial… At all. The day you will be stuck because you didn’t take that time, always comes.

This is what happened with the rewriting rules of a standard Zend Framework project, I just copied / pasted them.

It worked. Until the day I got stuck. I needed to understand why some requested files were passing though the rewriting logic when others weren’t.

Let’s shade some light on these rewriting rules:

1. RewriteCond %{REQUEST_FILENAME} -s [OR]
2. RewriteCond %{REQUEST_FILENAME} -l [OR]
3. RewriteCond %{REQUEST_FILENAME} -d
4. RewriteRule ^.*$ - [NC,L]
5. RewriteRule ^.*$ index.php [NC,L]

First, let’s see what the REQUEST_FILENAME variable is:

REQUEST_FILENAMEThe full local filesystem path to the file or script matching the request.

Now let’s take the rewriting rules one by one.

1. RewriteCond %{REQUEST_FILENAME} -s [OR]

[ Source: mod_rewrite ]

-s‘ (is regular file, with size)
Treats the TestString as a pathname and tests whether or not it exists, and is a regular file with size greater than zero.

So IF the requested file name is an existing non-empty file on the file system…

2. RewriteCond %{REQUEST_FILENAME} -l [OR]

[ Source: mod_rewrite ]

-l‘ (is symbolic link)
Treats the TestString as a pathname and tests whether or not it exists, and is a symbolic link.

OR is an existing symbolic link on the file system…

3. RewriteCond %{REQUEST_FILENAME} -d

[ Source: mod_rewrite ]

-d‘ (is directory)
Treats the TestString as a pathname and tests whether or not it exists, and is a directory.

OR is an existing directory on the file system…

4. RewriteRule ^.*$ - [NC,L]

Don’t rewrite anything !!

Let’s take a closer look at that line. Why doesn’t it rewrite anything? Because of the special character “-” (dash):

[ Source: RewriteRule directive ]

Syntax: RewriteRule Pattern Substitution [flags]

[ ... ]

Special string ‘-’ (dash) in Substitution means no substitution and is useful when you need to apply the rule while leaving original URL untouched.

This is the behavior we are expecting. If a requested file name complies with one of the above rewrite conditions, we don’t want the rewrite process to occur.

This means that any file, symlink or directory that actually exists in the /public/ folder (root of the webapp…) will be served normally by the Apache server. For instance, all the static resources (css, js, etc…) are located in the /public/ folder…

In addition, the flags [L] indicate that this rewrite rule is the last one to be applied, none will occur after that one, if processed:

[ Source: mod_rewrite ]

last|L‘ (last rule)
Stop the rewriting process here and don’t apply any more rewrite rules. This corresponds to the Perl last command or the break command in C. Use this flag to prevent the currently rewritten URL from being rewritten further by following rules. For example, use it to rewrite the root-path URL (‘/‘) to a real one, e.g., ‘/e/www/‘.

So again, if that rule is processed, it will prevent the following ones in the .htaccess to occur… This flag is interesting in our case, because the following rewrite rule is very generic and we don’t want it to occur always:

5. RewriteRule ^.*$ index.php [NC,L]

This rule means rewrite / re-orient / re-map any request URI coming in (^.*$) to index.php. And as you may know the index.php contains the core logic of a standard Zend Framework MVC project.

Note: The flag [NC] means “no case”:

[ Source: mod_rewrite ]

nocase|NC‘ (no case)
This makes the Pattern case-insensitive, ignoring difference between ‘A-Z’ and ‘a-z’ when Pattern is matched against the current URL.

So what’s important here, is that this last rule applies only if the one just above (line 4.) haven’t occured. Meaning that all the previous conditions (RewriteCond) only apply to the RewriteRule at line 4.

It allows the static resources to be served normally.

Hope that helps someone, somewhere.

PS: Understanding this was not much complicated than reading the official documentation of the mod_rewrite Apache module.

Tagged , ,

Zend_Loader_Autoloader Stand-alone and Modular approaches

blog has moved

I’ve moved my blog under my personal domain:

http://bsagols.com/blog

I didn’t do the proper redirection ’cause it costs 12 $ a year and I don’t see the point paying for this (12 $ (a year !) to put 1 line in an .htaccess file ?!).

Here is the new URL of this post:

bsagols / blog - Zend_Loader_Autoloader Stand-alone and Modular approaches

Here follows the original post…

- -

As I was desperately browsing the web for some information about how to configure the Zend_Loader_Autoloader in stand-alone mode, I found myself a bit confused about the different approaches of the Zend Autoloader.

I’ve identified 3 cases of using the Autoloader:

  1. Stand-alone: Let’s say this is the case when you do not use the MVC model of the Zend Framework, but you need to load classes “on the fly”
  2. Non-modular ZF MVC application
  3. Modular ZF MVC application

These are the 3 cases where the configuration of the Autoloader differs.

Stand-alone

This is the basic configuration of the Autoloader, the fundamental one. You need it to load any class dynamically as long as it is included in your include path.

First, the official Zend documentation is great:

http://framework.zend.com/manual/en/zend.loader.autoloader.html#zend.loader.autoloader.usage

What’s important here: instantiating the Autoloader Singleton…

Zend_Loader_Autoloader::getInstance();

… Does register 2 default namespaces:

  • Zend_
  • ZendX_

So you can load dynamically any class of the Zend library without any additional configuration.

If you wish to add other namespaces to be loaded dynamically, just register them:

$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('Foo_');
$autoloader->registerNamespace('Bar_');
...

Alternatively (this is equivalent) you can configure this in your application.ini file (cleaner, in my opinion):

[ application.ini ]

autoloadernamespaces[] = "Foo_"
autoloadernamespaces[] = "Bar_"
...

Non-modular ZF MVC application

So now that I am able to load any class from my library folder, what about loading classes located in my application folder (models, mappers, forms, etc…) ?

If you follow the standard non-modular structure of a ZF MVC project, the Zend Framework comes with a solution for that. Instead of configuring the (Stand-alone) Autoloader with all these new namespaces:

  • Model
  • Model_DbTable
  • Form_
  • etc…

You can instantiate the Zend_Application_Module_Autoloader which will configure / register automatically these namespaces for you.

Here the official documentation lacks of information, in my opinion… Or, at least, this is what I thought before finding another interesting section in the official Zend Framework documentation:

Autoloading in Zend Framework

And especialy that section, talking about the “Resource Autoloader”:

http://framework.zend.com/manual/en/learning.autoloading.resources.html#learning.autoloading.resources

Zend_Application_Module_Autoloader will look for the standard “Resources” and configure the associated namespaces:

RESOURCE         => NAMESPACE

forms/           => Form
models/          => Model
models/DbTable/  => Model_DbTable
models/mappers/  => Model_Mapper
plugins/         => Plugin
services/        => Service
views/helpers    => View_Helper
views/filters    => View_Filter

Just specify the folder where to look for the standard “Resources” (here APPLICATION_PATH):

[ Bootstrap.php ]

protected function _initAutoloader()
{
   new Zend_Application_Module_Autoloader(array(
      'namespace' => 'Application',
      'basePath'  => APPLICATION_PATH,
   ));
}

Alternatively you can configure this in your application.ini file (this is completely equivalent as long as your Bootstrap.php file is under the APPLICATION_PATH folder):

[ application.ini ]

appnamespace = "Application"

Note: The “Application” namespace is recommended by the official documentation of the Zend Framework.

Behind the scene (application.ini)

The Bootstrap.php (Zend_Application_Bootstrap_Bootstrap) tries to launch an instance of Zend_Application_Module_Autoloader with the following options:

  • namespace is the property “appnamespace” of application.ini (getAppNamespace()…)
  • basePath is under the folder where the Bootstrap.php file is located (dirname($path)…)

[ Zend_Application_Bootstrap_Bootstrap ]

/**
 * Retrieve module resource loader
 *
 * @return Zend_Loader_Autoloader_Resource
 */
 public function getResourceLoader()
 {
    if ((null === $this->_resourceLoader)
    && (false !== ($namespace = $this->getAppNamespace()))
    ) {
       $r    = new ReflectionClass($this);
       $path = $r->getFileName();
       $this->setResourceLoader(new Zend_Application_Module_Autoloader(array(
          'namespace' => $namespace,
          'basePath'  => dirname($path),
       )));
    }
    return $this->_resourceLoader;
 }

Modular ZF MVC application

Configuring the Autoloader for a modular ZF MVC application is just about configuring each module Autoloader independently:

[ Bootstrap.php ]

protected function _initAutoloader()
{
new Zend_Application_Module_Autoloader(array(
 'namespace' => 'Application',
 'basePath'  => APPLICATION_PATH . '/modules/default',
));
new Zend_Application_Module_Autoloader(array(
 'namespace' => 'Admin',
 'basePath'  => APPLICATION_PATH . '/modules/admin',
));
new Zend_Application_Module_Autoloader(array(
 'namespace' => 'Blog',
 'basePath'  => APPLICATION_PATH . '/modules/blog',
));
...
}

Alternatively you can configure this in your application.ini file :

[ application.ini ]

resources.modules[] =

Behind the scene (application.ini)

It loads an instance of Zend_Application_Resource_Modules. Behind the scene, this Application_Resource scans your modules folder, looking for modules.

Let’s say you have the following folder structure:

application/
   modules/
      default/
      admin/
      blog/

1. Zend_Application_Resource_Modules looks for modules

The Zend_Application_Resource_Modules will find 3 modules. For each folder / module, it will look for a Bootstrap.php file containing a _Bootstrap class and instanciate it. So let’s say:

application/
   modules/
      default/
         Bootstrap.php   // Default_Bootstrap extends Zend_Application_Module_Bootstrap

      admin/
         Bootstrap.php   // Admin_Bootstrap extends Zend_Application_Module_Bootstrap

      blog/
         Bootstrap.php   // Blog_Bootstrap extends Zend_Application_Module_Bootstrap

   Bootstrap.php   // Bootstrap extends Zend_Application_Bootstrap_Bootstrap

2. Zend_Application_Module_Bootstrap configures the module Autoloader

This is when instantiating “Default_Bootstrap” that the Autoloader of the “Default” module is loaded / configured (because it extends Zend_Application_Module_Bootstrap…).

By default, it uses the module name as the namespace for the module Autoloader:

[ Zend_Application_Module_Bootstrap ]

/**
 * Get default application namespace
 *
 * Proxies to {@link getModuleName()}, and returns the current module
 * name
 *
 * @return string
 */
 public function getAppNamespace()
 {
    return $this->getModuleName();
 }

The module name being the prefix of the module Bootstrap classname:

[ Zend_Application_Module_Bootstrap ]

 /**
 * Retrieve module name
 *
 * @return string
 */
 public function getModuleName()
 {
    if (empty($this->_moduleName)) {
       $class = get_class($this);
       if (preg_match('/^([a-z][a-z0-9]*)_/i', $class, $matches)) {
          $prefix = $matches[1];
       } else {
          $prefix = $class;
       }
       $this->_moduleName = $prefix;
    }
    return $this->_moduleName;
 }

For example, the “Admin_Bootstrap” classname corresponds to the module name “Admin”. So the Admin_Bootstrap class would launch behind the scene:

new Zend_Application_Module_Autoloader(array(
   'namespace' => 'Admin',
   'basePath'  => APPLICATION_PATH . '/modules/admin',
));

But this is completely transparent…

The special case of the “default” module

In the case of the “Default” module, getModuleName() will return “Default” as the corresponding module name (because classname is Default_Bootstrap). So Zend_Application_Module_Bootstrap will configure the module Autoloader like this:

new Zend_Application_Module_Autoloader(array(
 'namespace' => 'Default',
 'basePath'  => APPLICATION_PATH . '/modules/default',
));

It registers the namespace “Default” for the “default” folder… This is not the namespace we want to use, but “Application” is…

Meaning that trying to load:

// application/modules/default/models/User.php
$user = new Application_Model_User();

… Will fail. If we want this to work, we should prefix all the classes of the “Default” module, with “Default_” instead of “Application_”, but this is not what we want to do. We want the “Default” module to use the namespace “Application”.

A quick workaround (and so far the best and cleanest solution I have found), is to override the getModuleName() method:

[ in Default_Bootstrap extends Zend_Application_Module_Bootstrap ]

public function getModuleName()
{
 return "Application";
}

So it will configure the “Default” module Autoloader like this:

new Zend_Application_Module_Autoloader(array(
 'namespace' => 'Application',
 'basePath'  => APPLICATION_PATH . '/modules/default',
));

And you will be able to load your “Default” classes / Resources as usual:

// application/modules/default/models/User.php
$user = new Application_Model_User();

To sum up

Modular folder structure + Bootstrap files

application/
   modules/
      default/
         Bootstrap.php   // Default_Bootstrap extends Zend_Application_Module_Bootstrap

      admin/
         Bootstrap.php   // Admin_Bootstrap extends Zend_Application_Module_Bootstrap

      blog/
         Bootstrap.php   // Blog_Bootstrap extends Zend_Application_Module_Bootstrap

   Bootstrap.php   // Bootstrap extends Zend_Application_Bootstrap_Bootstrap

Application.ini

; bootstrap
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"

; front controller
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
...

; modules
resources.modules[] =

This is all what you need in order to configure your modular application! All the default namespaces of the Zend Framework are automatically loaded for each module.

I hope this is gonna help somebody somewhere.

cheers.

Zend Framework Style Javascript Redirect

blog has moved

I’ve moved my blog under my personal domain:

http://bsagols.com/blog

I didn’t do the proper redirection ’cause it costs 12 $ a year and I don’t see the point paying for this (12 $ (a year !) to put 1 line in an .htaccess file ?!).

Here is the new URL of this post:

bsagols / blog - Zend Framework Style Javascript Redirect

Here follows the original post…

- -

I wrote a simple javascript function that’s building a default Zend Framework URL and redirect the document to it.

My concern was to be able to send parameters through a javascript redirection to the Zend Framework. Basically instead of appending the parameters in the default way (&param1=value1&param2=…), it builds a compliant Zend Framework URL:

www.example.com/controller/action/param1/value1/param2/value2

Here is the snippet:

function redirect(url, key, value)
{
	if(typeof(key) === 'undefined' && typeof(value) === 'undefined')
	{
		document.location = url;
	}
	else
	{
		/*
		 * Example:
		 * 		- url = www.example.com/key1/value1/key2/value2/
		 * 		- key = "key1"
		 * 		- value = "toto"
		 */
		if(key !== null)
		{
			// index = 15
			var index = url.indexOf('/'+key+'/');

			var url1;
			// case 1: key is already present in URL
			if(index !== -1){

				// iafter = 21 = 15 + 4 ("key1".length) + 2 ("//".length)
				var iafter = index+key.length+2;

				// url1 = www.example.com/key1/
				url1 = url.substr(0, iafter);

				// index2 = 27 = 21 (iafter) + 6 ("value1".length)
				var index2 = url.indexOf('/', iafter);
				if(index2 !== -1){
					// url2 = /key2/value2
					var url2 = url.substring(index2, url.length);
				}
			}
			// case 2: key is not present in URL
			else{
				// url1 = www.example.com/key3/ (let's say key = "key3"...)
				url1 = url + '/'+key+'/';
			}

			// case 1: url = www.example.com/key1/
			// case 2: url = www.example.com/key3/
			url = url1;
		}
		else
		{
			// if there is no "/" at the end of url, add it
			if(url.lastIndexOf('/') != (url.length-1))
				{url += '/';}
		}

		// case 1: url = www.example.com/key1/toto
		// case 2: url = www.example.com/key3/toto
		// case key == null: url = www.example.com/toto
		url += value;
		if(url2){
			// only case 1: url = www.example.com/key1/toto/key2/value2
			url += url2;
		}

		// redirect
		document.location = url;
	}
}

Examples using it:

redirect("www.example.com");

redirect("www.example.com/controller1/action1", "param1", "value1");
// -> www.example.com/controller1/action1/param1/value1

redirect("www.example.com/controller1/action1/param1/value1/param2/value2/", "param1", "newvalue1");
// -> www.example.com/controller1/action1/param1/newvalue1/param2/value2</pre>

A precision, it just covers my needs, you may want to improve it for example passing more than 1 parameter to append / replace…

Hope this kind of help somehow.

Tagged

Thought 0 (The beginning)

blog has moved

I’ve moved my blog under my personal domain:

http://bsagols.com/blog

I didn’t do the proper redirection ’cause it costs 12 $ a year and I don’t see the point paying for this (12 $ (a year !) to put 1 line in an .htaccess file ?!).

Here is the new URL of this post:

bsagols / blog - Thought 0 (The beginning)

Here follows the original post…

- -

Because web sites are getting more and more sophisticated/complicated, what about learning the Unified Modeling Language (UML) ?

http://en.wikipedia.org/wiki/Unified_Modeling_Language

Official site: http://www.uml.org/

And why not get an official certification ??

http://www.omg.org/uml-certification/overview.htm

Tagged ,
Follow

Get every new post delivered to your Inbox.