使用Zend Framework 0.7中控制器的模块功能

在Zend Framework 0.6的时候,控制器的模块功能已经实现了,但是有个Bug并不能用。不过到Zend Framework 0.7版的时候已经解决了。所以,我马上在项目中运用这个特性。虽然文档和邮件列表里面有谈到,但我在移植的时候还是出现了一些小问题,所以还是罗嗦一下。

当你的项目慢慢变得复杂的时候,控制器目录会有很多文件,这样很不好管理(如果你全写在一个控制器里面,那我就无语了……)。所以,在Zend Framework里面实现了多个模块功能,让你设置不同的控制器目录,一个目录代表不同的模块。这样就可以把相关的控制器放在一起了。好了,实战开始:

首先说一下,我的控制器目录结构/controllers,然后,我需要把管理的控制器单独放在一个目录/controllers/Admin(!注意这里需要大写)。当然你可以这目录放在任意的地方。那么在设置控制器目录的时候就要修改一下:

$controller->setControllerDirectory(array(

    'default' => $_SERVER['DOCUMENT_ROOT'].'/core/controllers',
    'admin' => $_SERVER['DOCUMENT_ROOT'].'/core/controllers/Admin'

));

然后,添加下面这段代码。以打开模块功能。 

$controller->setParam('useModules', true); 

 这样,你就可以在/controllers/Admin中创建控制器了。比如创建一个FileController.php,路径如下:/controllers/Admin/FileController.php。类名需要写成模块名_文件名,所以这个控制器的类名是Admin_FileController。然后,该写什么的就写什么。

现在,就可以通过http://yourdomain/admin/file,来访问这个控制器了。

不过最终还是有点点小问题,就是在模块下,好象并不支持IndexController.php。这点可以通过使用RewriteRouter来帮我们一下。至于怎么使用RewriteRouter可以看我的另一篇网志。

$router->addRoute('admin', new Zend_Controller_Router_Route('/admin', array('controller' => 'admin_index', 'action' => 'index')));

昨天,在移植的时候,发现本机是好的(windows平台),一放到服务器上面就broken。后来一想,由于linux平台是区分大小名的。后来,我把Admin_FileController类名改成admin_FileController,模块名为admin。不过好像不好使……

Zend Framework 0.7.0发布

这个月Zend Framework 0.7的预览版已经发布了。主要来说还是MVC组件的一些改进,并添加了一些新的功能。

等会把版本更新一下。MVC组件现在更加完善上,可能会有些小的调整。顺便贴个checklog:

– Zend.php:
    ZF-35 ZF Version check
    ZF-329 Removal of loadInterface() Method
    ZF-380 Zend::loadFile() method do not return correct values
    ZF-411 API doc improvement
    ZF-454 Zend::isReadable triggers error-handler
– Zend_Acl:
    Moved from incubator to core.
– Zend_Auth: (incubator)
    ZF-657 Zend_Auth's use of Zend_Session
– Zend_Cache:
    ZF-463 Zend_Cache tests use a system directory
    ZF-724 testGetWithAnExistingCacheIdAndUTFCharacters fails
– Zend_Cache_Backend_ZendPlatform:
    Moved from incubator to core.
– Zend_Controller:
    ZF-537 Handling HTTP 100 responses
    ZF-628 Zend_Controller_Action::redirect and new repsonse object integration
    ZF-637 _formatName not removeing underscores in actions
    ZF-656 MVC Plugin Interface/Abstract Class incorrect
    ZF-658 request object should not set controller and action in params
    ZF-659 MVC documentation should cover utility methods of Action Controllers
    ZF-660 MVC modules fail need default module setting
    ZF-669 setHeader() shoudl allow modifications to HTTP response codes
    ZF-671 No baseUrl/pathInfo auto-detection in Zend_Controller_Request_Http
    ZF-679 Missing argument in _hasParam()
    ZF-680 endless loop Zend_Controller_Dispatcher::loadClass()
    ZF-682 Zend_Controller_Router_Route problem when using empty route and path
    ZF-707 Unsupported operand when $_GET and/or $_POST are null
    ZF-711 Unit test failure in Zend/Controller/Request/HttpTest::test__Isset()
    ZF-713 _hasParam in Zend_Controller_Action is just wrong
– Zend_Date:
    Finished implementation, resolved many issues.
    Moved from incubator to core.
– Zend_Db:
    ZF-201 PDO Adapter names should begin with 'pdo_'.
    ZF-511 Zend_Db_Adapter_MySQLi coding standards conformance
– Zend_Filter/Zend_Validate: (incubator)
    New prototype implementation.
– Zend_Gdata:
    ZF-704 testOrderbyParam(Zend_Gdata_CalendarTest) failing
    ZF-708 Document Gdata delete() method better
    ZF-712 Gdata exception handling is confusing
    ZF-729 Unable to delete calender events when using ClientLogin
    ZF-747 Report POST response message in Gdata exception
    ZF-757 Gdata doc hyperlinks have changed
    ZF-759 Doc use of Zend_Gdata->delete() without a feed object
    ZF-762 Gdata doc should explain how to use Zend_Feed object
– Zend_Http_Client:
    ZF-647 Support proxy servers
    ZF-689 Zend_Http_Client sets wrong HTTP protocol version
    ZF-697 Bad handling of the query part of an uri
    ZF-725 Can't choose which type of SSL to use
    ZF-741 Invalid chunk size in Zend_Http_Client_Adapter_Socket
    ZF-751 The timeout option is only applied on the opening of the connection
    ZF-753 PHP Notice: Undefined offset: 1
– Zend_Http_Server: (incubator)
    ZF-533 Server only reads the first line of the request
– Zend_Locale:
    Finished implementation, resolved issues.
    Moved from incubator to core.
– Zend_Mail_Folder: (incubator).
    Improvements to component under development.
– Zend_Memory: (incubator).
    New component.
– Zend_Measure:
    Moved from incubator to core, resolved issues.
– Zend_Registry:
    ZF-662 testManualInit(Zend_RegistryTest) failure
    ZF-672 Zend_Registry needs its set() and has() methods back
    ZF-674 testBeforeInit(Zend_RegistryTest) failure
    ZF-675 testManualInit(Zend_RegistryTest) failure
– Zend_Search_Lucene:
    ZF-85  Query Parser not handling fieldbname with underscores
    ZF-228 document and field boost does not work
    ZF-690 Large file indexing problem
– Zend_Service_Amazon:
    ZF-119 Service_Amazon_Item not return valid Track
– Zend_Session:
    Moved from incubator to core.
    ZF-548 Documentation for Zend_Session
    ZF-661 Expiration of namespace variables by hop does not work as expected
    ZF-676 Zend_Session_Core does not correctly check its state
    ZF-678 Some of the public API methods are not documented.
    ZF-698 Ambiguous error messages
    ZF-735 automatic defaulting of session name, and session collisions
    ZF-736 Rename unLock() method to unlock()
    ZF-740 doc not clear on session locking and limiting instances
    ZF-749 Exception handling for certain errors not clear
– Zend_TimeSync: (incubator)
    Improvements to component under development.
– Zend_Translate: (incubator)
    New component.
– Zend_Uri:
    ZF-611 Switch to lazy loading Exceptions
– Zend_XmlRpc:
    Improvements to code and documentation.
– Zend_View:
    ZF-173 Missing parenthesis in the example
    ZF-655 opt group support for FormSelect
    ZF-699 empty() and isset() on view properties are broken
    ZF-706 Cannot specify id attribute for hidden fields in 0.6.0
    ZF-727 Loading of helpers is not LIFO
    ZF-752 Wrong error message in Zend_View_Abstract

更多的可以去developer里看 

Plone 2.5.2 released

1月17号,Plone官方发布了2.5的第二个版本。这个版本主要还是修改一些bug。

  • LiveSearch(动态搜索)
  • Unicode handling(Unicode字符的处理)
  • External Editor(外部编辑器)
  • IE7 rendering(IE7的页面显示)

最近,由于工作的原因,对Plone的兴趣越来越没兴趣了。我想,如果公司不使用Plone平台的话,我将不再会做Plone的开发工作。但是,我倒对Zope3的平台感兴趣,我会更多的关注这个东西。马上公司使用Plone开发站点就要上线了,可以看看效率到底怎么样!

 

JQuery1.1发布了

随着ajax的流行,出现了许多优秀的JS框架,JQuery就是其中之一。今天JQuery终于发布了1.1版,有一些重要的更新,而且今天也是JQuery的生日。jQuery Birthday: 1.1

上次写了一篇小教程,不过数据丢了。准备把原来的整理一下。

这段代码实现的效果是在站点归档中“其它信息”展开效果,代码如下:

$(function(){
    var collapsibles = $("dl.collapsible");
    $(collapsibles).each(function(i){
        var collapsible = collapsibles[i];
       
        $("dt.collapsibleHeader", collapsible).click(function(){
            var container = $(this).parent();
            if (!$(container).is(".collapsible")) {
                return false;
            }
           
            if ($(container).is(".collapsedInlineCollapsible")) {
                $(container).addClass("expandedInlineCollapsible").removeClass("collapsedInlineCollapsible");
            } else {
                $(container).addClass("collapsedInlineCollapsible").removeClass("expandedInlineCollapsible");
            }
        });
    })

    if ($(collapsible).is(".collapsedOnLoad")) {
        $(collapsible).addClass("collapsedInlineCollapsible").removeClass("collapsedOnLoad");
    } else {
        $(collapsible).addClass("expandedInlineCollapsible");
    }
});

这段代码需要在页面加载完毕后执行,所以我们使用$(function(){})来达到这个效果,还一种等价的写法$(document).ready(function(){})。

$("dl.collapsible"),这是JQuery中最常用的方法,用于查找指定的元素,而且支持CSS和XPath的语法。这样所有的dl.collapsible被匹配。(如果你对CSS的语法不了解的放,可以先看看教程)

接着使用each进行遍历,再看下面这段:

$("dt.collapsibleHeader", collapsible).click(function(){
            var container = $(this).parent();
            if (!$(container).is(".collapsible")) {
                return false;
            }
           
            if ($(container).is(".collapsedInlineCollapsible")) {
                $(container).addClass("expandedInlineCollapsible").removeClass("collapsedInlineCollapsible");
            } else {
                $(container).addClass("collapsedInlineCollapsible").removeClass("expandedInlineCollapsible");
            }
        });

 $("dt.collapsibleHeader", collapsible),第二个参数是指定上下文,并在指定的上下文中查找。后面的click(function(){})是注册单击事件并绑定一个函数。is用来判断是否包含指定表达式;addClass和removeClass分别是添加和移除class。最后一段:

if ($(collapsible).is(".collapsedOnLoad")) {
        $(collapsible).addClass("collapsedInlineCollapsible").removeClass("collapsedOnLoad");
    } else {
        $(collapsible).addClass("expandedInlineCollapsible");
    }

当JS被禁用时所有的dl展开。 

我终于知道人们都想移民

就在前几天v2ex.com突然不能访问,前初是以为服务器调整。后来得知道事情真相,真是让人悲痛。

不知道什么原因,突然冒出所谓的《信息网络传播视听节目许可证》这个东西。所以,出现BlogBus遇上了文化V2EX被强制网线全拔事件。我经常上v2ex,上面根本就没有什么不良的东西。这样的网络环境真是让人太失望了。

实在让我哭笑不得,密切关注这件事情。 

 

代码重构

在使用ZF之后,我对MVC有了真正的了解。在前面的一些代码中,我在Action中加入了太多的业务代码,Struts是在Java中非常有影响 力的MVC框架,通过在网上查看这家伙的文章中,发现Action只是起到“决定做什么”的作用,并不是“怎么做”。我觉得这篇文章讲得非常好:MVC在Web系统中的模式与应用。这样当分开后,业务可以得到更大的重用。

重构是XP中的一个重要理念,不要害怕丢弃原来劣质的代码,只有这样才能不断优化设计结构,增加系统的可重用性和扩展性。虽然,我现在还不能在项目中实现XP编程理念,但我会不断的将这么理念引入的我的项目中去。

eclipse下面PHPIDE项目现在已经改了名字PHP Development Tool,现在我的开发环境就是她了。虽然,现在还是0.7RC1版,但功能也基本差不多了,最重要的免费的。

最后,关于现在站点的小bug,网志的标题都是一样的。这样对SEO极度不好,现在用google搜都搜不到啦。。。。

写在2006的最后(过去时)

由于前几天的数据丢失,本来在2006的最后一天写的东西掉了,但我还是希望对自己总结一下。

人生总是有很多选择,但你的每次只能选择其中是一个。不同的选择意味着不同的人生,要选择之前你跟本不知道会得到什么,但我相信我每一次选择都是有意义的。引用Steve Jobs的一句话:

you can't connect the dots looking forward; you can only connect them looking backwards。

你无法预先把点点滴滴串连起来;只有在未来回顾时,你才会明白那些点点滴滴是如何串在一起的。

Steve Jobs于2005年对史丹佛毕业生演讲

在2005年未,我开始做PHP程序员,其实在进那公司已经前就是在学校学了点C罢了。虽然,这份工作不长,只有短短的20天,这让我对PHP有了基本的了解。同时,终于找到我想做的事情。这个世界真的很奇怪,就跟Steve Jobs说的一样,“只有在未来回顾时,你才会明白那些点点滴滴是如何串在一起的”。在这之前我就开始使用Firefox了,而且我对浏览器非常有兴趣,然后开始学习xhtml和css。这些都是对WEB开发有用的东西,而且我自己觉得非常前卫。

虽然,第一份程序员的工作很快就结束了,在两个月后,我来到了现在的公司。通过这份工作,那我看到了不少有趣的东西。由于工作的关系,我开始使用Zope,由于Zope是由Python写的,这样我又知道了Python;使用Plone后,知道了Zope强大的平台和非常牛B、而且前卫的内容管理系统。在这一年里,不断的新东西被我认识:xp、版本管理、bug管理、面向对象、设计模式、开发框架等等。

在2006年的生日那天,我定下了今年该做了事情。虽然,最终有许多东西没有完成,但是,我还是认为2006对我来说是个不错的选择。

2007年是我三年计划中的第二年,所以,这是非常重要的。 

  1. 学习英语应该是我今年最重要的事情
  2. 我会继续发展这个东西,希望推到有趣的地方
  3. 也许,今年我会离开武汉,去更远的地方
  4. 今年,我还有许多想买的东西

(继续更新) 

gonefish.cn终于开始动作了

由于某些问题,以前的一些数据丢失。反正丢失了几篇网志,自己也不记得写了些什么东西。现在这个gonefish.cn的域名终于生效了。

随着程序的发展,会不断的接触新的东西。真是不错的体验啊。