包开发
简介
包是主要作用是为Laravel添加功能。包可以是任何东西,例如用于日期处理的Carbon,或者是一个完整的BDD测试框架Behat。
当然,还有很多不同类型的包。有些包是独立的,这意味着它们可以在任何框架中工作,而不仅仅是Laravel。上面提到的Carbon和Behat就是独立的包。要在Laravel中使用这些包只需要在composer.json
文件中指明。
另一方面,有些包仅支持Laravel。在上一个Laravel版本中,这些类型的包我们称为"bundles"。这些包可以包含专为增强Laravel应用的路由、控制器、视图、配置和迁移。由于开发独立的包不需要专门的过程,因此,本手册主要涵盖针对Laravel开发独立的包。
所有Laravel包都是通过Packagist和Composer发布的,因此很有必要学习这些PHP包发布工具。
创建包
为Laravel创建一个包的最简单方式是使用Artisan的workbench
命令。首先,你需要在app/confg/workbench.php
文件中配置一些参数。在该文件中,你会看到name
和email
两个参数,这些值是用来为新创建的包生成composer.json
文件的。一旦你提供了这些值,就可以开始构建一个新包了!
执行Artisan中的Workbench命令
php artisan workbench vendor/package --resources
厂商名称(vendor name)是用来区分不同作者构建的相同名字的包。例如,如果我(Taylor Otwell)创建了个名为"Zapper"的包,厂商名就可以叫做Taylor
,包名可以叫做Zapper
。默认情况下,workbench命令建的包是不依赖任何框架的;然而,resources
命令将会告诉workbench创建特定于Laravel的一些目录,例如migrations
、views
、config
等。
一旦执行了workbench
命令,新创建的包就会出现在Laravel安装目录下的workbench
目录中。接下来就应该为你创建的包注册ServiceProvider
了。你可以通过在app/config/app.php
文件里的provides
数组中添加该包。这将通知Laravel在应用程序开始启动时加载该包。服务提供者(Service providers)使用[Package]ServiceProvider
样式的命名方式。所以,以上案例中,你需要将Taylor\Zapper\ZapperServiceProvider
添加到providers
数组。
一旦注册了provider,你就可以开始写代码了!然而,在此之前,建议你查看以下部分来了解更多关于包结构和开发流程的知识。
包结构
执行workbench
命令之后,你的包将被初始化规定的结构,并能够与laravel框架融合:
基本包目录结构
/src
/Vendor
/Package
PackageServiceProvider.php
/config
/lang
/migrations
/views
/tests
/public
让我们来深入了解该结构。src/Vendor/Package
目录是所有class的主目录,包括ServiceProvider
。config
、lang
、migrations
和views
目录,就如你所猜测,包含了相应的资源。包可以包含这些资源中的任意几个,就像一个"regular"的应用。
服务提供器
服务提供器只是包的引导类。默认情况下,他们包含两个方法:boot
和register
。你可以在这些方法内做任何事情,例如:包含路由文件、注册IoC容器的绑定、监听事件或者任何想做的事情。
register
方法在服务提供器注册时被立即调用,而boot
方法仅在请求被路由前调用。因此,如果服务提供器中的动作(action)依赖另一个已经注册的服务提供器,或者你正在覆盖另一个服务提供其绑定的服务,就应该使用boot
方法。
当使用workbench
命令创建包时,boot
方法已经包含了如下的动作:
$this->package('vendor/package');
该方法告诉Laravel如何为应用程序加载视图、配置或其他资源。通常情况下,你没有必要改变这行代码,因为它会根据workbench的默认约定将包设置好的。
默认情况下,一旦注册了一个包,那么它的资源可以通过package方法在vendor/package
中找到。你也可以向 package
方法中传入第二个参数来重写这个方法。例如:
// 向 `package` 方法中传入一个自定义的命名空间
$this->package('vendor/package', 'custom-namespace');
//那么,这个包的资源现在可以通过这个自定义的命名空间来访问
$view = View::make('custom-namespace::foo');
Laravel并没有为service provider
提供“默认”的存放地点。您可以根据自己的喜好,将它们放置在任何地方,您也可以将它们统一组织在一个Providers
命名空间里,并放置在应用的app
目录下。这些文件可以被放置在任何地方,只需保证Composer的自动加载组件知道如何加载这些类。
包约定
要使用包中的资源,例如配置或视图,需要用双冒号语法:
加载包中的视图
return View::make('package::view.name');
获取包的某个配置项
return Config::get('package::group.option');
如果你包中包含迁移,请为迁移名(migration name)添加包名作为前缀,以避免与其他包中的类名冲突。
开发流程
当开发一个包时,能够使用应用程序上文是相当有用的,这样将允许你很容易的解决视图模板的等问题。所以,我们开始,安装一个全新的Laravel框架,使用workbench
命令创建包结构。
在使用workbench
命令创建包后。workbench/[vendor]/[package]
目录使用git init
,git push
!这将允许你在应 用程序中方便开发而不用为composer update
命令苦扰。
当包存放在workbench
目录时,你可能担心Composer如何知道自动加载包文件。当workbench
目录存在,Laravel将智能扫描该目录,在应用程序开始时加载它们的Composer自动加载文件!
包路由
在之前的Laravel版本中,handlers
用来指定那个URI包会响应。然而,在Laravel4中,一个包可以相应任意URI。要在包中加载路由文件,只需在服务提供器的boot
方法include
它。
在服务提供器中包含路由文件
public function boot()
{
$this->package('vendor/package');
include __DIR__.'/../../routes.php';
}
包配置
有时创建的包可能会需要配置文件。这些配置文件应该和应用程序配置文件相同方法定义。并且,当使用 $this->package
方法来注册服务提供器时,那么就可以使用“双冒号”语法来访问:
访问包配置文件
Config::get('package::file.option');
然而,如果你包仅有一个配置文件,你可以简单命名为config.php
。当你这么做时,你可以直接访问该配置项,而不需要特别指明文件名:
访问包单一配置文件
Config::get('package::option');