过去的一个月很艰难,但现在我的最后两门数学考试终于结束了,我将散乱的脑力活动集中在 JDevTools 上,试图弥补在复习格林公式等时的失去的时间。幸运的是,时间并没有完全浪费,因为我已经养成了习惯,每天早上步行5公里去学校,沿着莱芒湖边思考项目,以及我一旦可以再次编码时会如何攻击它。
在这个阶段,一个特别有趣的议题是脚本引擎。正如许多人所希望知道的,JDevTools 旨在让开发者的生活更轻松,减少 Joomla 开发的繁琐工作。为了为高级用户提供一个灵活的系统,我和我的导师决定开发一个脚本系统,并为那些愿意走捷径的人提供一批预制的脚本。然而,一个脚本系统需要易于使用和扩展,才能发挥作用,但如果它不够强大,就不会那么有用。我旨在实现这两点,但如何达到目标是我最近一直在思考的问题。
我保证今天不会深入细节。那些将留待我实际有一个运行良好的机器时再展示。相反,我会稍微思考一下在 PHP 中创建脚本引擎的挑战,以及到目前为止我通常是如何应对这些挑战的。
PHP 或非 PHP
我首先要回答的问题是,脚本应该由 PHP 代码组成,还是完全由其他东西制成。XML,正如在 Joomla 中用于参数一样,可以是编写脚本的另一种格式的良好示例,另一种脚本形式肯定有优势,因为不会受到 PHP 语法的影响,因此更加简洁。
让脚本由php代码组成的一个优点是,使用JDevTools的开发者(希望)已经熟悉php,这最小化了语法错误的可能性。另一个巨大优点是,为了解析php脚本,我唯一需要做的是将其写入临时文件并包含它。就这样,大量潜在的讨厌的错误被排除了。挑战仍然在于在PHP解析的限制内使脚本尽可能可用。
代码风格 -> 代码片段
在相当多的Web项目中使用过javascript之后,我对JQuery及其使用面向对象的属性将方法串联起来的方式产生了极大的敬意。对于不熟悉JQuery的人来说,这里有一个虚构的例子
$script->component("blip")->addView("blop")->addController("Blyp")->to("Blyp")->addTask("edit");
// 添加一个名为 "blip" 的组件,具有名为 "blop" 的视图和标识符为 "blyp" 的控制器;
// go() 将我们带到控制器,然后我们向其中添加一个任务 "edit"。
这个例子可能有点造作,但总的来说,我发现这种编码风格既有非常紧凑的优点,也非常容易理解。从左到右对组件执行的动作路径非常清晰。这种方法另一个优点是将方法分离成小的简单函数,减少了更改事物所需的参数数量。这是我学习新语法时经常感到困惑的地方。
我应该提到,这只是一个例子,虽然我已经为这个功能写下了代码,但随着时间的推移,名称和参数可能会发生变化。
代码风格 -> 块
如果所有内容都必须串联在另一个方法的末尾,那么在一个大的脚本中,脚本很快就会变得混乱,所以我想让开发者能够简单地将代码拆分为块,并在稍后组合它们。例如,如果我们想在自己的块中声明一个数据库表,我们会这样做
$table = JDevTools::Database();
$table->addRow("id","int")->auto_increment()->unsigned();
$table->addRow("name","text")->default("Giorgio Moroder");
如果我们然后想将这个表添加到名为 "blip" 的组件中,我们可以这样做
$script->to("blip")->setTable($table);
这样,就可以简单地将脚本的各个部分拆分为功能块,并在相关时将它们组合在一起。这使得结构化脚本变得容易,也使其他人更容易理解大型脚本的逻辑流程。
模块化
所有这些方法都需要在某处声明,而且不应该需要编辑10个地方的代码来添加一个新方法到数据库。这可能对编写脚本的开发者来说并不直接相关,但对于我们这些将编写要在JDevTools中使用的方法的人来说,有一个简单且一致的方法来编写和添加它们到代码中是非常重要的。为此,我发现了PHP的魔术方法非常有用。通常,当向类中添加方法时,需要编辑类所在文件以实现该方法,这很快会使文件膨胀得无法置信。幸运的是,使用魔术方法__call(),我可以为处理不存在方法的调用创建一个标准方法。__call()接受两个参数,被调用方法的名字和参数数组。
在我的情况下,我检查一个名为 'methods' 的子文件夹,看是否存在名为调用方法的文件。如果存在这样一个文件,我包含这个文件并在文件中创建一个同名类的实例,将__call()方法接收到的参数传递给类的构造器。这是一种非常漂亮的分离功能的方式,因为我们想要使用的每个方法现在都位于自己的文件中,包含在自己的类中。
结果如何呢?
目前仍在进行中,但到目前为止进展得相当不错。我希望能在这周内运行几个测试方法,以排除错误和虫子。之后,我应该会有一个稳固的路径来专注于为大多数常见任务编写一系列可靠的方法,当这些方法完成后,应该就是将它们串联起来,从中得到一些有用的东西。