不用模板,也要保持HTML和PHP尽量独立

页面上有的按钮是需要根据当前操作者的权限决定是否Disable掉的。昨天看了三儿写的代码,他把Input标签的最后一部分写在一个函数中echo出来,函数中包含对当前用户权限的判断,于是乎有了以下代码:

<?php
function disabledbutton($actionName,$user){
        if(PrivilegeController::mayI($actionName,$user)){
                echo ">";
        }
        else{
                echo 'disabled="disabled">';
        }
}
?>

<input type="button" value="Change" <?php disabledbutton('change', $curUser);?>
<input type="button" value="Add" <?php disabledbutton('add', $curUser);?>

这样写代码的一个大问题在于,HTML和PHP代码都被拆散了,代码的可维护性大大降低。试想如果10天休假之后,在回来看这个页面的代码,修改其中的一小部分,会是一种什么情形?

大家都知道使用模板技术能让逻辑和界面分离,其实模板技术本身执行的也就是标签替换的操作。不使用模板的时候,我们自己也可以通过调整PHP代码和HTML的书写方式,让逻辑代码和页面代码尽量分离,并且易于阅读:

 

<?php
$disableChange = PrivilegeController::mayI('change',$curUser)?'':'disabled="disabled"';
$disableAdd    = PrivilegeController::mayI('add',$curUser)?'':'disabled="disabled"';
?>

<input type="button" value="Change" <?=$disableChange?> >
<input type="button" value="Add" <?=$disableAdd?> >

这样的书写方式,保证了页面结构的完整性,而且逻辑处理代码全部集中在页面首部,更易于修改和维护。

UTF-8 BOM导致的Session无法启动问题

BOM的全称是byte-order mark , 它是在Unicode编码的文件首部用于表示文件编码类型的一个特殊字符,对于UTF-8编码来说,它的值是0xEFBBBF。这个字符是不可见的,大多数文本编辑器都不会把它显示出来,对于一般的PHP程序,它的存在也不会影响脚本的正常执行。只有一种情况例外——需要发送HTTP首部的时候。

因为它总是存在于文件的首部,自然也就在<?php标记之前。所以使用Session、Cookie以及Header的时候,会导致错误。系统会认为页面内容已经发送。

解决这个问题的办法是使用一些支持取消BOM标记的编辑工具,将BOM标记删除。

PHP5.0 属性与方法重载以及可能遇到的问题

PHP5支持更强大的重载了,通过覆盖__call、__get、__set方法,可以实现属性和方法的重载。利用PHP本身的动态特性,可以实现非常灵活的重载机制。

<?php
class Example {
        public function method1($arg1) {
                echo "This is method1 with argument {$arg1}\n";
        }
        public function method2($arg1, $arg2) {
                echo "This is method2 with argument {$arg1} and {$arg2}\n";
        }
        public function __call($method, $args) {
                $targetMethod = array($this, $method.count($args));
                if(is_callable($targetMethod)) {
                        call_user_func_array($targetMethod, $args);
                }
        }
        private $readonlyProperty = 100;
        public function __get($varName) {
                if(isset($this->$varName)) {
                        return $this->$varName;
                }
        }
}

$example = new Example();
$example->method(100);            //call method with 1 arg
$example->method(100, 200);       //call method with 2 args
echo $example->readonlyProperty//get and output the readonlyProperty
$example->readonlyProperty = 200; //try to set value for readonlyProperty will cause a problem

?>

我也开始在新的项目中尝试利用重载机制优化开发工作,但发现伴随而来的两个新问题。第一个问题是重载属性之后,PHP的empty函数不好用了。

echo empty($example->readonlyProperty)?'true':'false';

如果在上面的代码中增加这样一句,本来readonlyProperty确实存在,值也是非空的值(100),但是empty函数总是返回false。大概是因为empty函数是一个PHP编译后的函数,调用的时候不会触发__get方法执行,才导致这样的结果。

第二个问题是PHP的方法重载只支持实例方法重载,静态方法依然无法重载。

 

 

最近在PHP官方网站上找资料,发现在新的版本中,已经解决了上面所述的两个问题。从PHP5.1开始,新增__isset和__unset两个方法的重载,__isset会在调用PHP的检查空值函数empty或检查变量是否设置函数isset时触发,而__unset则由变量删除函数unset触发。从PHP5.3开始,新增__callStatic方法重载,支持重载静态方法。但是,到目前截止,PHP依然不支持重载类的静态属性。

参看:PHP Manual Overloading

Hello World

下面用我所了解的所有语言输出Hello, world! ,以后在这个博客大家还会看到这些语言。

PHP

<?php
echo "Hello, world!\n";
?>

 ActionScript

trace("Hello, world!");

Javascript

window.alert("Hello, world!");

 HTML

<h1>Hello, world!</h1><br />

 SQL

SELECT 'Hello, world!';

XML

<root>
    <item endline="true">
        Hello, world!
    </item>
</root>

C

#include <stdio.h>
int main(int argc, char ** argv) {
    printf("Hello, world!\n");
    return 0;
}

English

Hello, world!

开始欣的自由

这里是桄欣的技术博客。桄欣专注的领域为PHP语言、Ajax技术和Flash ActionScript技术。

本站的所有文字信息除特别说明的之外,都基于GFDL(GNU自由文档协议)发布;所有源代码除特别说明的外,都基于GPLv3(GNU通用公共许可协议第三版)发布。

请遵循以下条款:

1.您可以自由获取、复制、传播、修改和再次分发本站的文字资料和源代码。
2.您不能限制他人获取、复制、传播、修改和再次分发这些内容的自由。
3.您承诺仍然基于GFDL协议再次发布您修改后的文档,仍然基于GPLv3协议发布您修改后的源代码。