Zend Framework and DoJo
I pretty much wet my self when ZF announced that they’d be integrating Dojo with the next iteration, and low and behold the first RC was made publicly available a few days ago. I literally dived in head first today, only to find the documentation was some what lacking.
I don’t think the documentation is quite complete, but hats off to ZF for taking a step in the right direction.
Here’s a quick tutorial on using Dojo’s container’s and pane’s with ZF. I’ve added line breaks so it fits into the old blog.
Setting Up
Ok, so you’re first step will be to enable your view to support Dojo.
Download the latest version of Dojo and copy it to your scripts folder (/html/scripts is where I put mine).
Unfortunately some of Dojo’s files don’t work with ZF’s rewrite rules in .htaccess, you’ll need to amend it to look like this.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -f [NC,OR]
RewriteCond %{REQUEST_FILENAME} -d [NC]
RewriteRule .* - [L]
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
This will prevent files that exist in the sites root folder from being re-written to index.php i.e. html files which the Dojo library requires.
Now you’ll need to enable the Dojo through your controller, if you’ve extended Zend_Controller_Action stick this in your init method, else you can just put it in the init method for every controller that requires the Dojo library.
public function init(){
Zend_Dojo::enableView($this->view);
}
In your layout template you will need to add the following lines of code to the head.
isEnabled()){
$this->dojo()->setLocalPath('/scripts/dojo/dojo/dojo.js')
->addStyleSheetModule('dijit.themes.nihilo');
echo $this->dojo();
}
?>
This will add all of the required DoJo JS files and include the theme style sheet you choose, “setLocalPath” is the path to your DoJo.js file in the scripts folder, and “addStyleSheetModule” is the theme you wish to use, you have a choice between nihilo, soria and tundra.
You will also need to add a class to your body with the name of the theme. i.e. if the theme you wish to use is nihilo, you add class=”nihilo” to your body.
Creating a basic CMS frame
The ZF DoJo View Helper has several ways of rendering elements, I’ll be showing you two methods in this example.
Hopefully you’re using Zend Studio for Eclipse and have an index.phtml view ready to edit.
In this we’ll start by creating a borderContainer, this will contain all of your “pane’s”. Pane’s contain content, the borderContainer requires 4 content panes, think of old schools frames, where you have a top pane for your header, left pane for your menu, center pane for your main content and bottom pane for your copyright notices or status messages.
Our first line of code will be
borderContainer()->captureStart('masterLayout', array(
'design' => 'headline',
'persist' => true),
array('style' => 'width: 100%; height: 100%;')
);
?>
This will begin capturing everything we’re about to code into an output buffer, I’m going to demonstrate what I’ve found to be the best way to do this, by relating all of the DoJo Dijit Layout classes to DIV’s it’s the easiest way to understand this all. It’s worth noting that you’ll need to add:
body, html { margin: 0; height: 100%; }
To your CSS to make the border container the height of the page.
You’ll need to create the 4 pane’s for the border container, captureStart and captureEnd are inherited to all of the Dijit layout classes, anyting you output between captureStart and captureEnd will be added to the output buffer. You’re basic 4 content panes will look like this.
contentPane()->captureStart('titlePane', array('region' => 'top'));
// Start title pane capture
?>
My Custom CMS
contentPane()->captureEnd('titlePane');
// End title pane capture and output
?>
contentPane()->captureStart('navPane',
array('region' => 'left',
'splitter' => true, 'orientation' => 'vertical'));
// Start navPane capture
?>
My Nav Pane
contentPane()->captureEnd('navPane');
// End navPane capture and output
?>
contentPane()->captureStart('mainPane',
array('region' => 'center'),
array('style' => 'background-color: white;'));
// Start mainPane capture
?>
This will contain my main content
contentPane()->captureEnd('mainPane');
// End navPane capture and output
?>
contentPane()->captureStart('statusPane',
array('region' => 'bottom'));
// End navPane capture and output
?>
This is my status pane it appears at the bottom.
contentPane()->captureEnd('statusPane');
// End navPane capture and output
?>
You’ll notice that the captureStart method can take 3 arguments.
The first argument is the id of the pane, this will be the same as the ID output in the XHTML.
The econd argument is a config array that will be passed to Dojo, if you’re unsure about what your configuration options are for a particular pane you’re best bet will be to hit The Book Of Dojo if you want to make a pane resizable, you will just need to add ’splitter’ => true, ‘orientation’ => ‘vertical’ where orientation is how you want the resizing bar to appear i.e. at the bottom/top or left/right of the pane. Region dictates where in the borderContainer you want the pane to appear, options are center, left, bottom and top.
The final argument is an array of parameters you want to pass to the html as attributes, i.e. styles, classes etc.
Capture end can only take one argument, and that is the ID of the contentPane you want to stop capturing and output. captureEnd will return the XHTML to output, you can either store this in a variable or echo it, because we’re using output buffering echoing it is the best way.
Finally you’ll want to output everything
borderContainer()->captureEnd('masterLayout'); ?>
Earlier I mentiond it’s easy to relate this to creating DIV’s in XHTML, can you see where I’m coming from now? Your opening DIV’s are your capture start’s and your closing DIV’s are the captureEnd’s as long as you format your template files properly everything should be hunky dory.
Getting a bit more complex with an accordion
One of the nice features of the Dojo library is the accordion, you can add these to panels which looks pretty cool. I’m going to be showing you how to add an accordion to your navPane.
It’s pretty simple, just replace:
My Nav Pane
With:
accordionContainer()->captureStart('navAccordion',
array('duration' => 200),
array('style' => 'width: 200px; height: 300px;'));
// Start accordion capture
?>
accordionPane()->captureStart('accordion1',
array('title' => 'First Accordion'));
// Start first accordion item capture
?>
This is my first accordion content pane
accordionPane()->captureEnd('accordion1');
// End First accordion item capture and output
?>
accordionPane()->captureStart('accordion2',
array('title' => 'Second Accordion'));
// Start first accordion item capture
?>
This is my second accordion content pane
accordionPane()->captureEnd('accordion2');
// End First accordion item capture and output
?>
accordionContainer()->captureEnd('navAccordion');
// End accordion capture and output
?>
This will create an accordion in the navPane you can add as many accordion panes in the accordion container as you like.
That’s pretty much it, you can have a look at the demo here http://sandbox.justanotherdeveloper.co.uk/zend_dojo_layout, I’ll post the full code in a day or two.
Ideally it would be nice to extend the Zend_View and have custom tags and parsing them rather than writing PHP.
July 24, 2008 - 12:02 pm
The demo link is incorrect
Thanks for the tutorial!
July 24, 2008 - 12:43 pm
No probs! The demo link is back up, doesn’t look like ZF likes being in a sub folder
July 30, 2008 - 7:18 pm
Thanks for you effort, i read it carefuly.
Unfortunately i cant make it work!
I wrote your code into my files, and i am getting this error:
Notice: Undefined variable: dojo in C:\wamp\www\zf-tutorial\application\layouts\layout.phtml on line 8
Fatal error: Function name must be a string in C:\wamp\www\zf-tutorial\application\layouts\layout.phtml on line 8
Line 8:
if($dojo()->isEnabled()){
…
Any idea would be appreciated
July 30, 2008 - 7:29 pm
kk i got this one:
it should be if($this->dojo()isEnabled…
Waiting for more blog entries about dojo and ZF
Well done
July 30, 2008 - 7:45 pm
Thanks for the correction Vladimir, looks like every time I make a change in wordpress the code highlighter plugin chops off a significant part of my code! I’ll be coming up with more tutorials soon, I’m working on something at the moment so subscribe, subscribe, subscribe!
August 3, 2008 - 1:35 pm
Thanks for the Tutorial.
Would you mind to publish the full source?
August 21, 2008 - 3:50 pm
Hi, Thanks for the excellent intro to ZF and Dojo. I have built my own dojo layout application, but I am having trouble using dijit.Editor on textareas in a form displayed on a content pane. Any ideas on how to implement this?.
Many thanks
August 28, 2008 - 5:57 pm
Thanks for this great tutorial
I have some problems with .htccess but now it’s ok
August 31, 2008 - 2:49 pm
Good tutorial, thank you!
Is the complete source code avaliable?
September 9, 2008 - 2:10 pm
Nice write-up! It’s good to see people are using this functionality, and playing with the various features.
If you would like to see more and better documentation in the manual, I invite you to join ZF as a contributor to do so.
September 13, 2008 - 10:01 pm
Hi,
For some reason it doesn’t work for me. I cannot make it include the following in the HTML source:
//
It does load Dojo, though. What am I doing wrong?
Thanks.
January 12, 2009 - 5:10 am
You lost me at step 1. I’m a rank beginner at ZF. I’m having a bit of trouble understanding how $this winds through the layout and views. I want to set up dojo just once in int but disabled, and enable it in every controller that needs it. You said “if you extended Zend Controller Action …..” What would that look like and how would it tie in with the rest of the boosraper.
February 11, 2009 - 5:43 pm
Can you do smth about the formatting, it escapes ugly lt and gt, its somehow unreadable.
February 18, 2009 - 7:37 pm
Thank you for the tutorial but due WP notations it’s really hard to read the code you posted. Would you mind to release the full sourcecode?
ty
February 21, 2009 - 11:39 pm
No probs, the post has now been updated with the source code, check the bottom of the post for the link! If any one knows of any plugin to format code for wordpress be my guest!
March 8, 2009 - 9:02 am
excelent post, i couldn’t find the source link to prevent replace escaped chars.
thanks!
March 14, 2009 - 8:12 am
Cool.
Can I get the full source? It will help a lot in my learning with ZF+Dojo.
Thanks a lot.
March 30, 2009 - 9:06 am
This post seems like exactly like what I have been looking for, but the code in the page in unreadable and the sourcecode, despite the authors recent comments, are not included in the article.
BTW if you want a syntax system for wordpress, you might try this one http://wordpress.org/extend/plugins/syntaxhighlighter/
April 23, 2009 - 3:36 pm
Your arrows are being html encoded!
June 19, 2009 - 9:50 pm
Hi,
I cannot read the code in the website either, probably due to bad encoding and the full source is nowhere to be seen on your site. This is exactly the kind of thing I am looking for to get me started. can you post the full code? It would be much appreciated.
Thanks in advance.
JR
August 17, 2009 - 7:47 am
Hi
awesome tutorial and by the look of the demo fantastic.
I have the same issue tho – Can’t read the code and no source files.
Please publish them.
August 24, 2009 - 8:01 pm
I’d love to see the source code associated with this tutorial as well.
Thanks in advance.
September 2, 2009 - 4:11 pm
Hi,
what is the problem to publish the complete code?
Thanks!
September 5, 2009 - 6:21 pm
doctype() ?>
headTitle() ?>
headMeta() ?>
headStyle() ?>
headLink()->prependStylesheet($this->baseUrl().’/css/style.css’); ?>
dojo()->isEnabled())
{
echo “DOJO enable”;
$this->dojo()->setLocalPath($this->baseUrl().’/js/dojo/dojo/dojo.js’)
->requireModule(‘dijit.layout.ContentPane’)
->requireModule(‘dijit.layout.AccordionContainer’)
->requireModule(‘dijit.layout.BorderContainer’)
->requireModule(‘dojo.parser’)
->addStyleSheetModule(‘dijit.themes.tundra’);
echo $this->dojo();
}else
{
echo “DOJO disabled”;
}
?>
headScript() ?>
borderContainer()->captureStart(‘masterLayout’, array(
‘design’ => ‘headline’,
‘persist’ => true),
array(’style’ => ‘width: 100%; height: 100%;’)
);
?>
contentPane()->captureStart(‘titlePane’, array(‘region’ => ‘top’));
// Start title pane capture
?>
My Custom CMS
contentPane()->captureEnd(‘titlePane’);
// End title pane capture and output
?>
contentPane()->captureStart(‘navPane’,
array(‘region’ => ‘left’,
’splitter’ => true, ‘orientation’ => ‘vertical’));
// Start navPane capture
?>
accordionContainer()->captureStart(‘navAccordion’,
array(‘duration’ => 200),
array(’style’ => ‘width: 200px; height: 300px;’));
// Start accordion capture
?>
accordionPane()->captureStart(‘accordion1′,
array(‘title’ => ‘First Accordion’));
// Start first accordion item capture
?>
This is my first accordion content pane
navigation(); ?>
accordionPane()->captureEnd(‘accordion1′);
// End First accordion item capture and output
?>
accordionPane()->captureStart(‘accordion2′,
array(‘title’ => ‘Second Accordion’));
// Start first accordion item capture
?>
This is my second accordion content pane
accordionPane()->captureEnd(‘accordion2′);
// End First accordion item capture and output
?>
accordionContainer()->captureEnd(‘navAccordion’);
// End accordion capture and output
?>
contentPane()->captureEnd(‘navPane’);
// End navPane capture and output
?>
contentPane()->captureStart(‘mainPane’,
array(‘region’ => ‘center’),
array(’style’ => ‘background-color: white;’));
// Start mainPane capture
?>
This will contain my main content
layout()->content; ?>
contentPane()->captureEnd(‘mainPane’);
// End navPane capture and output
?>
contentPane()->captureStart(’statusPane’,
array(‘region’ => ‘bottom’));
// End navPane capture and output
?>
This is my status pane it appears at the bottom.
contentPane()->captureEnd(’statusPane’);
// End navPane capture and output
?>
borderContainer()->captureEnd(‘masterLayout’);
?>
<!–
My Custom CMS
This is my first accordion content pane
navigation(); ?>
This is my second accordion content pane
This will contain my main content
layout()->content; ?>
This is my status pane it appears at the bottom.
–>
September 5, 2009 - 6:27 pm
doctype() ?>
headTitle() ?>
headMeta() ?>
headStyle() ?>
headLink()- >prependStylesheet($this->baseUrl ().’/css/style.css’); ?>
dojo()->isEnabled())
{
echo “DOJO enable”;
$this->dojo()->setLocalPath($this->baseUrl().’/js/dojo/dojo/dojo.js’)
->requireModule(‘dijit.layout.ContentPane’)
->requireModule(‘dijit.layout.AccordionContainer’)
->requireModule(‘dijit.layout.BorderContainer’)
->requireModule(‘dojo.parser’)
->addStyleSheetModule(‘dijit.themes.tundra’);
echo $this->dojo();
}else
{
echo “DOJO disabled”;
}
?>
headScript() ?>
borderContainer()->captureStart(‘masterLayout’, array(
‘design’ => ‘headline’,
‘persist’ => true),
array(’style’ => ‘width: 100%; height: 100%;’)
);
?>
contentPane()->captureStart(‘titlePane’, array(‘region’ => ‘top’));
// Start title pane capture
?>
My Custom CMS
contentPane()->captureEnd (‘titlePane’);
// End title pane capture and output
?>
contentPane()->captureStart(‘navPane’,
array(‘region’ => ‘left’,
’splitter’ => true, ‘orientation’ => ‘vertical’));
// Start navPane capture
?>
accordionContainer()->captureStart(‘navAccordion’,
array(‘duration’ => 200),
array(’style’ => ‘width: 200px; height: 300px;’));
// Start accordion capture
?>
accordionPane()->captureStart(‘accordion1′,
array(‘title’ => ‘First Accordion’));
// Start first accordion item capture
?>
This is my first accordion content pane
navigation(); ?>
accordionPane()->captureEnd(‘accordion1′);
// End First accordion item capture and output
?>
accordionPane()->captureStart(‘accordion2′,
array(‘title’ => ‘Second Accordion’));
// Start first accordion item capture
?>
This is my second accordion content pane
accordionPane()->captureEnd(‘accordion2′);
// End First accordion item capture and output
?>
accordionContainer()->captureEnd(‘navAccordion’);
// End accordion capture and output
?>
contentPane()->captureEnd(‘navPane’);
// End navPane capture and output
?>
contentPane()->captureStart(‘mainPane’,
array(‘region’ => ‘center’),
array(’style’ => ‘background-color: white;’));
// Start mainPane capture
?>
This will contain my main content
layout()->content; ?>
contentPane()->captureEnd(‘mainPane’);
// End navPane capture and output
?>
contentPane()->captureStart(’statusPane’,
array(‘region’ => ‘bottom’));
// End navPane capture and output
?>
This is my status pane it appears at the bottom.
contentPane()->captureEnd(’statusPane’);
// End navPane capture and output
?>
borderContainer()->captureEnd(‘masterLayout’);
?>
i am doing something wrong the dojo layout doesnt show up
any ideas
October 21, 2009 - 9:10 pm
Very Good article!
I need full code. Please, sent me!?
thanks
February 5, 2010 - 11:41 pm
Hi,
I miss the first chars on every line in your source?
I see:
doctype() ?>
But I think it must be:
echo $this->doctype() ?>
What happened? I tried in Firefox and IE.