如何在本地开发环境中设置测试你的扩展包类或工具,以在本地Laravel项目中进行测试。
一个示例Laravel项目可以在这个GitHub仓库中找到。
你可能会惊讶地发现,我们开发网络工具时使用了数百个扩展包。要获取它们,你只需访问一个包管理器,比如 Packagist
,在2023年10月时有382,000个。
如果你想开发自己的扩展包,合理地想知道如何在真实条件下测试它。在开发过程中在 Packagist
上发布扩展包不是一个选择。另一个方法是不使用 Composer
将它集成到一个新项目中。本文中的方法紧密结合了真实场景,但也需要一些环境设置。
创建一个文件夹,这将作为你扩展包的基础。
mkdir package
创建一个 composer.json
文件,这是扩展包必不可少的基石。
package/composer.json
{
"name": "capsulescodes/package",
"description": "Capsules Codes Package",
"type": "library",
"autoload": { "psr-4" : { "CapsulesCodes\\Package\\" : "src/" } }
}
-
name
: 名称应该采用“实体”在左边,“包名”在右边的结构。强烈建议使用描述性的包名,以便于用户搜索。 -
description
: 扩展包描述应该是清晰简练的。 -
type
: 有4种类型:“library
”,“project
”- "metapackage
", 和 "composer-plugin
"。其中 "library
" 是最常用的。《project》代表一个项目,如框架模板。 -
autoload
: 这是我们的包的核心元素,定义了一个命名空间来访问位于项目根目录的数据。类的自动加载规范协议由PSR-4
定义。这是一个关键步骤。一定要包含 "\\
",尤其是在语句的末尾。
建议确保name
信息与namespace
匹配。此外,建议使用src
作为项目根目录的文件夹名称。
此外,如果您在一个不包含composer.json
文件的文件夹中运行composer init
,则会通过向导引导您创建自己的composer.json
文件。
在package
文件夹内创建一个名为src
的文件夹。
cd package
mkdir src
- 文件排列并不重要,但文件之间的间距对您和本文都非常重要。
创建一个名为Greeter
的PHP类,其中包含一个返回短语Hello world!
的greet
函数。
package/src/Greeter.php
<?php
namespace CapsulesCodes\Package;
class Greeter
{
public function greet() : string
{
return "Hello world!";
}
}
- 请记住标注
namespace
。否则,类将无法被找到。
现在可以测试这个包了。为此,需要使用Laravel
模板项目创建一个测试环境。
返回到package
的父目录并创建一个作为测试的template
Laravel
项目。
cd ../../
composer create-project laravel/laravel template
composer create-project laravel/laravel template
命令在此生成了一个'type': 'project'
。
为了告诉template
我们的包位于同一父文件夹中,需要在composer.json
文件中添加两条信息。
template/composer.json
...
"minimum-stability": "dev",
"repositories": [ { "type" : "path", "url" : "../package" } ]
...
-
minimum-stability
:这个选项允许通过composer
安装包而不生成异常。当包不是stable
时,这是必要的,在本例中,我们的包目前处于dev
状态。 -
repositories
:此数组允许添加路径让composer
在本地查找包时参照。 -
type
:目录类型可以是composer
、package
、vcs
或path
。path
选项允许本地使用包,而vcs
选项允许通过版本控制系统(如Github)使用包。
现在可以安装我们新的包了。
composer require capsulescodes/package
现在它列在require
依赖项中。
package/composer.json
"require": {
...
"capsulescodes/package": "dev-main",
...
}
- 由于该包仍在开发中,因此使用的是
dev-main
版本。
通过执行php artisan tinker
进行测试
php artisan tinker
> CapsulesCodes\Package\Greeter::greet()
= "Hello world!"
您可以通过修改web.php
文件来测试Greeter
静态类。
package/routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use CapsulesCodes\Package\Greeter;
Route::get( '/', fn() => dd( Greeter::greet() ) );
"Hello world!" // routes/web.php:7`
工作环境已准备就绪。
这将是有趣的,可以添加额外的say()
方法以实时测试工具。
package/src/Greeter.php
<?php
namespace CapsulesCodes\Package;
class Greeter
{
public static function greet() : string
{
return "Hello world!";
}
public static function say( string $something ) : string
{
return $something;
}
}
使用php artisan tinker
进行测试。您可能需要重新加载它。
php artisan tinker
> CapsulesCodes\Package\Greeter::say( "That's a quick way to develop and test a package!" )
= "That's a quick way to develop and test a package!"
您可以通过修改web.php
文件来测试Greeter
静态类。
package/routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use CapsulesCodes\Package\Greeter;
Route::get( '/', fn() => dd( Greeter::say( "That's a quick way to develop and test a package!" ) ) );
"That's a quick way to develop and test a package!" // routes/web.php:7
在这个阶段,一切准备工作都做好了,现在可以开发一个与PHP Framework无关的包。创建Laravel包需要采取额外的步骤。对于本文,目标是实施一个php artisan greet
命令,这将调用Greeter
静态类。
建议在创建Laravel包时遵循Laravel的典型项目结构。这更容易让需要的人找到信息。
首先,必须通过扩展Laravel特定的Illuminate\Console\Command
命令来创建GreetCommand
。
package/src/Commands/GreetCommand.php
<?php
namespace CapsulesCodes\Package\Console\Commands;
use Illuminate\Console\Command;
use CapsulesCodes\Package\Greeter;
class GreetCommand extends Command
{
protected $signature = "greet";
protected $description = "Greet people with a 'Hello world!'";
public function handle()
{
dump( Greeter::greet() );
}
}
- 使用Laravel的
Illuminate\Console\Command
基类作为扩展。 - 之前创建的静态类
Greeter
用于handle()
方法。但是,为了测试包,可以将return Greeter::greet()
替换为return "Hello world!"
。
为了使模型项目识别此命令,有必要使用ServiceProvider
通知它。
package/src/Providers/PackageServiceProvider
<?php
namespace CapsulesCodes\Package\Providers;
use Illuminate\Support\ServiceProvider;
use CapsulesCodes\Package\Console\Commands\GreetCommand;
class PackageServiceProvider extends ServiceProvider
{
public function boot()
{
$this->commands( [ GreetCommand::class ] );
}
}
- 使用Laravel的
Illuminate\Support\ServiceProvider
基类作为扩展。 - 将新创建的
GreetCommand
命令添加到this->commands
方法请求的数组中,使template
项目能够访问该命令。
现在,该包必须通知模型项目一个新的 ServiceProvider
可用于发现。这避免了手动将其添加到模板 app.php
配置文件中 ServiceProviders
列表的需要。
package/composer.json
"extra" : { "laravel" : { "providers" : [ "CapsulesCodes\\Package\\Providers\\PackageServiceProvider" ] } },
测试 php artisan greet
命令。
php artisan greet
"Hello world!" // ../package/src/Console/Commands/GreetCommand.php:17
如果遇到任何问题,建议执行 composer update
命令来重新加载新包。
您可以通过修改 web.php
文件来使用 Artisan
测试 greet
命令。
package/routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Artisan;
Route::get( '/', fn() => Artisan::call( 'greet' ) );
"Hello world!" // ../package/src/Console/Commands/GreetCommand.php:17
如果您想仅在控制台模式下使您的 GreetCommand
可用,请将此条件添加到 PackageServiceProvider
中。
package/src/Providers/PackageServiceProvider.php
public function boot()
{
if( $this->app->runningInConsole() ) $this->commands( [ GreetCommand::class ] );
}
也可以实现 config
文件、migrations
、tests
、routes
或 views
。也许,这就是以后考虑的事情。
很高兴这有帮助。
driesvints, mho, antoniputra 赞同了这篇文章