支持Laravel.io的持续发展 →

在本地环境中创建Laravel包

16 Nov, 2023 7 min read

capsules-package-000.png

如何在本地开发环境中设置测试你的扩展包类或工具,以在本地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的父目录并创建一个作为测试的templateLaravel项目。

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:目录类型可以是composerpackagevcspathpath选项允许本地使用包,而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 文件、migrationstestsroutesviews。也许,这就是以后考虑的事情。

很高兴这有帮助。

CapsulesX 了解更多。

上次更新 8 个月前。

driesvints, mho, antoniputra 赞同了这篇文章

3
喜欢这篇文章吗?告诉作者并给他们一个掌声!
mho (MHO) 全职副业全栈网络开发者 | 设计师 Work @ http://capsules.codes

你可能还喜欢的其他文章

March 11th 2024

如何使用 Larastan 将您的 Laravel 应用程序从 0 到 9 进行优化

在 Laravel 应用程序执行前就发现 bugs 的可能性,这得益于 Larastan,它...

阅读文章
July 19th 2024

不使用 traits 标准化 API 响应

我注意到,大多数用于 API 响应的库都是通过 traits 实现的,并且...

阅读文章
2024年7月17日

在您的Laravel项目中通过Discord通知收集反馈

如何在Laravel项目中创建一个反馈模块,并在收到消息时收到Discord通知...

阅读文章

我们感谢以下 优秀的公司 对我们的支持

在这里放置您的标志?

Laravel.io

Laravel故障排除、知识共享和社区建设的门户网站。

© 2024 Laravel.io - 版权所有。