第一方面、通过上面的例子我们会发现,每一个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";
目录
也欢迎进行QQ联系本人 ,交流我在开发metaPHP过程中的经验
QQ:309568486