Zend_Db_Select: Select query cannot join with another table

When I executed a query created with Zend_Db_Select in a Zend_Db_Table, I got the following error message:

Select query cannot join with another table

What is happening here? A very simple select statement with a join is not allowed in Zend_Db_Select?
To solve this mysterious matter, I decided to Google the error message, off course. Luckily, one of the first results I got was the Zend Framework manual, a page on Zend_Db_Table. Luckily? Not really, because the documentation only mentions “You can allow JOIN clauses on a select to allow multi-table lookups”. That’s great, but… HOW?

But as always, the documentation comes to the rescue! On the Zend_Db_Select page a comment points in the right direction. There exists an undocumented function “setIntegrityCheck(false)“. And if you see the code of Zend_Db_Table_Select, in the assemble() function, it becomes even more clear: there is indeed a parameter “$_intgrityCheck” that can ensure that selected columns are only from the primary table.

So I pass this function in my Zend_Db_Select statement, and now it is possible to do joins!

View helpers and variables not available in layout

I got a really strange problem while implementing a menu with Zend_Navigation. I added this piece of code in the Bootstrap.php:

    protected function _initNavigation()
    {
        $this->bootstrap('layout');
        $layout = $this->getResource('layout');
        $view = $layout->getView();
        $config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/navigation.ini');
 
        $navigation = new Zend_Navigation($config);
        $view->navigation($navigation);
    }

This is fine for creating a menu or breadcrumbs, but there is one big problem: after this code is in use, all custom variables and the View Helper Include path are not available any more in the layout phtml file.

For example “echo $this->name” just echoes null. Or the custom view helper “$this->myHelper()” cannot be found because the View Helper include path only contains the path to Zend View Helpers.

And writing the same code in the phtml file of a simple action does work!

So what is the relation between the code above and the problems mentioned?

It all starts at the first line of the function “_initNavigation()”: there is a bootstrap function for the layout. Unfortunately it is necessary to add another line to not have the problems above. It is needed to also bootstrap the view! So the code becomes:

    protected function _initNavigation()
    {
        $this->bootstrap('layout');
        $this->bootstrap('view');
        $layout = $this->getResource('layout');
        $view = $layout->getView();
        $config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/navigation.ini');
 
        $navigation = new Zend_Navigation($config);
        $view->navigation($navigation);
    }

Now the layout AND the view are bootstrapped, and the custom view helpers and variables can again be used in the layout phtml file.

I found this interesting issue in the ZF Jira: ZF-9537. It has already been reported, but it is not an issue (see status). So this is supposed to be normal behaviour? Does anyone has a good explanation for this?

Zend Navigation: Breadcrumbs minimum depth

Creating breadcrumbs with Zend Framework is really easy:

  1. Create a menu structure (ini file, php array, …)
  2. add a small peace of code in the view file: “echo $this->navigation()->breadcrumbs()”
  3. open your page and you see… nothing

This is what happened to me on the home page of my most recent project.  All though the ZF manual indicates you just have to echo the breadcrumbs, nothing appeared.

The problem was this: my menu started at level zero, and ZF sets the minimum level that will be displayed to one. Luckily there is the documentation, but it is really annoying that the method “setMinDepth()” is not in the API, so it took me much longer to find out this method existed.

Url view helper

When creating a link in a view file to another page of your application, Zend Framework provides a view helper that is very handy: Zend_View_Helper_Url.

echo $this->url(array(
    'module' => 'abc',
    'controller' => 'def',
    'action' => 'ghi',
    'param1' => '1',
    'param2' => '2'
); // output: "/abc/def/ghi/param1/1/param2/2"

If you don’t provide the module, controller or action, the current module, controller or action will be used as default values.

I think this is a very easy way to create links inside an application, without retyping every time your controllers or actions.

Zend Framework certified!

Zend Framework Certified Engineer LogoToday I passed the Zend Framework certification. From now on I can call myself Zend Framework Certified Engineer.

I followed the Zend Certification training at Ausy/Dataflow. Gauthier Delamarre is an excellent teacher, and he helped me very good to prepare for the examination. Though it is my opinion that with only the training you cannot pass. It requires a lot of experience with the ZF, and you have to study the online reference guide really good.

Some tips for anybody who wants to do the certification:

  • know the output of every function,
  • know which and how many parameters every function requires, but also know the optional parameters,
  • know what happens if something goes wrong (does ZF throw an Exception or do you get a Fatal Error, a warning,…),
  • know the configuration settings (for example Frontend and Backend Caching have a lot of settings),
  • study the reference guide in depth!

var_dump() in Firebug

In my previous post I talked about query profiling in Firebug with FirePHP. Today I will talk about another feature from the Zend Framework and FirePHP: logging.

Again, it’s very simple:

  • create a new Zend_Log
  • add the Zend_Log_Writer_Firebug to it
$log = new Zend_Log();
$log->addWriter(new Zend_Log_Writer_Firebug());
$log->debug($something);

This will behave like var_dump(), with these differences/improvements:

  • the output is displayed in Firebug
  • the HTML output doesn’t change
  • also for Ajax calls; no var_dump() info visible in the output from the Ajax call
  • the output has a nice layout

Remark: to use this, you need Firebug and FirePHP

Quick query checks with Firebug

Firebug gets better and better!
One of my last discoveries is Zend_Db_Profiler_Firebug. With this great feature of the Zend Framework it is possible to check queries in Firebug.
Step 1: install Firebug + FirePHP and activate the Console and Net tab
Step 2: activate Zend_Db_Profiler_Firebug in the application:

resources.db.params.profiler.class = Zend_Db_Profiler_Firebug
resources.db.params.profiler.enabled = true

For example enable it in development environment, and disable it in production.
Step 3: refresh your application, and see the queries appear in Firebug: you see the duration of all queries, and for each query individually, all parameters passed to the query and the total number of queries.

If you don’t want to use MySQL Proxy, this is a good alternative to check queries!

I have no hard data to prove it, but I don’t have the impression that it slows down my applications.
Does anybody know more about the performance of Profiler_Firebug?

Zend Framework: partial() and render()

partial() will render a view script, and render() will render a view script. So… which one do I have to use?

All depends on the variable scope.

Render()

The render() function will render the given view script within the variable scope of the script is was called from.

$this->render('script.phtml');

Partial()

partial() will also render the given view script, but you can define a special variable scope: you can pass all requested parameters in an array.

$this->partial('script.phtml', array('var1' => 'value 1', 'var2' => 'value 2'));

This can be very useful to use a view script in a loop.

Ignore option in Zend_Translate

My project is under version control with SVN. Although SVN is very usefull, it generates a lot of files, and sometimes this makes the performance bad.

Take for instance Zend_Translate. I use Qt to handle all translations. Qt will scan a given directory for all translation files, and so it will also scan all .svn directories.

resources.translate.data = APPLICATION_PATH "/locale"
resources.translate.adapter = Qt
resources.translate.options.scan = directory

While debugging my application, I discovered a very useful option to ignore all .svn directories:

resources.translate.options.ignore = ".svn"

Very useful option.
Off course it is possible to add more directories or files to ignore.

Implementing a menu with Zend_Navigation

A few weeks ago I saw a very good ZendCast about Zend_Navigation.

This was a very good start for me to use Zend_Navigation for the menu and breadcrumbs in my application.

Performance

While developing there were some performance issues that came up:

  1. parsing a .ini or .xml file makes the application slower
  2. for Ajax-requests, the menu should not be loaded

The solution for the first problem is a simple array. I created a function getMenu() that returns a Zend_Navigation object, and this object contains my menu array. The array is less readable than a .ini or .xml file, I have to admit, but it’s still very easy to work with.

private function getMenu()
{
    return new Zend_Navigation(array(
        array(
            'label' => 'Home',
            'id' => 'home',
            'visible' => false,
            'controller' => 'index',
            'action' => 'index'
        ),
        array(
            'label' => 'Page 1',
            'id' => 'page_1',
            'uri' => '',
            'pages' => array(
                array(
                    'label' => 'Page 1.1',
                    'id' => 'page_1_1',
                    'controller' => 'general',
                    'action' => 'index'
                )
            )
        )
    ));
}

For the second problem I had to dig a little bit deeper into Zend Framework.
Normally the Zend_Layout and Zend_View are created in the bootstrap. And this is also the place where I would initialize Zend_Navigation.
For an Ajax request, I disable the layout.

$this->_helper->layout->disableLayout();
$this->getHelper('viewRenderer')->setNoRender();

Does it make sense to first create the layout and view, then add the menu to the view, and afterwards disable the layout if the application do an Ajax request?

My solution was this: I created a plugin for the menu. This plugin checks if the layout is enabled or disabled, and only creates the menu when the layout is enabled. The plugin uses the postDispatch method, because only then the layout can be checked if it is enabled or disabled. In the preDispatch it is always enabled.

public function postDispatch(Zend_Controller_Request_Abstract $request)
{
    $layout = Zend_Layout::getMVCInstance();
    $view = $layout->getView();
 
    if ($layout->isEnabled() && Zend_Auth::getInstance()>hasIdentity()) {
        $view->navigation($this->getMenu());
    }
}

Difference between URI and MVC

This is a very simple difference.

Zend_Navigation_Page_Mvc uses the parameters “controller” and “action” to create the anchors in the menu.
Zend_Navigation_Page_Uri uses the “uri” parameter the create the anchor.

I use only Mvc to create my anchors.
I use the Uri for one case: if I want a menu item that has no anchor. If the “uri” parameter is left blank, Zend_Navigation will display the label, but it will not create anchor tags around it, so you can create a nice menu with menu titles that are not linkable, and menu items with links underneath