Help us understand the problem. What is going on with this article?

Laravelパッケージ開発ハンズオン〜環境編〜

Laravelのパッケージ開発を行う流れやディレクトリ構成について考えました。

流れ

  • 作業ディレクトリを作成
  • 開発パッケージを作成
    • 例として artisan に hello:world コマンドを追加する
  • Docker環境の構築
  • 開発パッケージのインストール
  • 動作確認

最終的なディレクトリ構成

.
└── work # 作業ディレクトリ
    ├── core # Laravelインストール場所
    ├── docker # docker環境
    └── packages # パッケージのディレクトリ
        └── laravel-hello-world # myパッケージ
  • 複数のパッケージを開発する場合を考慮して packages と一つディレクトリを挟む
  • coreにLaravelをインストールする。
  • Laravelのバージョン切り替えは考慮してない。
    • もし切り替えたい場合は core の中に 各バージョンのディレクトリを切るか🤔

作業ディレクトリを作成

$ mkdir -p work/packages/laravel-hello-world

Docker環境の構築

以前の記事で紹介した構成をカスタマイズして使います。

$ cd work
$ git clone git@github.com:ucan-lab/docker-laravel5.git docker
$ cd docker

work ディレクトリでgit cloneを実行します。

work/docker/.env 修正(変更箇所のみ)

COMPOSE_PROJECT_NAME=laravel-hello-world
PROJECT_PATH=../core
PACKAGES_PATH=../packages

work/docker/docker-compose.yml 修正(変更箇所のみ)

services:
  app:
    volumes:
      - ${PACKAGES_PATH}:/packages

- ${PACKAGES_PATH}:/packages の行を追記します。

Dockerビルド&Laravelインストール

$ docker-compose up -d --build
$ docker-compose exec app composer create-project --prefer-dist "laravel/laravel=5.8.*" .

core ディレクトリ内にLaravelがインストールされます。

開発パッケージを作成

今回は例として laravel-hello-world パッケージという artisan コマンドに hello:world を追加するだけのサンプルパッケージを作ることにします。

作業ディレクトリへ移動

$ docker-compose exec app ash
$ cd /packages/laravel-hello-world

composer init

composer init コマンドを実行して、 composer.json ファイルを作成します。

$ composer init

  Welcome to the Composer config generator  

This command will guide you through creating your composer.json config.

Package name (<vendor>/<name>) [root/laravel-hello-world]: ucan-lab/laravel-hello-world
Description []: laravel-hello-world
Author [, n to skip]: n
Minimum Stability []: 空Enter
Package Type (e.g. library, project, metapackage, composer-plugin) []: library
License []: MIT

Define your dependencies.

Would you like to define your dependencies (require) interactively [yes]? n
Would you like to define your dev dependencies (require-dev) interactively [yes]? n

{
    "name": "ucan-lab/laravel-hello-world",
    "description": "laravel-hello-world",
    "type": "library",
    "license": "MIT",
    "require": {}
}

Do you confirm generation [yes]? 空Enter

"require": {} から以下の設定を追記します。

    "require": {
        "php": "^7.1",
        "laravel/framework": "^5.5.0"
    },
    "autoload": {
        "psr-4": {
            "UcanLab\\LaravelHelloWorld\\": "src/"
        }
    },
    "extra": {
        "laravel": {
            "providers": [
                "UcanLab\\LaravelHelloWorld\\Providers\\ConsoleServiceProvider"
            ]
        }
    }
  • 依存ライブラリ
  • 名前空間とオートロード
  • Laravel用のサービスプロバイダ

composer バリデーション

バリデーションコマンドを実行して composer.json の記述に誤りがなければokです。

$ composer validate
./composer.json is valid

空のディレクトリと空のファイルを作成

$ mkdir -p src/{Console,Providers}
$ touch src/Console/HelloWorldCommand.php
$ touch src/Providers/ConsoleServiceProvider.php

src/Console/HelloWorldCommand.php 作成

<?php

namespace UcanLab\LaravelHelloWorld\Console;

use Illuminate\Console\Command;

class HelloWorldCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'hello:world';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Hello World.';

    /**
     * @return void
     */
    public function handle(): void
    {
        $this->info('Hello World.');
    }
}

src/Providers/ConsoleServiceProvider.php

<?php

namespace UcanLab\LaravelHelloWorld\Providers;

use Illuminate\Support\ServiceProvider;
use UcanLab\LaravelHelloWorld\Console\HelloWorldCommand;

class ConsoleServiceProvider extends ServiceProvider
{
    protected $defer = true;

    public function boot()
    {
        $this->registerCommands();
    }

    public function register()
    {
        // register bindings
    }

    protected function registerCommands()
    {
        $this->app->singleton('command.ucan-lab.hello.world', function () {
            return new HelloWorldCommand();
        });

        $this->commands([
            'command.ucan-lab.hello.world',
        ]);
    }

    public function provides()
    {
        return [
            'command.ucan-lab.hello.world',
        ];
    }
}

開発パッケージのインストール

work/core/composer.json

下記のリポジトリ設定を追記します。 どこでもいいんですけど、 require の手前あたりが綺麗な気がします。

    "repositories": [
        {
            "type": "path",
            "url": "/packages/laravel-hello-world",
            "symlink": true
        }
    ],

"symlink": true をしておくと core/vender/laravel-hello-world シンボリックリンクを貼ってくれるので、パッケージのソースコードを変更しても composer update 不要でリアルタイムで反映されます。
url は dockerから見たファイルパスを設定します。

$ docker-compose exec app composer require ucan-lab/laravel-hello-world:dev-master

動作確認

$ docker-compose exec app php artisan hello:world
Hello World.

Hello World. と表示される。

スクリーンショット 2019-08-28 20.30.25.png

さいごに

テストコードやpackagist登録は別記事にしようかなと思います。

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした