修改已有代码

第一方面、通过上面的例子我们会发现,每一个metaPHP元代码,都是对应的php代码的长度的两倍以上,这意味着如果用metaPHP从0开始编写一个较大的代码,那么是一个不小的工作量。

第二方面、我们有大量的需求是在已有代码的基础上做出修改。

这时候我们需要在一部分php代码的基础上去做扩展和修改,而不是从0开始,是一种方便的方法,下面我们回到第一张Hello World的那个例子。

<?php
include './metaPHP/include.php';//引入metaPHP
$metaApi = new phpInterpreter('');//下面开始讲解这个函数的参数

//输出hello World的代码的结构,可以理解为下面的复合数组形式
$metaApi->codeMeta = array(
    'type'=>'window',
    'child'=>array(
        array(
            'type'=>'phpBegin'
        ),
        array(
            'type'=>'echo',
            'value'=>array(
                'type'=>'string',
                'data'=>'Hello World',
            ),
        )
    ),
);
print_r($metaApi->getCode());//获得生成的php代码

 

 

phpInterpreter的参数就是传入一段php代码,这时候生成的对象会自动带有这段php代码的codeMata。我们只需在已生成的codeMeta属性的基础上做修改,就能完成我们想要的,例如刚才的例子可以简化为。

<?php
include './metaPHP/include.php';//引入metaPHP
$metaApi = new phpInterpreter('<?php 
echo "Hello World";
');//下面开始讲解这个函数的参数

print_r($metaApi->codeMeta);
print_r($metaApi->getCode());//获得生成的php代码

 

运行结果

这时,我们可以对codeMeta进行修改,用来得到新的元代码,继而生成新的php代码

例如,我们修改codeMeta对象

<?php
include './metaPHP/include.php';
$metaApi = new phpInterpreter('<?php
echo "Hello World";
');
print_r($metaApi->codeMeta);
$metaApi->codeMeta['child'][1]['value']['data'] = 'Hello Meta';
echo($metaApi->getCode());//获得生成的php代码 

 

那么左后echo的结果是

不过用$metaApi->codeMeta['child'][1]['value']['data']定位修改点确实很不方便,尤其是[1]这种形式,随便修改一点代码就会导致这么定位找不到了。如果是大型文档,层次结构会很多,那么用数组键一步步定位,会有很多问题

这时我们会用到search方法

 

<?php
include './metaPHP/include.php';
$metaApi = new phpInterpreter('<?php
echo "Hello World";
');

$echoObj = $metaApi->search('.echo value')->toArray();
print_r($echoObj);

$echoObj[0]['data'] = 'Hello Meta';

echo($metaApi->getCode());//获得生成的php代码

运算结果如下

这个选择器的值是【.echo value】

整个选择器是一个字符串,用空格隔开就是代表一层一层的选择子元素

这里遇到了【.】运算符,是type过滤运算符,【.】后面跟的名字echo,【.echo】就是找到type=echo的元素

value代表的是找到key为【value】属性

那么【.echo value】整个这一句话的意思就是找到type等于echo的元素,它的value属性

返回值是一个数组,因为任何一个选择器有匹配中多个结构,(本例中只匹配中一个)。

所以用[0]代表找到的第一个结构,修改data的值

$echoObj[0]['data'] = 'Hello Meta';

这时候再次getCode方法就能生成新的代码


 

选择器中有很多种匹配符,如刚才我们提到的【.】匹配符代表type=后面的值

匹配符 含义    
. type匹配    
# name匹配    
[属性=值] 其他属性匹配    
       

 

过滤器:filter,刚才说到选择器会匹配中多个元素,有时候只有部分才是我们想要的,所以我们需要对结果进行过滤

如下:

$metaApi = new phpInterpreter('<?php
$word1 = "Hello World";
$word2 = "other Word";
');

 

这时生成的元代码结果如下

Array
(
    [type] => window
    [child] => Array
        (
            [0] => Array
                (
                    [type] => phpBegin
                )
            [1] => Array
                (
                    [type] => =
                    [object1] => Array
                        (
                            [type] => variable
                            [name] => $word1
                        )
                    [object2] => Array
                        (
                            [type] => string
                            [borderStr] => "
                            [data] => Hello World
                        )
                )
            [2] => Array
                (
                    [type] => =
                    [object1] => Array
                        (
                            [type] => variable
                            [name] => $word2
                        )
                    [object2] => Array
                        (
                            [type] => string
                            [borderStr] => "
                            [data] => other Word
                        )
                )
        )
)

 

我们想给$word2的值进行修改,如果我们只是过滤【=】赋值,被赋值的对象

$echoObj = $metaApi->search('.= object1')->toArray();

 

 

echoObj将会得到两个值(因为有两个【.=】运算)

这时候我们用:filter过滤一下。filter的语法是【:filter(过滤字符串)】

$metaApi->search('.= object1:filter([name=$word2])')->toArray();

这时候得到的值是只要一个了

别忘了我们的初衷是修改$word2的值,这时候需要获取刚才过滤对象的浮层对象的object2才行。

我们在执行完search方法后,在toArray之前,可以链式操作添加一个parent()方法

<?php
include './metaPHP/include.php';
$metaApi = new phpInterpreter('<?php
    $word1 = "Hello World";
    $word2 = "other Word";
');

$echoObj = $metaApi->search('.= object1:filter([name=$word2])')->parent()->toArray();
print_r($echoObj);exit;

就可以得到所有刚刚选择器选出来的备选结构的父亲一层结构。依然是个数组,因为选择器选择的不止一个,所以parent有时也会对应多个

那么我们对这个结构进行修改

<?php
include './metaPHP/include.php';
$metaApi = new phpInterpreter('<?php
    $word1 = "Hello World";
    $word2 = "other Word";
');

$echoObj = $metaApi->search('.= object1:filter([name=$word2])')->parent()->toArray();
$echoObj[0]['object2']['data'] = 'new World';

echo($metaApi->getCode());//获得生成的php代码

 

那么最终就生成了对应的新的php代码

<?php
$word1="Hello World";
$word2="new World";

 

刚刚的代码很完美,只不过又遇到了层级的数组键取值['object']['data'],如果遇到复杂的情况,依旧是不方便。metaPHP提供了单独的针对结构的选择器功能,metaSearch类,和phpInterpreter的search方法拥有一样的选择器引擎。可以方便的供你在复杂的结构中筛选出想要的

<?php
include './metaPHP/include.php';
$metaApi = new phpInterpreter('<?php
    $word1 = "Hello World";
    $word2 = "other Word";
');

$echoObj = $metaApi->search('.= object1:filter([name=$word2])')->parent()->toArray();

$rewriteDataApi = new metaSearch($echoObj[0]);  //把被查询的结构丢里面(注意[0])
//根据选择器查找【object2 data】
$rewriteData = $rewriteDataApi->search('object2 data')->toArray();

$rewriteData[0] = 'new World';  //注意,所有选择器返回的都是数组形式,别忘了[0]修改某一项
echo($metaApi->getCode());      //获得生成的php代码

 

metaSearch构造函数接收一个meta结构,我们传入刚才筛选出来的$echoObj,然后再调用search方法得到修改的目标object2 data,然后修改目标为'new World'。

注意所有的选择器返回都是一组数组结构,即使你只找到一个结果,也会是以数组的形式返回一组结构,只不过数组中只要一个结构。在使用时经常忘记添加[0]去得到这个最终的结构

生成的代码为

<?php
$word1="Hello World";
$word2="new World";

 

 

目录

引擎介绍

元代码结构

metaPHP数组的使用

函数的使用

类的定义和使用

杂七杂八的

修改已有代码

 

也欢迎进行QQ联系本人 ,交流我在开发metaPHP过程中的经验

QQ:309568486

posted @ 2017-09-25 17:32  浩然哥哥v5  阅读(473)  评论(0编辑  收藏  举报