5.7. 添加自己的组件和修饰

5.7.1. 新建组件
5.7.2. 新建修饰

当mint满足不了你的需求时,你可以很方便地扩充它。

5.7.1. 新建组件

新建组件可以分为两步

  1. 新建组件类,必须实现接口 IMintComponent ,它定义了四个方法。现在不必直接实现它,只须实现抽象类IAbstractMintComponent就可以了,这个抽象类含有很多有用的方法,可以帮助我们轻松处理DOM节点。

  2. 添加组件类,并给它命名,让mint知道该组件的存在。

完成这两步之后就可以直接在模板中使用了。

让我们先创建一个简单的组件。

例 5.4. MyComponent - 自定义的组件类

class MyComponent extends IAbstractMintComponent {
    
//定义支持的参数
    
public function getSupportedParameters() {
        return array(
"i""j");
    }
    
    
//处理组件
    
public function processComponent() {
        
$params $this->getParameters();
        if (!isset(
$params["i"]) || !isset($params["j"])) {
            return 
false// 不执行任何操作
        
}
        
$i $params["i"];
        
$j $params["j"];
        
$this->addFirstChildText($i $j); // 在节点的第一个子元素前加一个数字
        
return true;
    }    
}

该组件实现了IAbstractMintComponent定义的两个抽象方法 getSupportedParameters 和 processComponent,前者定义了我们的组件可以接受的参数名列表(i和j),后者处理组件,只是简单的获取参数值,并将结果附加到当前节点的第一个子节点之前。现在添加组件,并使用IModelAndTemplate视图方案:

    public function appIndex() {
        
IMint::setOptions(array("template-dir"=>"./template""compile-dir"=>"./compile-dir""mode"=>"debug"));
        
        
//添加组件
        
IMint::addComponentProcessor("@my""MyComponent");
        
        return new 
IModelAndTemplate($this"test");
    }

我们把组件命名为@my,以@开头只是我们的习惯,并不是必须的。

注意

这里我们使用了$this作为数据模型传入了IModelAndTemplate,这是为了很方便地加入新的对象,无需再新建一个对象容器。

现在在模板中使用组件:

<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
    <title>test</title>
</head>
<body>
<span com="@my" i="2" j="1.6"></span>
</body>
</html>

分析结果为:

<span>3.6</span>


正好符合我们的期望。使用

<span com="@my" i="20" j="1.6"></span>

得到的结果是

<span>21.6</span>

在这个例子中,我们的i和j两个参数都是固定的,如果换成变量会怎么样?你可能期望也能正常工作,但事实上不是的,mint在第一次编译之后,除非在debug模式下,否则就不再调用任何组件,因为我们已经从模板中编译出一个已经能工作的.php文件,无需再次分析。也就是说组件只在第一次分析模板的时候是有用的,processComponent方法对同一个组件来说只被调用一次,所以即时你多次传入不同的变量也只能得到第一次的结果。庆幸的是,我们可以在processComponent中给编译文件加入一些PHP代码,让编译文件在运行期决定怎么处理变量。现在改造上面的例子

例 5.5. MyComponent2 - 升级版

class MyComponent2 extends IAbstractMintComponent {
    
//定义支持的参数
    
public function getSupportedParameters() {
        return array(
"i""j");
    }
    
    
//处理组件
    
public function processComponent() {
        
$params $this->getParameters();
        if (!isset(
$params["i"]) || !isset($params["j"])) {
            return 
false// 不执行任何操作
        
}
        
$i IMintVariable::getDefinition($params["i"]); // 这时候得到的是变量名
        
$j IMintVariable::getDefinition($params["j"]);
        
$this->addFirstChildText("<?php echo {$i}+{$j};?>"); // 哇,我们加入了PHP代码 。。。
        
return true;
    }    
}

修改appIndex方法

    public function appIndex() {
        
IMint::setOptions(array("template-dir"=>".""compile-dir"=> "./compile-dir""mode"=>"debug"));
        
        
//添加组件
        
IMint::addComponentProcessor("@my""MyComponent");
        
IMint::addComponentProcessor("@my2""MyComponent2");
        
        
$this->2;
        
$this->1.6;
        
        return new 
IModelAndTemplate($this"test");
    }

修改模板

<span com="@my2" i="$i" j="$j"></span>

原来的常量变成了i和j两个变量,并可以由appIndex方法传入,现在的分析结果同样是

<span>3.6</span>

现在你就可以在appIndex方法中随意改变$this->i和$this->j的值了,每一次浏览器上将输出不同的值。


5.7.2. 新建修饰

正如我们上面所说,任何系统函数和用户自定义函数都可以作为修饰,它把mint变量当作第一个参数传入。

对于程序

    $this->string "abcdefg";
    
$this->array = array(1234);

可以使用

{$string|strlen}
{$array|count}
{$array|array_sum}

可以分别得到7、4和10三个数字。我们可以随意再定义一个针对数组的处理函数:

function myjoin(array $array$char) {
    return 
implode($char$array);
}

然后在模板中使用它:

{$array|myjoin('a')}

传入了一个参数“a”作为连接字符,分析结果为:

1a2a3a4

当然了,你可以让myjoin接受更多的参数,只需在使用的使用用分号分隔开来即可。

还可以通过使用OO的方式加入一个新的修饰,先定义MyJoinModifier类,它继承自IAbstractMintModifier,并实现了IMintModifier接口定义的__construct和execute两个方法:

class MyJoinModifier extends IAbstractMintModifier  {
    public function 
__construct() {
        
//do nothing
    
}
    
    public function 
execute() {
        
$arguments $this->getArguments();
        
$char = isset($arguments[0])?$arguments[0]:" ";
        return 
implode($char$this->getVariable());
    }
}

然后在使用它之前调用

IMint::addModifierProcessor("myjoin""MyJoinModifier");

添加一个修饰并把它命名为myjoin即可。