提高你的生产力
作者: Fabien Potencier 翻译:逗派
使用symfony本身是web开发人员提高生产力的好方法。当然,每个知道symfony的异常细节和web 调试工具条的人都可以很大程度的提高生产力。 本章将告诉你一些提示和技巧,通过使用一些新的或很少被人所知的功能来更高的提高你的生产力。
启动速度更快:自定义项目创建过程
通过symfony中CLI的工具,创建一个新的symfony的项目,是快速,简单:
$ php /path/to/symfony generate:project foo --orm=Doctrine
generate:project
任务为您生成新项目的默认目录结构,并创建设置合理的默认值的配置文件。然后,您可以使用symfony的任务创造应用系统,安装插件,配置你的模型等等。 但是,创建一个新项目的第一个步骤通常总是不尽相同:您创建一个主应用程序,安装一堆的插件,根据你的需求调整一些默认配置等等。 随着symfony 1.3构架,该项目创建过程可以自定义和自动化。
由于所有symfony的任务都是类,所以可以很容易定制和扩展他们。
但是generate:project
任务并不能很容易的自定义,因为当执行这个任务的时候,项目还没有存在。
generate:project
任务有一个--installer
选项,它可以指定在创建项目的过程中执行一个php脚本 :
$ php /path/to/symfony generate:project --installer=/somewhere/my_installer.php
/somewhere/my_installer.php脚本在
sfGenerateProjectTask
实例的环境下运行,所以可以通过使用 $this
对象来使用该任务的方法。 以下各节描述所有你可以用来自定义您的项目创建过程的方法。
如果你在php.ini中开启了include()方法的url file-access功能, 你甚至可以可以把URL作为参数传给--installer(当然当你使用了一个你完全不知道内容的脚本你需要非常小心):$ symfony generate:project --installer=http://example.com/sf_installer.php
installDir()
installDir()
方法映射一个目录结构(包括子目录和文件)到新建的项目中:
$this->installDir(dirname(__FILE__).'/skeleton');
runTask()
runTask()
方法执行一个symfony任务。 它需要一个任务名称,一个作为任务的参数和选项的字符串两个参数:
$this->runTask('configure:author', "'Fabien Potencier'");
参数和选项也可以使用数组传递:
$this->runTask('configure:author', array('author' => 'Fabien Potencier'));
正如期望的,symfony任务的简写也可以使用:$this->runTask('cc');
这个方法当然可以用来安装插件:
$this->runTask('plugin:install', 'sfDoctrineGuardPlugin');
为了安装特定版本的插件,只需要传递必要的选项就可以了:
$this->runTask('plugin:install', 'sfDoctrineGuardPlugin', array('release' => '10.0.0', 'stability' => beta'));
为了执行一个新安装的插件里的任务,首先需要重新加载任务:$this->reloadTasks();
如果你创建了一个新的应用程序,想使用一个依赖特定应用程序的任务,像generate:module,你一定要自己手动变换配置环境:
$this->setConfiguration($this->createConfiguration('frontend', 'dev'));
日志
在安装脚本运行时为了给开发者回馈信息,您可以将一些东西很容易的写入日志中:
// 一个简单日志
$this->log('some installation message');
// 记录一个日志块
$this->logBlock('Fabien\'s Crazy Installer', 'ERROR_LARGE');
// 记录一个日志模块
$this->logSection('install', 'install some crazy files');
用户交互
askConfirmation()
, askAndValidate()
和 ask()
方法允许你问问题,使得你的安装过程可以动态配置。 如果你只需要确认,请使用 askConfirmation()
方法:
if (!$this->askConfirmation('Are you sure you want to run this crazy installer?'))
{
$this->logSection('install', 'You made the right choice!');
return;
}
通过使用ask()方法你也可以问任何问题,并获得一个字符串代表的用户答案:
$secret = $this->ask('Give a unique string for the CSRF secret:');
如果你想验证答案,使用askAndValidate()
方法:
$validator = new sfValidatorEmail(array(), array('invalid' => 'hmmm, it does not look like an email!'));
$email = $this->askAndValidate('Please, give me your email:', $validator);
文件系统操作
如果你想改变文件系统,你可以通过symfony的文件系统对象:
$this->getFilesystem()->...();
Sandbox应用的创建过程 symfony sandbox是一个预先打包的symfony项目,包括一个现成的应用程序和预先设定的SQLite数据库。任何人可以通过使用安装脚本创建一个sandbox :$ php symfony generate:project --installer=/path/to/symfony/data/bin/sandbox_installer.php
symfony/data/bin/sandbox_installer.php
脚本是一个安装脚本的实际例子,值得一读。
安装脚本只是一个php脚本文件。所以,你可以做任何你想做的事情 。不象创建一个新项目时一而在再而三执行相同的任务,您可以创建自己的安装程序脚本,调整成您想要的symfony项目安装方式。 通过安装程序创建一个新的项目要快得多,并防止丢失步骤。您甚至可以与他人分享您的安装脚本!
在 第六章 , 我们将使用一个自定义的安装脚本。 你可以 附件 B 中找到源代码。
更快的开发
从PHP代码到CLI任务,编程意味着无尽的敲打键盘。让我们看看如何把输入降低至最低限度。
选择你的IDE
使用IDE能够帮助开发者在从多种的途径提高效率。 首先,绝大多数的现代化IDE提供PHP的自动完成功能。这意味着你只要打一个方法名字的开始几个字母。这也意味这即使你不记得方法的名字,你也不用去查询API文档,因为IDE会提示当前对象的所有可用方法。 此外,有的像PHPEdit或NetBeans的IDE,了解了更多的Symfony,能够对symfony的项目提供更具体的集成。
文本编辑器 有些用户更喜欢文本编辑器来编写代码,主要原因是文本编辑器比IDE快很多。 当然,文本编辑器没有提供IDE那么多的功能。但是绝大多数流行的编辑器,也提供插件或扩展用于增强用户体验,使得编辑PHP和symfony项目更加的有效。 比如,很多Linux用户倾向于使用VIM来工作。对于这些开发者,可以使用 vim-symfony 扩展。 VIM-symfony 是一系列VIM脚本把symony集成到你喜爱的编辑器中。使用vim-symfony, 你可以容易的创建vim宏和命令来简化你的symfony开发。它还捆绑了默认的命令集,许多配置文件(模式,路由等)也是触手可及,使您可以轻松地从 action切换到template。 有些MacOS X用户喜欢使用TextMate。这些开发者可以安装 symfony bundle , 它添加了很多日常开发中省时的宏和快捷方式。
使用支持symfony的IDE
有些IDE,比如 PHPEdit 3.4 和 NetBeans 6.8 , 本身支持symfony,所以给框架提供了精细粒度的集成。看看它们的文档,了解他们的symfony中的具体支持,以及如何可以帮助你更快地发展。
帮助IDE
在IDE自动完成PHP的只能是明确的,在PHP代码中定义的方法。但是如果你的代码使用了 __call()
或 __get()
魔法方法,IDE就没有办法猜测可用的方法或属性。好消息是,你可以在PHPDoc块中提供方法和/或属性来帮助IDE(通过使用@method和@propterty标签) 比如我们有一个Message
类拥有一个动态属性 (message
) 和一个动态方法 (getMessage()
)。 下面的代码向你展示怎样让IDE知道这些信息,而不需要在PHP代码中明确申明:
/**
* @property clob $message
*
* @method clob getMessage() Returns the current message value
*/
class Message
{
public function __get()
{
// ...
}
public function __call()
{
// ...
}
}
即使 实际的getMessage()
方法不存在, 由于 @method
标签IDE还是能识别这个方法。 对于message属性也是同样的原理,因为我们添加了
@property
标签。 这个技术已经在doctrine:build-model
任务中使用了。比如,一个有两列(message
和 priority
)的Doctrine MailMessage
类看起来像下面代码:
/**
* BaseMailMessage
*
* This class has been auto-generated by the Doctrine ORM Framework
*
* @property clob $message
* @property integer $priority
*
* @method clob getMessage() Returns the current record's "message" value
* @method integer getPriority() Returns the current record's "priority" value
* @method MailMessage setMessage() Sets the current record's "message" value
* @method MailMessage setPriority() Sets the current record's "priority" value
*
* @package ##PACKAGE##
* @subpackage ##SUBPACKAGE##
* @author ##NAME## <##EMAIL##>
* @version SVN: $Id: Builder.php 6508 2009-10-14 06:28:49Z jwage $
*/
abstract class BaseMailMessage extends sfDoctrineRecord
{
public function setTableDefinition()
{
$this->setTableName('mail_message');
$this->hasColumn('message', 'clob', null, array(
'type' => 'clob',
'notnull' => true,
));
$this->hasColumn('priority', 'integer', null, array(
'type' => 'integer',
));
}
public function setUp()
{
parent::setUp();
$timestampable0 = new Doctrine_Template_Timestampable();
$this->actAs($timestampable0);
}
}
更快的查询文档
由于symfony是一个有丰富功能的大框架,记得所有可能的配置,或所有你要使用的类和方法是非常困难的。正如我们已经看到过,使用IDE可以提供你非常强大的自动完成功能。让我们探索如何利用现有的工具来尽可能快地找到可能的答案。
在线API
最快的方式找到一个类或方法的文档是在线浏览 API . 更有趣的是系统内建的API搜索引擎。搜索允许你只用几个字母就可以快速找到一个类和方法。在API页面的搜索框输入几个字母,一个带有有用提示的快速搜索框会实时出现。 你可以通过输入类名的开头来搜索: 或者一个方法的名称:
或者一个类名加
::来列出所有可用方法:
或者再添加方法名的开头来提炼可能结果:
如果你想列出一个包所有的类,只要输入包名,提交请求就可以了。 你甚至可以集成symfony API搜索到你的浏览器种。这样,你甚至不需要访问symfony网站就能查找。这是因为symfony API搜索本身提供了 OpenSearch 支持. 如果你使用Firefox, symfony API搜索引擎会在搜索引擎菜单自动出现。你也可以点击在API文档上的 "API OpenSearch" 链接来添加到你的浏览器搜索框。
你可以在这个 博客 上查看截图,展示symfony api搜索引擎使如何很好的集成到Firefox中的。
备忘单
如果你想快速查看框架主要部分的信息,很多备忘单 可供你选择:
- Directory Structure and CLI
- View
- View: Partials, Components, Slots and Component Slots
- Lime Unit & Functional Testing
- ORM
- Propel
- Propel Schema
- Doctrine
有些备忘单还没有更新到symfony1.3
离线文档
关于配置的问题最好的答案是symfony参考指南。这是一本任何时候你用symfony开发时都需要放在身边的书。感谢非常详细的目录,术语的索引,夸章节引用等,这本书是找到每个可用配置的最快方法。你可以浏览在线版本 ,买一本打印版本 ,设置下载一个PDF
版本
在线工具
正如本章开始看到的,symfony中提供了一个很好的工具集来帮助您更快得开始。 最后,您将完成您的项目,并在一段时间后将其部署到生产。 要检查您的项目是否已经部署就绪,可以使用在线部署清单 。 这个网站涵盖了你在产品上线前需要全都检查得重点。
更快的调试
当在开发环境下出现错误的时候,symfony展现一个包涵了有用信息的异常页面。例如你可以查看堆栈跟踪信息和已执行的文件,如果你设了在settings.yml
(看下面的代码) 配置文件中设置了sf_file_link_format
, 你甚至可以点击文件名,对应的文件就会在你喜欢的文本编辑器或IDE中打开。虽然这是一个在你调试问题时可以帮你节约很多时间的小功能,是一个非常棒的例子,。
当设置了
sf_file_link_format参数,
在Web调试工具条上的日志和可视面板显示的文件名(尤其当启用了XDebug)也可以点击。
默认情况下, sf_file_link_format
是空的。symfony将把php配置文件中 xdebug.file_link_format
的值重新设为默认值。(在php.ini中设置
xdebug.file_link_format
允许现在的XDebug版本在堆栈跟踪添加所有文件的链接)。 sf_file_link_format
的值根据你的IDE和操作系统不同而不同。比如,如果你想在TextMate中打开,添加下面的代码到settings.yml
中:
dev: .settings: file_link_format: txmt://open?url=file://%f&line=%l
%f
占位符会由symfony替换位文件的绝对路径, %l
占位符由行号取代。 如果你使用VIM,在网上有更多的关于 symfony 和 XDebug 的描述。
使用搜索引擎来学习配置你的IDE。你也可以通过同样的方式来查找关于sf_file_link_format
或xdebug.file_link_format
的配置。
更快的测试
记录你的功能测试
功能测试模拟用户的交互行为,以便全面测试集成的所有应用程序块。写功能测试虽然简单,但非常耗时。不过,每一个功能测试文件就是模拟用户浏览您的网站的 一个场景,因为浏览网站比写php代码要快的多,如果你能够记录浏览的过程,并自动转换成php代码呢?谢天谢地,symfony中有这样的插件。它被称 为swFunctionalTestGenerationPlugin,它让你在几分钟内产生一个现成的可自定义的测试框架。当然,你仍然需要添加适当的 测试使之有用,但这仍然节省了大量时间。 该插件通过注册symfony过滤器(filter),拦截所有请求,并将其转换为功能测试代码。按通常的方式安装插件后,你需要启用它。打开您应用程序 的filters.yml文件并在注释行后添加下面的内容:
functional_test: class: swFilterFunctionalTest
接下来,在你ProjectConfiguration
类中启用插件:
// config/ProjectConfiguration.class.php
class ProjectConfiguration extends sfProjectConfiguration
{
public function setup()
{
// ...
$this->enablePlugin('swFunctionalTestGenerationPlugin');
}
}
因 为插件使用web调试工具条作为它的主要用户界面,请务必将它激活(在默认开发环境情况下是激活的)当启用时,一个新的菜单名为“Functional Test”在工具条上出现。在这个面板上,您就可以点击“激活(Activate)”链接来开始录制,点击“重置(Reset)”按钮重新开始录制。当您 完成了,复制并粘贴textarea中代码到一个测试文件,并开始对其进行自定义。
更快的运行测试套件
当你有一个大的测试套件,每次您更改后运行所有测试将是非常耗时的,尤其是当一些测试失败了。每次您修复一个测试,你应该运行整个测试套件以确保你没有破坏其他测试。但是直到失败的测试被修复了,否则就没有必要重新执行所有的测试。为了加速这个过程, test:all
任务有一个 --only-failed
(可以简写为-f
)选项,可以强制只执行上次测试失败的用例:
$ php symfony test:all --only-failed
在第一次执行时,所有的测试都正常运行。但随后的测试,只运行上次失败的测试。当您修复您的代码时,一些测试会通过,并从随后的测试中删除。当所有的测试都通过的时候,所有的测试会被重新运行...然后你就重复这样的过程。