Category: PHP

Anything about PHP

  • 又被番茄发现 Zend_Db_Select 的 Bug 了

    如果找到 Zend Framework 的 Bug,Zend 公司给发钱,恐怕项目组的兄弟们能出去挫好几顿了。

    废话少说,这次的 Bug 比较弱智。绝对是粗心大意引起的。少了一个参数,造成使用 join 方法时报找不到表的错误。

    Index: Select.php

    ===================================================================

    — Select.php    (revision 5792)

    +++ Select.php    (working copy)

    @@ -417,7 +417,7 @@

          */
         public function join($name, $cond, $cols = ‘*’, $schema = null)
         {
    –        return $this->joinInner($name, $cond, $cols);
    +        return $this->joinInner($name, $cond, $cols, $schema);
         }
     
         /**

     

    发到邮件列表上没人理。唉!算了!这种事情,自己动手丰衣足食。改一下,直接提交了svn。还好,之前申请的 zend framework 的 svn 帐号这回派上用途了。

  • ninny Project 的数据库完成向 mysql 5.0 的迁移

    升级为 PowerDesigner 12 来维护逻辑表果然方便多了,可以随意生成 Oracle 10g 和 mysql 5.0 的物理表。在修改了配置文件之后,我惊喜的发现原来一行代码也不需要修改,就完成了迁移工作。Zend Framework 的数据库部分的设计果然可圈可点。

    由于服务器自身的限制,以 Oracle 作为数据库的版本无法提供演示和下载。所以迫不得已只好再维护一个 mysql 5.0 的数据库版本。PowerDesigner 真的是利器,逻辑表不需要任何修改就可以生成 mysql 版本的物理表。如果大家有类似的迁移需求,推荐大家也用一用这个。等有钱了,一定买一套正版回来用。

    修改了资源权值和角色权值为添加时间戳,这样可以省掉维护两个触发器。PowerDesigner 12 好像还不能编写 mysql 5.0 的触发器。或许我需要手工添加一些规则才可以再 PowerDesigner 中直接编写 mysql 的触发器。不过不管怎么样,现在不需要触发器也可以按正常的权值构造 ACL 对象了。

    下一步的计划就是构造一个后台管理,将资源、角色、权限、用户等的管理都放到后台中进行。

  • 如何正确的编译 Zend Framework 手册的 chm 版本

    或许早就应该写一下这个方法了,只是一直没有什么心情。这会休息,就随手敲打敲打吧。

    由于我的环境是 windows,所以需要额外安装一些辅助软件。windows 下编译 docbook 的方法有许多种。我以前使用 java 写的一个工具,不过后来发现 cygwin 比较方便。

    详细的 cygwin 以及 docbook 编译必须的包请看 hohappy 编写的指南:http://www.phpeye.com/article/view/id/55

    废话不说了,现在看看如何编译chm。首先需要编译 chm 对应的 xsl。我使用sf.net 下载的 docbook-xsl-1.72.0。其中包含 /htmlhelp/htmlhelp.xsl。 (more…)

  • 为提升便利性,为 ninny Project 添加两个脚本工具

    工具存放地址:svn://www.i-fang.com/IfangSites/trunk/app/bin

    说明:这些工具是为快速开发编写的,请不要尝试在部署的时候使用。因为,多数服务器无法使用 CLI 方式执行 PHP 脚本。而这些工具只能执行于 CLI 模式下。

    1. collectResouces.php —— 资源收集工具

      我一直为 ACL 中资源的管理而烦恼,所以编写了这个工具。对于通用性资源(module、controller、action)进行采集,并按照顺序插入数据库中的资源表。
      使用方法:php collectResouces.php
    2. createModule.php —— 模块、控制器、动作自动创建工具

      其实编写 Controller Action 和 View Script 的第一步工作都是一样的。创建目录,创建文件,添加固定的内容……对于我来说,很烦。所以编写了这个脚本可以通过简单的 Yes/No 方式自动创建必要的目录、文件、代码框架。
      使用方法:php createModule.php
  • 基于 Zend Framework 的整合快速开发结构

    在思考现有项目代码重构的过程中的附带产品。主要是基于 Zend Framework 并对其中一些内容进行扩展、整合。放弃部分灵活性,同时提高耦合度为代价,换取开发速度的提升。

    我准备将这个项目的代号命名为“ninny”。

    项目SVN : svn://www.i-fang.com/IfangSites

    项目页面:http://blog.xxiyy.com/?page_id=21

    欢迎拍砖。

    现有 E-R 图,权限控制部分

    E-R 图
  • php 5 中使用get成员方法返回对象可能存在的问题。

    "错误的类设计可能会改变本不应该改变的成员属性。"这个问题是在看 Java 的时候书中提到的。PHP5 默认传递的也是引用,那么可能也存在这个问题。于是跳下床来,做了个试验。果然……

    先看一段代码:

    <?php 
    /**
     * privateClass 
     *
     * 一个私有的类,在 publicClass 中使用
     */
    class privateClass
    {
        
    /**
         * name
         *
         * 保存一个名字 
         * 
         * @var string
         * @access protected
         */
        
    protected $name '';
        
    /**
         * __construct
         *
         * 构造函数 
         * 
         * @param string $name 
         * @access public
         * @return void
         */
        
    public function __construct($name)
        {
            
    $this->setName($name);
        }

        /**
         * getName 
         *
         * 获得名字
         * 
         * @access public
         * @return string
         */
        
    public function getName()
        {
            return 
    $this->name;
        }

        /**
         * setName
         *
         * 设置名字 
         * 
         * @param string $name 
         * @access public
         * @return void
         */
        
    public function setName($name)
        {
            
    $this->name $name;
        }
    }
    (more…)

  • 就之前性能测试反馈的一些补充

    我说过对于FXXX 不在公开场所将其同 Zend Framework 比较的这样的话。所以我在这里做一些补充说明,一些是关于技术的,一些是关于技术人员应有的技术涵养的。

    在收到性能测试的反馈之后,我特别进行了测试:

    在 include(‘FXXX.php’) 之前定义:

    define(‘NO_LEGACY_FXXXPHP’, true);

    则 FxxxPHP 只会载入两个文件:FXXX.php (核心)和 Config/DEBUG_MODE_CONFIG.php(默认的设置文件,用于调试模式)。而不会再载入 Compatibility.php 文件。此时,开发者按照 FxxxPHP 1.0.70 的规范编写应用程序即可。而 Compatibility.php 是为了方便 FxxxPHP 1.0.60 应用程序升级而设置的。

    于是,我将这个开关加到之前的测试之上。很遗憾,在50次测试中,只有两次 FXXX 比 Zend Framework 快。

    据说,在 L 兄的测试中通过修改了两行多余的代码,使得 FXXX 的执行快过了 Zend Framework。我没有办法测试,因为他并没有给出这个修改方法。不过我想也有可能的,因为框架本身在 loadClass 上的工作几乎完全相同。那么通过优化是完全可以得到相同的效能。 (more…)

  • 关于 Zend Framework 和国产 FXXX 在类加载性能上的测试

     之前,FXXX 的主要开发者 L 兄曾经在 phpchina 上同我做过一些讨论。当然讨论的结果似乎不能令人满意。FXXX 对于我一直所诟病的数据库支持对于 L 兄来说似乎不是什么大的问题。而 Zend Framework 对于他来说似乎也是一直拥有效率黑洞,以及大而不精等诸多糟粕。Zend Framework 即将成为 PEAR2 是 L 兄一个比较精辟的形容。

    项目中最初推翻 FXXX 转而使用 Zend Framework 主要是由于 Orcale 的支持问题。但是这个问题似乎是 FXXX 的软肋,不能碰,一碰就招致狂风暴雨般的质问。当然,质问的内容不是框架的数据库支持。而是触碰这个软肋的人的技术水平问题。而 Zend Framework 的性能黑洞,也让我带着意思疑虑。Zend Framework 的性能是否真的不可调和,这个框架是否真的又臃肿,又庞大?带着这个问题,我做了以下试验:

    试验内容:为了检测 Zend Framework 的性能到底如何,我必须选择一个参照对象。很遗憾,优秀的 FXXX 被选中了。因为这个性能的疑虑正是 L 兄带给我的,所以………….解铃还需系铃人。

    那么对两个框架所有的部分都进行测试,似乎不太可能。这绝对是超出我能力范围的。那么我选择了 Loader 作为测试的内容。两个框架都有各自的加载类的方法。而这个方法又是在所有使用框架的开发中需要使用的。

    Zend_Loader::loadClass() vs FXXX::loadClass()

    我首先在Doc Root  目录中创建了 Zend 和 FXXX 目录,用于存放两个框架必要的文件。既然是测试 Loader 那么只要存放必要的 Loader 文件就可以了。顺便可以测试一下两个框架的耦合度。 (more…)

  • 手册中 Zend_Db_Table 的表关系例子的 E-R 图及部分解释

    在 Zend Framework 的 9.8. Zend_Db_Table Relationships 章节中,介绍了使用 Zend_Db_Table 关联表的例子。我听过不少人都觉得这部分相当难理解。我觉得手册如果能给出例子中所用数据表的E-R图,那么能帮助大家更清晰的理解这个例子。

    E-R 图:

    Zend_Db_Table 例子中的 E-R 图

    建表用 SQL 语句 (MYSQL 5.0):


    — 表的结构 `accounts`

    CREATE TABLE `accounts` (
    `account_name` varchar(50) NOT NULL,
    PRIMARY KEY (`account_name`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


    — 表的结构 `bugs`

    CREATE TABLE `bugs` (
    `bug_id` varchar(50) NOT NULL,
    `reported_by` varchar(50) NOT NULL,
    `assigned_to` varchar(50) NOT NULL,
    `verified_by` varchar(50) NOT NULL,
    PRIMARY KEY (`bug_id`),
    KEY `reported_by` (`reported_by`),
    KEY `assigned_to` (`assigned_to`),
    KEY `verified_by` (`verified_by`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8; (more…)

  • Zend Framework 代码分析——Zend_Loader

    Zend_Loader 应该是 Zend Framework 中相对简单的类。所有方法都为静态方法,用于加载(loading)类或文件(loadClass、loadFile、autoload、registerAutoload 方法),以及加载类或文件时进行的必要判断(isReadable 方法)。

    Zend_Loader 从 3834 版本被加入 Zend Framework 并没有太多的改动。除了 4259 版本添加了 registerAutoload 方法。

    public static function loadClass($class, $dirs = null)

    方法是高效的加载类的方法。类的文件命名必须是 {$className}.php。当第二个参数 $dirs 为文件夹名或元素是文件夹名的数组时,将从这些文件夹中找到第一个匹配的文件进行加载。而如果 $dirs 为 null,则将类名的下划线作为分隔,划分为文件夹。例如 Zend_Foo_Bar,将会加载 Zend/Foo/Bar.php这个文件。若无法在上述所有地方找到可用的文件加载类,则将对 include_path进行搜索。

    if (class_exists($class, false) || interface_exists($class, false)) {

    return;

    }

    首先判断是否已经加载,这里使用了 interface_exists,在 php 中 interface 可以被认为是一种特殊的类。

    if ((null !== $dirs) && !is_string($dirs) && !is_array($dirs)) {

    require_once 'Zend/Exception.php';
    throw new Zend_Exception('Directory argument must be a string or an array');

    }
    if (
    null === $dirs) {

    $dirs = array();

    }
    if (
    is_string($dirs)) {

    $dirs = (array) $dirs;

    }

    若类和接口没有被加载,则对 $dirs 进行验证,判断是否为合法的类型:null、字符串、数组,否则抛出异常。而最终 $dirs 都将转换为数组处理。 (more…)