Alex Tech Adventures The webs best tutorials!

Modular application

E-mail Print PDF
(0 votes, average 0 out of 5)

When your site has multiple functionality, like user services and administration, you may want to break them into separate modules. This way you can have library/books/list and admin/book/edit or generally speaking module/controller/action. Addition of module to the URI can be a challenge as modules are outside of the general MVC. Instead, each module has its own independent MVC. In this video I show how to set up such modular structure as well as applying familiar concepts, such as layout and ACL, to this new paradigm.

 

Download source

 

P.S. I had a real hard time uploading this video and I am still not sure if it came out correctly. It suppose to be 48 minutes long. Please report if its broken.

P.P.S By request, here's the SQL for the database. Its very small so i'll just include it here:

-- phpMyAdmin SQL Dump
-- version 3.2.0
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Aug 14, 2009 at 11:42 AM
-- Server version: 5.1.37
-- PHP Version: 5.2.10

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
-- Database: `zftutorial`
--

-- --------------------------------------------------------

--
-- Table structure for table `books`
--

CREATE TABLE IF NOT EXISTS `books` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(50) COLLATE latin1_general_ci NOT NULL,
`author` varchar(100) COLLATE latin1_general_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=5 ;

--
-- Dumping data for table `books`
--

INSERT INTO `books` (`id`, `title`, `author`) VALUES
(1, 'Core PHP Programming', 'Leon Atkinson'),
(2, 'Programming in Python 3', 'Mark Summerfield '),
(3, 'Core Java', 'Cay S. Horstmann and Gary Cornell'),
(4, 'AJAX and PHP: Building Responsive Web Applications', 'Bogdan Brinzarea, Cristian Darie, Filip Chereches-Tosa, Mihai Bucica ');

-- --------------------------------------------------------

--
-- Table structure for table `users`
--

CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) COLLATE latin1_general_ci NOT NULL,
`password` varchar(50) COLLATE latin1_general_ci NOT NULL,
`role` varchar(50) COLLATE latin1_general_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=3 ;

--
-- Dumping data for table `users`
--

INSERT INTO `users` (`id`, `username`, `password`, `role`) VALUES
(1, 'john', 'pass1', 'users'),
(2, 'rob', 'pass2', 'admins');

Last Updated ( Sunday, 23 August 2009 22:34 )  
Discuss (33 posts)
Re:Modular application
Sep 07 2009 17:56:32
Very interesting point. I see how the way its done now can be a problem in regard keeping things organized in terms of per feature (book management, user management) rather than per task (edit, delete, view). Personally, I believe both should be considered. I agree that searching for classes is a pain if, for example as you said, i want to extract my book module alone so others can include it in their application. But while i do that, I also do not want all classes to be all disorganized and not categorized by their tasks. If the module is big then dealing with separate tasks could become a management issue. Furthermore, an admin module is a rather common aspect of web applications (or so i've noticed). I am sure they would welcome a "plugin" that would fit into their existing scheme more naturally. I am not 100% sure if i am making any sense here, but to give a practical idea, look at home joomla extensions have regular files and admin files separated, so that administration backend and user front end of joomla gets the apropriate files without any conflicts.

I agree this is difficult to do in ZF at the moment. There is no true sense of a module the way there is, say, in Java. I think what ZF needs to come up with is a concept of "packaging" the way its done in Java. You package the relevant files to books from library and admin in there so it can be extract the same way elsewhere. To keep track of relevant files need one or both of two things:

1. have an IDE that keeps track of the files as i work by packages. So when i create a package "books" it keeps track of relevant files automatically from library and admin modules. I can then have the IDE put them all in an archive file while preserving directory structure which I can take anywhere and perhaps even use it as an extension or a plugin like in joomla.
2. extend Zend Tool to support concept of a package. Right now we can assign controller to a module. We should be able to asign it to both module and a package for the same purpose: let zend tool isolate the files relevant to a package.

Thats my view on things. I want to continue separating using modules based on tasks (list add edit delete) for organization while using some sort of package management to keep track of related classes. May be someone from Zend will eventually do this (i saw traces of this in their discussions) or may be one day i'll have enough resources and energy to play with this myself
#36
Re:Modular application
Oct 01 2009 00:13:20
Thanks for your fantastic tutorials!

I've been trying to use custom view helpers with a modular layout however have been experiencing problems as my view helpers won't load and produces the following exception message:

Fatal error: Uncaught exception 'Zend_Loader_PluginLoader_Exception' with message 'Plugin by name 'DisplayDate' was not found in the registry

My directory structure is setup the same as yours was at the end of tutorial 10.

The helpers I am trying to load are in:
application/
helpers/
Display-Date.php => Zend_View_Helper_DisplayDate

Any ideas as to what might be going wrong??

Thanks for any help
#75
Re:Modular application
Oct 01 2009 00:52:22
Make sure that the directory with your helpers is in HelperPath.
You can add it to the path using $view->addHelperPath, for example,
$view->addHelperPath('Zend/Dojo/View/Helper/', 'Zend_Dojo_View_Helper');
#77
Re:Modular application
Oct 01 2009 10:17:20
Thanks for the reply.

I figured out the problem. The custom helper was should have been saved in DisplayDate.php rather than Display-Date.php!
#80
Re:Modular application
Oct 07 2009 15:04:26
Today I tried to change to using modules, however I ran into a problem when using forms and models.

I have the following two modules:
- default
- administration

My administration is in fact my backend/admin part of the site. For this part of the site I have some models and some forms. But when I try to load them in the constructor I get the following error:

Code:


Warning: include(C:\xampp\server\application/modules/default/forms//Album.php) [function.include]: failed to open stream: No such file or directory in C:\xampp\server\library\Zend\Loader\Autoloader\Resource.php on line 176

Warning: include() [function.include]: Failed opening 'C:\xampp\server\application/modules/default/forms//Album.php' for inclusion (include_path='C:\xampp\server\application\..\library;C:\xampp\server\library;.;C:\xampp\server\library') in C:\xampp\server\library\Zend\Loader\Autoloader\Resource.php on line 176

Fatal error: Class 'Form_Album' not found in C:\xampp\server\application\modules\administration\controllers\AlbumController.php on line 16



My application.ini:
Code:


[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
phpSettings.date.timezone = "Europe/Amsterdam"
includePaths.library = APPLICATION_PATH "" DIRECTORY_SEPARATOR ".." DIRECTORY_SEPARATOR "library"
bootstrap.path = APPLICATION_PATH "" DIRECTORY_SEPARATOR "Bootstrap.php"
bootstrap.class = "Bootstrap"
resources.frontController.moduleDirectory = APPLICATION_PATH "" DIRECTORY_SEPARATOR "modules"
recources.modules = ""

resources.layout.layout = "layout"
resources.layout.layoutpath = APPLICATION_PATH "" DIRECTORY_SEPARATOR "layouts" DIRECTORY_SEPARATOR "scripts"

resources.db.adapter = "Mysqli"
resources.db.params.host = "localhost"
resources.db.params.username = "root"
resources.db.params.password = ""
resources.db.params.dbname = "test"

router.configurationPath = APPLICATION_PATH "" DIRECTORY_SEPARATOR "configs" DIRECTORY_SEPARATOR "router.xml"

[staging : production]

[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1



My Bootstrap.php (in the application folder) :
Code:


<?php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
__FBTAB__
__FBTAB__protected function _initAutoload()
__FBTAB__{
__FBTAB____FBTAB__$moduleLoader = new Zend_Application_Module_Autoloader(array(
__FBTAB____FBTAB____FBTAB__'namespace'__FBTAB__=> '',
__FBTAB____FBTAB____FBTAB__'basePath'__FBTAB__=> APPLICATION_PATH . '/modules/default'));
__FBTAB____FBTAB__return $moduleLoader;
__FBTAB__}

__FBTAB__protected function _initViewHelpers()
__FBTAB__{
__FBTAB____FBTAB__$this->bootstrap('layout');
__FBTAB____FBTAB__$layout__FBTAB__= $this->getResource('layout');
__FBTAB____FBTAB__$view__FBTAB__= $layout->getView();
__FBTAB____FBTAB__
__FBTAB____FBTAB__$view->doctype('HTML4_STRICT');
__FBTAB____FBTAB__$view->headMeta()->appendHttpEquiv('Content-Type', 'text/html;charset=utf-8');
__FBTAB____FBTAB__$view->headTitle()->setSeparator(' - ');
__FBTAB____FBTAB__$view->headTitle('Test');__FBTAB__
__FBTAB__}
}



And last (the important part of) my controller:
Code:


<?php

class Administration_AlbumController extends Zend_Controller_Action
{

    public function init()
    {
        /* Initialize action controller here */
    }

    public function addAction()
    {
        $this->view->title = 'Add new album';
        $this->view->headTitle($this->view->title, 'PREPEND');
        
        $form = new Form_Album();
        $form->submit->setLabel('add');
        $this->view->form = $form;
        
        if($this->getRequest()->isPost()){
__FBTAB__        $formData = $this->getRequest()->getPost();
__FBTAB__        if($form->isValid($formData)){
__FBTAB____FBTAB__        $artist = $form->getValue('artist');
__FBTAB____FBTAB__        $title = $form->getValue('title');
__FBTAB____FBTAB__        
__FBTAB____FBTAB__        $albums = new Model_DbTable_Albums();
__FBTAB____FBTAB__        $albums->addAlbum($artist, $title);
__FBTAB____FBTAB__        
__FBTAB____FBTAB__        $this->_redirect('/');
__FBTAB__        }else{
__FBTAB____FBTAB__        $form->populate($formData);
__FBTAB__        }
        }
    }
}
?>



I have a few questions concerning this problem:
- how do I get the autoloader to look in the right (modular) directory? I have changed the name of the classes to Administration_Form_Album() and Administration_Model_DbTable_Albums() (als in the controllers code) but this causes the following error to occur:
Code:


Fatal error: Class 'Administration_Form_Album' not found in C:\xampp\server\application\modules\administration\controllers\AlbumController.php on line 16


- Sometimes it comes in handy to use a form or model (or even a view of some sort) to be used by both modules. How can I get this to work? Or do I need to copy things and have double content?

Help is much appreciated.

I wouldn't have come this far without your tutorials though...
#92
Re:Modular application
Oct 08 2009 15:03:48
After quite a lot of research I noticed that the autoloader only works for one module ($namespace is a string, not an array). Which means that if you want another module to also use autoloading you need to set the autoloading for that as well. Therefor I created another _init function which creates the other autoloader for my other module.

Maybe not the nicest way of doing such a thing (it would have been nicer to put both in one function), but this is my code (which is in my general Bootstrap.php in de application directory):

Code:


class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
__FBTAB__
__FBTAB__protected function _initAutoload()
__FBTAB__{
__FBTAB____FBTAB__$moduleLoader = new Zend_Application_Module_Autoloader(array(
__FBTAB____FBTAB____FBTAB__'namespace'__FBTAB__=> '',
__FBTAB____FBTAB____FBTAB__'basePath'__FBTAB__=> APPLICATION_PATH . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'default'));
__FBTAB____FBTAB__return $moduleLoader;
__FBTAB__}
__FBTAB__
__FBTAB__protected function _initSecondAutoload()
__FBTAB__{
__FBTAB____FBTAB__$moduleLoader = new Zend_Application_Module_Autoloader(array(
__FBTAB____FBTAB____FBTAB__'namespace'__FBTAB__=> 'Administration',
__FBTAB____FBTAB____FBTAB__'basePath'__FBTAB__=> APPLICATION_PATH . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'administration'));
__FBTAB____FBTAB__return $moduleLoader;
__FBTAB__}
}

#93
Re:Modular application
Oct 12 2009 15:27:48
Sorry that i am just getting to reply to this.
Your solution seems logical.
However, I may have another idea where the problem is. Did you bootstrap each module individually? You should have a blank Bootstrap.php file in the root of each of the module directories with just
Code:


<?php

class Default_Bootstrap extends Zend_Application_Module_Bootstrap 
{
__FBTAB__
}



If i remember correctly from back when i was doing this video, it is extending Zend_Application_Module_Bootstrap that allows the autoloader to know about other modules too. (correct me if i am wrong).
#97
Re:Modular application
Oct 13 2009 09:34:08
In application/modules/administration:

Code:


<?php

class Administration_Bootstrap extends Zend_Application_Module_Bootstrap {
__FBTAB__
}



And in application/modules/default:

Code:


<?php

class Default_Bootstrap extends Zend_Application_Module_Bootstrap {
__FBTAB__
}



But that didn't work...
#102
Re:Modular application
Nov 08 2009 19:19:05
If someone want to use an alternative for registerNamespace use this code as example:
Code:


__FBTAB__protected function _initAutoloaders()
    {
        $this->getApplication()->setAutoloaderNamespaces(array('Forms_','Blog_',''));
        return $this;
    }

#157
Re:Modular application
Nov 10 2009 03:14:37
The structure that I'm using for my platform is look like this:
Code:


 |-application
 |---admin
 |-----blocks
 |-----elements
 |-----modules
 |-------default
 |---------controllers
 |-----------helpers
 |---------forms
 |-----------configs
 |-----------decorators
 |-----------element
 |-----------helpers
 |---------models
 |---------services
 |---------views
 |-----------filters
 |-----------helpers
 |-----------scripts
 |-------------error
 |-------------index
 |-------------user
 |---configs
 |---public
 |-----modules
 |-------default
 |---------configs
 |---------controllers
 |-----------helpers
 |---------models
 |---------services
 |---------views
 |-----------filters
 |-----------helpers
 |-----------scripts
 |-------------error
 |-------------index
 |-bin
 |-data
 |---cache
 |---captcha
 |-----fonts
 |---indexes
 |---locales
 |---logs
 |---sessions
 |---uploads
 |-docs
 |-library
 |---App
 |-----Controller
 |-------Plugin
 |---------Admin
 |---------Public
 |-----View
 |-------Admin
 |-public
 |---admin
 |-----themes
 |-------full-site
 |---------default
 |-----------css
 |-----------images
 |-------------captcha
 |-----------js
 |-------------ckeditor
 |-------------jQuery
 |---------------Plugins
 |---------------UI
 |-----------------Plugins
 |-----------------themes
 |-----------layouts
 |-------------filters
 |-------------helpers
 |-------------partials
 |-------------scripts
 |-------mobile
 |---------default
 |---css
 |---images
 |---js
 |---layouts
 |-----filters
 |-----helpers
 |-----scripts
 |-scripts
 |---build
 |---jobs
 |-temp
 |-tests
 |---admin
 |-----application
 |-------controllers
 |---public
 |-----application
 |-------controllers



The main folders are consist form:


    application
    bin
    data
    docs
    library
    public
    scripts
    temp
    tests


application folder and public folder I guess that you know why they are for.

bin contains bash scripts, for example I have a script that takes parameters and runs unit testing for the application.

inside data folder I keep cache, captcha fonts, indexes, locales, logs, sessions and uploads.

docs folder contains documentation information.

library folder contains Zend, and ZendX folder with latest ZF and also an App folder with custom things.

scripts folder contains php CLI files mostly used for automated things and for cron jobs.

temp keeps temporary things.

test folder contains phpunit testings.

Inside application folder I have admin folder, configs and public folder.

admin and public are two different zf applications.

configs contains the appliation.ini config file along with some other configs.
#160
Modular application
Nov 11 2009 14:02:06
Great site and tutorials!
How do I get own layouts for each module?
#161
Re:Modular application
Nov 11 2009 14:08:16
You must write your own switch layout plugin.
I made it by this example: _blog.astrumfutura.com/archives/362-Examp...Revised-Styling.html
#162
Modular application
Nov 11 2009 14:19:16
01Kuzma: Thanks for prompt replay!
But isn't little ineffective to have a array run each hit? 99,9% of each the hits will not for the admin layout, just the default..
#163
Re:Modular application
Nov 11 2009 14:21:20
I think you are right.
This solution must be improved
#164
Modular application
Nov 11 2009 15:03:57

Would it not be possible to put each module ACL-settings and layout setting in the own bootstrap.php located in the module folder?
#165
Modular application
Nov 12 2009 03:33:58
I found this post that have a solution there the design is chosen by an own plugin and not in the main bootstrap. I think this should be a better solution, what do you other thinks??

old.nabble.com/Quick-Guide-How-to-use-di...dule-td23443422.html
#167
Re:Modular application
Nov 12 2009 17:53:11
That is so clever!
Code:


$layout->setLayout($request->getModuleName()) 
              ->setLayoutPath(APPLICATION_PATH . '/modules/' . 
                $request->getModuleName() . '/layouts'); 


Thanks, skatan, for sharing
#168
Modular application
Nov 13 2009 15:02:59
I'm glad to make this site even better, great tutorials!

But I still have some efficent performence that I searching for a solution:
I don't know if only my set up that makes all the modules bootstrap-files run for every hit:
The admin-module bootstrap is runing even if I hit the root: www.domain.com
I would like to put my ACL-settings for admin into the admin bootstrap as the same as with layout I see it ineffective to run ACL-settings for admin when 99,99% of all hits is not a admin.

Or I'm thinking wrong and maybe insecure..??

Looking forward for a discussion
#171
Re:Modular application
Nov 13 2009 21:23:53
Unfortunately that is the way Zend_Application works. ZF needs to set up the full environment before it can do any processing of MVC. ZF does this through bootstrap files, hence, it looks at every bootstrap file there is. Due to PHP's unpersistent nature (script does not stay in memory but 'dies') it has to do that on every request. That's the price we have to pay for scripting languages like PHP which are unlike full application servers (like ColdFusion) that store application wide data in memory for long term, instead of per request.

However, I am not sure if ZF works the same way on Zend Server as it does on Apache/PHP. I know it has better integration with Zend_Cache but I never got around to play with it so I cannot tell if it is capable of storing application state in memory like, for example, ColdFusion or JSP.
Can someone give an answer to that??

What I've seen many devs do is to create a separate application altogether for "unrelated" section. For example, admin is very often not a module but a whole different ZF app. Not sure i like that style of organization but it cuts down on security issues(less room for mistakes in setting up complex ACL) and better performance since it does not "interfere" with other parts.
#172
Modular application
Nov 15 2009 12:36:59
#175
Modular application
Nov 20 2009 01:47:07
Is it possible to set a ACL-rule for the hole "default"-module so that I don't need to write rules each and every page/constructor in the Bootstrap? Or how to I make it dynamic, so users could create new pages without consulting with admin for bootstrap-work each time?
#191
Re:Modular application
Nov 29 2009 03:39:36
At the moment thats the only way to go
In passing I've seen some rumors that someone is playing around with the ability to have the whole deal (controller, navigator, acl, action, module etc.) generated in one go from a single configuration in UML or something. Not sure, cannot find it again.
It would be awesome if someday there would actually be a tool that does a lot of this module and ACL work automatically in a more rapid application development like other framework and languages have.
#207
Modular application
Dec 18 2009 16:45:06
thank you soooooooo much, That is great tutorial,
I loved it
I have question I cant understand how did the application call the (login page) authentication/login by default why it is not going to index/index as what its supposed ? I dont know if I missed any thing here please any ideas
#255
Modular application
Dec 18 2009 18:35:23
Ooops I see ,
its in the AccessCheck.php
that is why it goes to the login directly
thanks any way
#256
Re:Modular application
Jan 18 2010 08:35:38
Hello!
I've one problem with modular structure.
I've direcotry tree like this: default/models/Entries.php.
Everything worked fine until I've added a line into my model:
protected $_rowClass=''Entry;
So I'm getting error that Zend can't find Entry.php. It's not searching in default/models/ folder.
I've fixed it by putting entry model into library/entry/db/table/row folder and chaging Entries.php like this:
protected $_rowClass = 'Entry_Db_Table_Row_Entry';
With this fix it's working; maybe you know how to use it in first way?
P.S. As I understand I should point zend to search for models in my custom directory?
Thank you!
#336
There are too many comments to list them all here. See the forum for the full discussion.
You need to login or register to post comments.
Discuss...
You are here: Home Development Zend Framework Modular application

Statistics

Members : 571
Content : 36
Web Links : 1
Content View Hits : 40320

Who's Online

We have 37 guests online