Posts Tagged ‘ ZendFramework

Zend Framework与Dojo联用开发RIA

一、Dojo 入门简介:

随着富互联网应用程序(Rich Internet Application,RIA)的发展,一批 JavaScript Toolkit 也随之兴起 , Dojo 便是其中的优秀代表,本系列文章将由浅入深带领读者走进 Dojo 的世界。本文作为这个系列的开篇 , 主要讲述了 Dojo 的体系架构以及如何安装使用。

伴随 Web 2.0, Ajax 和 RIA 的热潮,各种 Ajax 开发工具包如雨后春笋般蓬勃发展,Dojo 正是这些工具包中的佼佼者。Dojo 为富互联网应用程序(RIA) 的开发提供了完整的端到端的解决方案,包括核心的 JavaScript 库,简单易用的小部件(Widget)系统和一个测试框架,此外,Dojo 的开源开发社区还在不停地为它提供新的功能。

Dojo 是一个 JavaScript 实现的开源 DHTML 工具包。它是在几个项目捐助基础上建立起来的(nWidgets,f(m),Burstlib) 。 Dojo 的最初目标是解决开发 DHTML 应用程序遇到的一些长期存在的历史问题,现在,Dojo 已经成为了开发 RIA 应用程序的利器:

  • Dojo 让您更容易地为 Web 页面添加动态能力,您也可以在其它支持 JavaScript 的环境中使用 Dojo ;
  • 利用 Dojo 提供的组件,您可以提升 Web 应用程序的可用性和交互能力;
  • Dojo 很大程度上屏蔽了浏览器之间的差异性,因此,您可以不用担心 Web 页面是否在某些浏览器中可用;
  • 通过 Dojo 提供的工具,您还可以为代码编写命令行式的单元测试代码。
  • Dojo 的打包工具可以帮助您优化 JavaScript 代码,并且只生成部署应用程序所需的最小 Dojo 包集合。

接下来,我们看看 Dojo 是如何组织这些功能组件的。 阅读全文

Zend Framework 体系结构图

Zend Framework Zend_Validate_Date 验证方法

默认格式为 月/日/年 m/d/Y
$v = new Zend_Validate_Date();

自订日期格式
$v = new Zend_Validate_Date('d-F-Y');

自订日期格式+起始日期
$v = new Zend_Validate_Date('d-F-Y', '06-September-2007');

自订日期格式+截止日期
$v = new Zend_Validate_Date('d-F-Y', null, '06-September-2007');

Instantiating the validator with a custom date format and a start date of whatever day it is
$v = new Zend_Validate_Date('d-F-Y', Zend_Validate_Date::TODAY);

自订日期格式+起始日期+截止日期
$v = new Zend_Validate_Date('M-d-Y', 'Sep-01-2007', 'Sep-30-2007');

中国时间写法

$v = new Zend_Validate_Date('Y-m-d');

$v = new Zend_Validate_Date('Y-m-d', '2007-09-23');

$v = new Zend_Validate_Date('Y-m-d', '2007-09-23', '2008-09-23');

判断方法:

if($v->isValid($your_date))

Zend Framework 页面布局

Zend Framework 的页面布局模块——Zend_Layout——既可以跟 MVC 一起使用,也可以单独使用。本文只讨论与 MVC 一起使用的情况。

1. 布局脚本

在 application/views 下创建一个 layouts 的文件夹。主布局脚本 layout.phtml 代码如下:

<?php echo $this->doctype(‘XHTML1_STRICT’) ?>
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<?php echo $this->headTitle() ?>
<?php
$this->headLink()->appendStylesheet(“/styles/main.css”);
// add more links …
?>
<?php echo $this->headLink() ?>
</head>
<body>
<div id=”header”>
<?php echo $this->partial(‘header.phtml’) ?>
</div>
<table>
<tr>
<td valign=top>
<div id=”leftcolumn”>
<?php echo $this->partial(‘leftcolumn.phtml’) ?>
</div>
</td>
<td valign=top>
<div id=”content”>
<?php echo $this->layout()->content ?>
</div>
</td>
</tr>
</table>
<div id=”footer”>
<?php echo $this->partial(‘footer.phtml’) ?>
</div>
</body>
</html>

除了 layout.phtml 之外,还需要编写 header.phtml,leftcolumn.phtml,footer.phtml,以及 main.css 等文件。

Zend Framework 的文档中用一个视图表示了页面布局的应用。

2. 设置页面布局

在 MVC 下设置页面布局非常简单,编辑 html/index.php,加入下面两行代码:

/** Setup layout */
require_once ‘Zend/Layout.php’;
Zend_Layout::startMvc($rootPath . ‘/application/views/layouts’);

注意:在启动页面布局后,要调整已有的各个页面,把不需要的 html 元素,如<header> <title> <body> 等去掉。另外,可以通过 $this->headTitle() 来设置页面的题头。

改变页面的布局也很简单,只需在控制器中用下面的代码即可:

$this->_helper->layout->setLayout(‘new_layout’);

如果一个控制器所有动作都使用同一个页面布局,可以通过控制器的初始化函数来设置:

public function init() {
parent::init();

$this->_helper->layout->setLayout(‘new_layout’);
}

Zend Framework 多国语言支持

如果你的项目想要支持多语言版本,那么就需要用到 Zend_Translate。Zend_Translate 的详细文档在这里,不过如果想偷懒的话,也很简单,在 View Helpers 文档中介绍了如何用 Translate Helper 轻松实现多语言支持。

1. 准备翻译文件

Zend_Translate 支持多种格式的翻译文件。选用何种格式可以参考这里。如果条目不是很多(5000条以下),那么可以考虑用最直观的数组格式,而且可以写到一个 php 文件里。假设,我们需要一个中文版支持,翻译文件命名为 zh_cn.php,放在与 application 平行的 languages 文件夹里。该文件内容如下:

<?php
return array(
‘hello_world’ => ‘你好!’,
);

2. 加载翻译文件

编辑 html/index.php 文件,在前端控制器运行之前,插入下面的代码

require_once ‘Zend/Registry.php’;
require_once ‘Zend/Translate.php’;
$adapter = new Zend_Translate(‘array’, $rootPath . ‘/languages/zh_cn.php’, ‘zh’);
Zend_Registry::set(‘Zend_Translate’, $adapter);

上述代码的作用是载入 zh_cn.php,并把它保存成全局变量。Zend_Registry 可以看成是一个全局变量容器。

注意:在保存到 Zend_Registry 中时,键值必须是 Zend_Translate,否则,得不到应有的结果。

3. 在视图中使用翻译条目

编辑 application/views/scripts/index/index.phtml 文件,将原来的“<h1>Hello World!</h1>”替换成:

<h1><?php echo $this->translate(‘hello_world’); ?></h1>

4. 查看页面

这时,浏览器中看到的应是“你好!”。

Zend Framework 错误处理

使用 Zend Framework 的 MVC 结构,如果不做特殊的处理,所有的异常都会被前端控制器捕获,并累积起来。

Zend Framework 提供了若干种方法来处理异常。这里介绍最简单的一种。

在第一部分《快速上手》中,我们已经有了一个很简单的错误处理机制,即通过 applicatoin/controllers/ErrorController.php 以及其中定义的 errorAction 方法来处理异常。不过,只是给出了一个很简陋的报错信息。现在,我们把它再完善一下,达到两个基本要求:

  1. 用户请求了不存在的控制器或动作(404 错误),在用户的浏览器中给出报错信息;
  2. 其他的系统错误,则在日志文件中记录下来。

1. 创建日志

创建一个与 application 平行的文件夹,命名为 logs。

编辑 html/index.php 文件,加入下面的代码:

require_once ‘Zend/Log.php’;
require_once ‘Zend/Log/Writer/Stream.php’;
$log = new Zend_Log(new Zend_Log_Writer_Stream($rootPath . ‘/logs/errors.log’, ‘a+’));
Zend_Registry::set(‘error_log’, $log);

注意:Web 服务器应具有对 logs 文件夹的读写权限。

2. 完善错误处理代码

编辑 application/controllers/ErrorController.php 文件,新的 errrorAction 方法为:

public function errorAction()
{
$log = Zend_Registry::get(‘error_log’);
$content = null;
$errors = $this->_getParam (‘error_handler’) ;
switch ($errors->type) {
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER :
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION :
// 404 error — controller or action not found
$this->getResponse ()->setRawHeader ( ‘HTTP/1.1 404 Not Found’ ) ;
// … get some output to display…
$content = “error_page_not_found”$$
break ;
default :
// application error; display error page, but don’t change
// status code
$content = “error_unexpected”$$
// …

// Log the exception
$exception = $errors->exception;

$log->debug($exception->getMessage() .
PHP_EOL . $exception->getTraceAsString());
break ;
}

// Clear previous content
$this->getResponse()->clearBody();
$this->view->content = $content;
}

在 languages/zh_cn.php 中加入错误信息的中文条目(如果你不需要支持多国语言,那么可以忽略这些):

‘error_page_not_found’ => “<h1>404 错误:页面不存在!</h1>” . PHP_EOL .
‘<p>对不起,您所要求的页面不存在。</p>’,
‘error_unexpected’ => ‘<h1>错误!</h1>’ . PHP_EOL .
‘<p>对不起,系统无法响应您的请求。请稍后再试。</p>’,

最后,略微修改一下 application/views/error/error.phtml 文件:

其中的错误显示代码为:

<?php echo $this->translate($this->content); ?>

注意:如果你需要记录所有的异常和错误,包括各种警告,可以参考这里。

Zend Framework 入门——快速上手

1. 安装

从 Zend Framework 的网页上下载最新版本。解压后,把整个目录拷贝到一个理想的地方,比如:/php/library/Zend。

打开 php.ini 文件,确认包含 Zend 目录的路径在 include_path 里定义了。以上面的配置为例,php.ini 中应有类似下面的条目:

include_path = “.:/php/library”

注意:Windows 下的写法略有不同,应该类似于 include_path = “.;C:\php\library”

初始的安装就这么简单。Zend Framework 的一些组件会用到 php 的一些附加模块。具体的要求请参考这里。

2. 项目的目录结构

如果你的项目不包含多个模块,可以用下面的目录结构:

application/
    controllers/
        IndexController.php
    models/
    views/
        scripts/
            index/
                index.phtml
        helpers/
        filters/
html/
    .htaccess
    index.php

如果你的项目要包含多个模块(比如:博客,社区,等等),那么建议使用模块化的目录结构。

3. 网页的根目录

网页的根目录应指向上述目录结构中的 html 文件夹。

4. 重写规则

编辑 html/.htaccess 文件,加入下面两行:

RewriteEngine onRewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
注意:上述是针对 apache 的配置。如果是其他的服务器,请参考这里。

5. 引导程序

编辑 html/index.php 文件,敲入下面代码:

<?php

require_once ‘Zend/Controller/Front.php’;

$rootPath = dirname(dirname(__FILE__));

Zend_Controller_Front::run($rootPath . ‘/application/controllers’);

上面代码的作用是实例化前端控制器(Front Controller)并运行它。

6. 默认的动作控制器(Action Controller)

Zend Framework 的默认路由规则是 http://域名/控制器名/动作(方法)名。例如:

http://example.com/user/show 会被解析到名为 User 的控制器以及该控制器中定义的 show 方法。如果该方法没有定义,则默认转到 index 方法。

注意:在代码中,控制器名的后面要加上 Controller,而动作名的后面要加上 Action。

编辑 application/controllers/IndexController.php 文件,输入:

<?php

/** Zend_Controller_Action */

require_once ‘Zend/Controller/Action.php’;

class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
}
}

7. 视图(页面)脚本

编辑 application/views/scripts/index/index.phtml,输入:

<!DOCTYPE htmlPUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>

<html>

<head>

<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />

<title>My first Zend Framework App</title>

</head>

<body>

<h1>Hello, World!</h1>

</body>

</html>

8. 错误控制器

默认情况下,Zend Framework 的错误处理插件是被注册的。它需要一个错误控制器来处理错误。缺省的错误控制处理被假定为 ErrorController 以及其中定义的 errorAction。

编辑 application/controllers/ErrorController.php,输入:

<?php
/** Zend_Controller_Action */
require_once ‘Zend/Controller/Action.php’;

class ErrorController extends Zend_Controller_Action
{
public function errorAction()
{
}
}

下面是对应的视图脚本。编辑 application/views/scripts/error/error.phtml,输入:

<!DOCTYPE htmlPUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>

<html>

<head>

<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />

<title>Error</title>

</head>

<body>

<h1>An error occurred</h1>

<p>An error occurred; please try again later.</p>

</body>

</html>

9. 运行

好,现在运行网站。在浏览器中键入下面三个地址,得到的结果应该是一样的——就是最最常见的“Hello, World!“。

http://域名

http://域名/index

http://域名/index/index

如果是这样,那么恭喜你!

Zend_Acl / Zend_Auth 例子

Zend_Acl / Zend_Auth example scenario

by Simon Mundy

Hi there all

After submitting the initial example of how Zend_Auth and Zend_Acl could be implemented Gavin pointed out areas that weren’t really addressed in my proof of concept and it could potentially confuse newcomers to the way MVC is utilised. I’d like to clarify that post to a) Address those concerns and b) see if there’s any constructive criticism of the process that could benefit everyone.

Requirements

Demonstrate a web environment where ‘public’ (i.e. non-authenticated) users and ‘member’ users have access restrictions, and to what context they may visit those resources. In a lot of ways this broad concept relates very well to small-medium sites of a lot of Zend developers (in my opinion). For purpose of clarity we will assume this is a SIG group for Mac Users to discuss all things Mac OS X-related. The site has 3 areas (home, news, tutorials) that are for the general public. Members can also view a discussion forum, community newsletter and support request area for members to share common problems.

Site layout
-------------
Expressed as :controller/:action notation:-

/home

/news/index
     /view
     /email

/tutorials/index
          /view

/forum/index
      /category
      /view
      /add
      /update
      /reply
      /search
      /report - report abuse, etc.

/support/index
        /view
        /search
        /submit
        /confirmation -
        /comment - add comment

/login/index - handles form processing and auth processing

/logout/index - destroys current auth instance

/error/noroute - handles all 404s
      /failure - handles 'Site error' messages
      /privileges - handles 'You are not privileged...' messages

/admin - a cms to handle all site management

This loosely illustrates the site functionality and content – for the sake of brevity we’ll assume that the general concepts and operations of these site functions are understood and familiar. What we’re interested in is how to handle user authentication and then access, but at least this gives us some ‘real world’ understanding of what is required.

Access rules:

Three types of user ‘roles’ have been identified for the site:-

  • guest (not authenticated) – Guests can access ‘home’, ‘news’ and ‘tutorials’ only. Guests attempting to access member-only content will be asked to authenticate.
  • member (authenticated) – Access all top-level controllers. Can update forum posts but only those authored by themselves. Not allowed access to admin section. Access to ‘admin’ will result in ‘privileges’ error message.
  • admin (authenticated) – Unrestricted access.

Application layout

Using the ‘Conventional’ layout that Gavin outlines in http://framework.zend.com/wiki/display/ZFDEV/Choosing+Your+Application%27s+Directory+Layout

The bootstrap is located inside /htdocs/index.php

Bootstrap

The bootstrap takes care of the usual suspects – Db, View, Config, Log, Router – and stores them inside the Zend_Front_Controller so that they can be accessed via each controller using the getInvokeArg() method. This negates the need for an extra registry object and (hopefully) makes the dependencies somewhat easier to track.

To satisfy the needs of the Access rules, we create a subclassed instance of Zend_Acl like so:

class MyAcl extends Zend_Acl
{
    public function __construct(Zend_Auth $auth)
    {
        parent::__construct();

        $roleGuest = new Zend_Acl_Role('guest');

$this->add(new Zend_Acl_Resource('home'));
$this->add(new Zend_Acl_Resource('news'));
$this->add(new Zend_Acl_Resource('tutorials'));
$this->add(new Zend_Acl_Resource('forum'));
$this->add(new Zend_Acl_Resource('support'));
$this->add(new Zend_Acl_Resource('admin'));

        $this->addRole(new Zend_Acl_Role('guest'));
        $this->addRole(new Zend_Acl_Role('member'), 'guest');
        $this->addRole(new Zend_Acl_Role('admin'), 'member');

        // Guest may only view content
        $this->allow('guest', 'home');
        $this->allow('guest', 'news');
        $this->allow('guest', 'tutorials');
        $this->allow('member', 'forum');
        $this->deny('member', 'forum', 'update'); // Remove specific privilege
        $this->allow('member', 'support');
        $this->allow('admin'); // unrestricted access

        // Add authoring ACL check
        $this->allow('member', 'forum', 'update', new MyAcl_Forum_Assertion($auth));
        // NOTE: Dependency on auth object to allow getIdentity() for authenticated user object
    }
}

…and then this is added to the bootstrap. The final index.php file looks something like:

Index.php
<?php

// Initialise configuration / environment
$config = new Zend_Config(new Zend_Config_Ini('../application/config/config.ini', 'live'));

// Create sitemap from .ini using structure from example
$sitemap = new Zend_Config(new Zend_Config_Ini('../application/config/sitemap.ini', 'live'));

// Create db object and enable/disable debugging
$db = Zend_Db::factory($config->db->connection, $config->db->asArray());
...etc...

// Create auth object
$auth = Zend_Auth::getInstance();

// Create acl object
$acl = new MyAcl($auth); // see 

// Create router and configure (LIFO order for routes)
$router = new Zend_Controller_RewriteRouter;
...add rules...

// Create view and register objects
$view = new My_View;
...init view...

$front = Zend_Controller_Front::getInstance();
$front->throwExceptions(true);
$front->setRouter($router)
      ->setDispatcher(new Zend_Controller_ModuleDispatcher())
      ->registerPlugin(new My_Plugin_Auth($auth, $acl))
      ->registerPlugin(new My_Plugin_Agreement($auth))
      ->registerPlugin(new My_Plugin_View($view))
      ->setControllerDirectory(array('default' => realpath('../application/controllers/default'),
                                     'admin' => realpath('../application/controllers/admin')))
      ->setParam('auth', $auth)
      ->setParam('view', $view)
      ->setParam('config', $config)
      ->setParam('sitemap', $sitemap)
      ->dispatch();

This is a pretty standard (IMO) bootstrap – the areas to note for the purpose of Authentication/Acl are the two first plugins:

Auth.php

The purpose of this plugin is to first determine the ‘role’ of the current Auth identity. If Zend_Auth::getIdentity() returns false then we don’t have a ‘role’ for the identity, so we assume ‘guest’. If a user is authenticated, the Zend_Auth identity would be returned as an object and we would extract the role from this. For simplicity’s sake, let’s assume that the ‘role’ is stored in a MySQL database and is returned as a public property from the Identity object (i.e. ‘member’ or ‘admin’).

The ‘role’ is then a one-to-one match against the Acl rules. If we interrogate the Acl and we are allowed to view the current controller (maps to the ‘resource’ id given to each Acl resource) then the dispatcher continues on its merry way.

If the Acl denies the access, we then determine if the user has a valid identity. If not, we tell the request object that we want to redirect to a new controller (login) to perform a login. At this stage, no request data is required – this will be handled via a form in the LoginController.

If, however, the identity is valid then we know that access if definitely blocked for that user and we send the request to the ‘error’ controller to display the ‘no privleges’ error.

I’ve chosen this strategy as it means that none of the controllers need know anything about the ACL process – they can assume that access to the action has been already approved and need only check action-specific privilege checks (e.g. ensuring they view valid articles, forum threads, etc.)

However a developer could still choose to add further ACL rules if required and reduce the amount of ACL-related ‘clutter’ in the controllers themselves.

<?php

class My_Plugin_Auth extends Zend_Controller_Plugin_Abstract
{
    private $_auth;
    private $_acl;

    private $_noauth = array('module' => 'default',
                             'controller' => 'login',
                             'action' => 'index');

    private $_noacl = array('module' => 'default',
                            'controller' => 'error',
                            'action' => 'privileges');

    public function __construct($auth, $acl)
    {
        $this->_auth = $auth;
        $this->_acl = $acl;
    }

public function preDispatch($request)
{
        if ($this->_auth->hasIdentity()) {
            $role = $this->_auth->getIdentity()->getUser()->role;
        } else {
            $role = 'guest';
        }

    $controller = $request->controller;
    $action = $request->action;
    $module = $request->module;
$resource = $controller;

    if (!$this->_acl->has($resource)) {
        $resource = null;
    }

        if (!$this->_acl->isAllowed($role, $resource, $action)) {
            if (!$this->_auth->hasIdentity()) {
                $module = $this->_noauth['module'];
                $controller = $this->_noauth['controller'];
                $action = $this->_noauth['action'];

为你的ZendFramework选择合适的目录结构

Choosing Your Application’s Directory Layout

This document demonstrates and named types of file organization schemes (layouts) that are commonly found in dynamic web applications. This document aids developers starting new projects by explaining the pros and cons associated with each of the popular layouts below. Community contributed suggestions and guidelines help provide insight into suggested approaches for organizing code into a hierarchical layout, while also giving developers a nomenclature to discuss their layouts with others.

For an in-depth look at the Conventional Modular Layout discussed below, please see the ZFDemo Tutorial.

Layouts

The following represent common layout variations you might find from application to application. They are presented in alphabetical, specialized order.

All references to directories named “/var”, “/variable”, “/tmp”, or “/temporary” should be interpreted as implying the use of a unique prefix to avoid security issues. For example, “/tmp” should actually be interpreted as “/my/permission/protected/tmp”, and not the shared “/tmp” found on many *nix systems. Likewise the other top-level directories, like “/application” are also meant to have deployment-specific prefixes (e.g. /home/me/myZFApp/application).
/*<![CDATA[*/ div.rbtoc1218553180088 {margin-left: 0px;padding: 0px;} div.rbtoc1218553180088 ul {list-style: none;margin-left: 0px;padding-left: 20px;} div.rbtoc1218553180088 li {margin-left: 0px;padding-left: 0px;} /*]]>*/

Classical (Unix/Linux-like)

Initially broken down into two main directories, web-readable and application files. This style mimics Unix/Linux OS directory layouts, and would be preferred by someone who favors Unix/Linux-style naming conventions.

/application
    /etc
    /lib
        /Zend
        /(other libraries)
    /usr
        /controllers
        /models
        /views
    /var
        /sessions
        /cache
        /view_compiles
/htdocs
    /images
    /scripts
    /styles

Pros

  • Self-contained; application-related files that are not publicly-accessible are in one place
  • Library files located locally (not server-wide)
  • Strong layout when models, views, and controllers have overlap, or are interrelated

Cons

  • Cryptic naming convention not common to people outside the Unix/Linux world
  • Grouping of all models, views, and controllers into a single location is seen as poor practice if they are not related. For example, think of a site’s blog-related code and its poll-related code.

Classical Extended

/application
    /config
    /library
        /Zend
        /(other libraries)
    /user
        /controller
        /model
        /view
    /variable
        /sessions
        /cache
        /view_compiles
/htdocs
    /images
    /scripts
    /styles
    index.php

Pros

  • Same as Classical
  • Shorter Unix/Linux-style names lib, usr, and var are replaced with full length names for clarity

Cons

  • Same as Classical, except for the cryptic naming scheme

Classical Extended Embedded

In certain environments, moving the application-related files outside the web-readable directory might not be an option. In this case, the files are in the web readable directory and should be protected via an .htaccess file if at all possible, or some other related protection mechanism.

Security concern
Directly exposing application files to the outside world can potentially result in sensitive information about the application or server being revealed to attackers.
/htdocs
    /application
        /config
        /library
            /Zend
            /(other libraries)
        /user
            /controller
            /model
            /view
        /variable
            /sessions
            /cache
            /view_compiles
        .htaccess (deny from all)
    /images
    /scripts
    /styles
    index.php

Pros

  • Useful in environments where htdoc directory is all a developer has access to

Cons

  • This layout could present security issues if not properly configured
  • The route /application/ is not available for use due to it existing in the file system

Conventional

/application
    /config
    /controllers
    /models
    /views
/htdocs
    /images
    /scripts
    /styles
    index.php
/library
    /Zend
    /(other libraries)
/tmp
    /sessions
    /cache
    /view_compiles

Pros

  • With the exception of user created library code, application related code (as it relates to the domain model, controllers and views) is in one specific location.
  • Can take advantage of a library installed globally on a system (like PEAR)
  • As opposed to a Classical layout, focus on code containment is at the main directory level, thus creating a wider directory structure at the top most level.
    • Application directory in this layout means ‘the code responsible for the direct duties of carrying out application specific actions’.
    • Library directory in this layout are librarys of code that carry out a specific and common pattern of duties, usually not related to the specifics of an application, but related to the carrying out of common tasks.
    • Tmp, or ‘variable’ directory, exists to aid the application in its duties that may require the use of a filesystem to create tmp files like session files, cache files or view compiles.
  • When an available option, this is the suggested format of the Zend Framework.
    • Using the most common or most encouraged format aids future developers (that might inherit or use your software) by reducing thier time getting up to speed.

Cons

  • Wider top level of directories. If your perception of application directory is not limited to the site specific files and includes libraries and system (tmp) files.
  • Harder to move top files into an Embedded structure (within the htdocs directory) as each concrete directory must be secured against web readability, and routes by the same name as concrete directories cannot exist (easily).
  • Certain applications might require custom (or extended) libraries, in that case, it is important to note that you not distinguish between 3rd Party libraries and user generated libraries. Library code is simply, regardless of source, library code.

Conventional Modular

In this style, models, views, and controllers for a specific application module are grouped into logical “packages”, or directories.

/application
    /config (optional)
    /(module 1)
        /config (optional as needed)
        /controllers
        /models
        /views
    /(module 2)
        /controllers
        /models
        /views
    /(module n)
        /controllers
        /models
        /views
/htdocs
    /images
    /scripts
    /styles
    index.php
/library
    /Zend
    /(other libraries)
/tmp
    /sessions
    /cache
    /view_compiles

Pros

  • same as Conventional
  • Allows for packaging of non-interrelated application components (think plugin architecture of a web site with a blog, polls, quote generator).

Cons

  • same as Conventional

Naming conventions

Name Common alternatives
htdocs www, public_html, or inetpub
images img
scripts js or javascript
styles css