Skip to content

包开发

介绍

包是向 Laravel 添加功能的主要方式。包可以是任何东西,从处理日期的优秀工具 Carbon,到像 Behat 这样的完整 BDD 测试框架。

当然,包有不同的类型。一些包是独立的,意味着它们可以与任何框架一起使用,而不仅仅是 Laravel。Carbon 和 Behat 都是独立包的例子。任何这些包都可以通过在 composer.json 文件中请求它们来与 Laravel 一起使用。

另一方面,其他包则专门用于 Laravel。在 Laravel 的早期版本中,这些类型的包被称为“捆绑包”。这些包可能具有路由、控制器、视图、配置和迁移,专门用于增强 Laravel 应用程序。由于开发独立包不需要特殊过程,因此本指南主要涵盖 Laravel 特定包的开发。

所有 Laravel 包都通过 PackagistComposer 分发,因此了解这些出色的 PHP 包分发工具是必不可少的。

创建一个包

创建一个新的 Laravel 包的最简单方法是使用 workbench Artisan 命令。首先,您需要在 app/config/workbench.php 文件中设置一些选项。在该文件中,您会找到 nameemail 选项。这些值将用于为您的新包生成 composer.json 文件。一旦您提供了这些值,您就可以开始构建工作台包了!

发出工作台 Artisan 命令

php
php artisan workbench vendor/package --resources

供应商名称是区分您包与其他作者的同名包的一种方式。例如,如果我(Taylor Otwell)要创建一个名为“Zapper”的新包,供应商名称可以是 Taylor,而包名称将是 Zapper。默认情况下,工作台将创建与框架无关的包;然而,resources 命令告诉工作台生成具有 Laravel 特定目录的包,例如 migrationsviewsconfig 等。

一旦执行了 workbench 命令,您的包将在 Laravel 安装的 workbench 目录中可用。接下来,您应该注册为您的包创建的 ServiceProvider。您可以通过将其添加到 app/config/app.php 文件中的 providers 数组来注册提供者。这将指示 Laravel 在应用程序启动时加载您的包。服务提供者使用 [Package]ServiceProvider 命名约定。因此,使用上面的示例,您将添加 Taylor\Zapper\ZapperServiceProviderproviders 数组中。

一旦提供者被注册,您就可以开始开发您的包了!但是,在深入之前,您可能希望查看下面的部分,以更熟悉包结构和开发工作流。

lightbulb

如果找不到您的服务提供者,请从应用程序的根目录运行 php artisan dump-autoload 命令。

包结构

使用 workbench 命令时,您的包将设置具有良好集成其他 Laravel 框架部分的约定:

基本包目录结构

php
/src
	/Vendor
		/Package
			PackageServiceProvider.php
	/config
	/lang
	/migrations
	/views
/tests
/public

让我们进一步探索这个结构。src/Vendor/Package 目录是您包所有类的家,包括 ServiceProviderconfiglangmigrationsviews 目录,正如您可能猜到的那样,包含您包的相应资源。包可以拥有这些资源,就像“常规”应用程序一样。

服务提供者

服务提供者只是包的引导类。默认情况下,它们包含两个方法:bootregister。在这些方法中,您可以做任何您想做的事情:包含路由文件、在 IoC 容器中注册绑定、附加到事件,或您希望做的任何其他事情。

register 方法在服务提供者注册时立即调用,而 boot 命令仅在请求被路由之前调用。因此,如果您服务提供者中的操作依赖于另一个服务提供者已经注册,或者您正在覆盖由另一个提供者绑定的服务,则应使用 boot 方法。

使用 workbench 创建包时,boot 命令将已经包含一个操作:

php
$this->package('vendor/package');

此方法允许 Laravel 知道如何正确加载视图、配置和其他资源。通常,您无需更改此行代码,因为它将使用工作台约定设置包。

默认情况下,在注册包后,其资源将使用 vendor/package 的“包”部分访问。然而,您可以将第二个参数传递给 package 方法以覆盖此行为。例如:

php
// 将自定义命名空间传递给包方法
$this->package('vendor/package', 'custom-namespace');

// 包资源现在通过自定义命名空间访问
$view = View::make('custom-namespace::foo');

服务提供者类没有“默认位置”。您可以将它们放在您喜欢的任何地方,可能在 app 目录中的 Providers 命名空间中组织。文件可以放在任何地方,只要 Composer 的 自动加载设施 知道如何加载类。

如果您更改了包资源的位置,例如配置文件或视图,您应该将第三个参数传递给 package 方法,指定资源的位置:

php
$this->package('vendor/package', null, '/path/to/resources');

延迟提供者

如果您正在编写一个不注册任何资源(如配置或视图)的服务提供者,您可以选择使您的提供者“延迟”。延迟服务提供者仅在应用程序 IoC 容器实际需要它提供的服务时加载和注册。如果在给定的请求周期中没有需要提供者的服务,则该提供者不会被加载。

要延迟执行您的服务提供者,请将提供者的 defer 属性设置为 true

php
protected $defer = true;

接下来,您应该从基础的 Illuminate\Support\ServiceProvider 类重写 provides 方法,并返回一个包含您提供者添加到 IoC 容器的所有绑定的数组。例如,如果您的提供者在 IoC 容器中注册了 package.servicepackage.another-service,则您的 provides 方法应如下所示:

php
public function provides()
{
	return array('package.service', 'package.another-service');
}

包约定

在使用包的资源时,例如配置项或视图,通常将使用双冒号语法:

从包加载视图

php
return View::make('package::view.name');

检索包配置项

php
return Config::get('package::group.option');
lightbulb

如果您的包包含迁移,请考虑在迁移名称前加上您的包名称,以避免与其他包的潜在类名冲突。

开发工作流

在开发包时,能够在应用程序的上下文中进行开发是很有用的,这样您可以轻松查看和实验您的模板等。因此,要开始,请安装一个新的 Laravel 框架副本,然后使用 workbench 命令创建您的包结构。

workbench 命令创建了您的包后,您可以从 workbench/[vendor]/[package] 目录中 git init 并直接从工作台 git push 您的包!这将允许您在应用程序上下文中方便地开发包,而不必被不断的 composer update 命令所困扰。

由于您的包位于 workbench 目录中,您可能想知道 Composer 如何知道自动加载您的包的文件。当 workbench 目录存在时,Laravel 将智能地扫描它以查找包,在应用程序启动时加载它们的 Composer 自动加载文件!

如果您需要重新生成包的自动加载文件,可以使用 php artisan dump-autoload 命令。此命令将为您的根项目以及您创建的任何工作台重新生成自动加载文件。

运行 Artisan 自动加载命令

php
php artisan dump-autoload

包路由

在 Laravel 的早期版本中,使用 handles 子句来指定包可以响应的 URI。然而,在 Laravel 4 中,包可以响应任何 URI。要为您的包加载路由文件,只需在服务提供者的 boot 方法中 include 它。

从服务提供者包含路由文件

php
public function boot()
{
	$this->package('vendor/package');

	include __DIR__.'/../../routes.php';
}
lightbulb

如果您的包使用控制器,您需要确保它们在 composer.json 文件的自动加载部分中正确配置。

包配置

访问包配置文件

一些包可能需要配置文件。这些文件应以与典型应用程序配置文件相同的方式定义。当使用默认的 $this->package 方法在服务提供者中注册资源时,可以使用通常的“双冒号”语法访问:

php
Config::get('package::file.option');

访问单文件包配置

但是,如果您的包包含单个配置文件,您可以简单地将文件命名为 config.php。这样做时,您可以直接访问选项,而无需指定文件名:

php
Config::get('package::option');

手动注册资源命名空间

有时,您可能希望在典型的 $this->package 方法之外注册包资源,例如视图。通常,这仅在资源不在常规位置时进行。要手动注册资源,您可以使用 ViewLangConfig 类的 addNamespace 方法:

php
View::addNamespace('package', __DIR__.'/path/to/views');

一旦命名空间被注册,您可以使用命名空间名称和“双冒号”语法访问资源:

php
return View::make('package::view.name');

addNamespace 的方法签名在 ViewLangConfig 类中是相同的。

级联配置文件

当其他开发人员安装您的包时,他们可能希望覆盖某些配置选项。然而,如果他们在您的包源代码中更改值,则在下次 Composer 更新包时将被覆盖。相反,应该使用 config:publish Artisan 命令:

php
php artisan config:publish vendor/package

当执行此命令时,您应用程序的配置文件将被复制到 app/config/packages/vendor/package,开发人员可以安全地修改它们!

lightbulb

开发人员还可以通过将环境特定的配置文件放置在 app/config/packages/vendor/package/environment 中,为您的包创建环境特定的配置文件。

包视图

如果您在应用程序中使用包,您可能偶尔希望自定义包的视图。您可以使用 view:publish Artisan 命令轻松导出包视图到您自己的 app/views 目录:

php
php artisan view:publish vendor/package

此命令将把包的视图移动到 app/views/packages 目录。如果该目录尚不存在,则在运行命令时将创建它。一旦视图被发布,您可以根据自己的喜好进行调整!导出的视图将自动优先于包自己的视图文件。

包迁移

为工作台包创建迁移

您可以轻松为任何包创建和运行迁移。要为工作台中的包创建迁移,请使用 --bench 选项:

php
php artisan migrate:make create_users_table --bench="vendor/package"

为工作台包运行迁移

php
php artisan migrate --bench="vendor/package"

为已安装包运行迁移

要为通过 Composer 安装到 vendor 目录的完成包运行迁移,您可以使用 --package 指令:

php
php artisan migrate --package="vendor/package"

包资产

将包资产移动到公共目录

一些包可能有资产,例如 JavaScript、CSS 和图像。然而,我们无法链接到 vendorworkbench 目录中的资产,因此我们需要一种方法将这些资产移动到应用程序的 public 目录。asset:publish 命令将为您处理此事:

php
php artisan asset:publish

php artisan asset:publish vendor/package

如果包仍在 workbench 中,请使用 --bench 指令:

php
php artisan asset:publish --bench="vendor/package"

此命令将根据供应商和包名称将资产移动到 public/packages 目录。因此,名为 userscape/kudos 的包将其资产移动到 public/packages/userscape/kudos。使用这种资产发布约定,您可以安全地在包的视图中编写资产路径。

发布包

当您的包准备发布时,您应该将包提交到 Packagist 存储库。如果包特定于 Laravel,请考虑在包的 composer.json 文件中添加 laravel 标签。

此外,标记您的版本是礼貌和有帮助的,这样开发人员在请求包时可以依赖稳定版本。如果稳定版本尚未准备好,请考虑使用 branch-alias Composer 指令。

一旦您的包发布,您可以继续在 workbench 创建的应用程序上下文中开发它。这是继续方便地开发包的好方法,即使在发布之后。

一些组织选择为自己的开发人员托管自己的私有包存储库。如果您对此感兴趣,请查看 Composer 团队提供的 Satis 项目的文档。