使用Laravel开发自己的Package

Service Provider最主要的功能就是让我们写package,本文以一个简单的 Hello World 的功能,介绍一下package的开发流程。

包含routecontrollerview,然后会打包成package传到github与packagist,最后在其他的laravel项目中直接使用 composer require vendor/package 下载执行我们上传的package。

Version

  • Laravel 5.5
  • php 7.1.12

建立项目

composer create-project laravel/laravel MyPackage --prefer-dist

建立一个开发package的项目。

建立目录

在项目根目录下串建立packages目录,关于该package的源代码都会放在它里面。

packages目录下建立vendor/package/src子目录,本package会建立curder/helloworld/src

设定PSR-4命名空间

由于目前Laravel预设的root namespace是在app目录下,并且无法法得知我们新加的packages/curder/helloworld/src目录,必须在MyPackage项目的composer.json加入对应新的root namespace

{
    "name": "laravel/laravel",
    "description": "The Laravel Framework.",
    "keywords": ["framework", "laravel"],

    ...

   "autoload": {
        "classmap": [
            "database/seeds",
            "database/factories"
        ],
        "psr-4": {
            "App\\": "app/",
            "Curder\\HelloWord\\": "packages/curder/helloworld/src/"
        }
    },

    ...
}

注意我们添加的行:"Curder\\HelloWorld\\": "packages/curder/helloworld/src/"的命名空间和路径的映射关系。

修改完上面的设定后,需要执行下面的composer命令更新一下自动加载。

composer dump-autoload

建立Service Provider

使用下面的命令建立Service Provider

php artisan make:provider HelloWorldServiceProvider

产生HelloWorldServiceProvider.php默认在app/Providers目录下,因为我们是要写package,所以将此文件移到packages/curder/helloworld/src目录下。

因为文件的目录已经移动,需要重新修改一些它的namespace。

<?php

namespace Curder\HelloWorld;

use Illuminate\Support\ServiceProvider;

class HelloWorldServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

注意文件的命名空间是:Curder\HelloWorld,使用命令生成的Provider默认会建立boot()register()

注册ServiceProvider

config/app.php中註冊HelloWorldServiceProvider

return [
    ...

    'providers' => [

        ...

        /*
         * Package Service Providers...
         */

        Curder\HelloWord\HelloWorldServiceProvider::class,

        /*
         * Application Service Providers...
         */

        ...
    ],

    ...
];

注册刚刚建立的HelloWorldServiceProvider

建立Router

把路由文件放到src/routes/下,并命名为web.php,内容如下:

<?php

$namespace = 'Curder\HelloWorld\Http\Controllers';

Route::group([
    'namespace' => $namespace,
    'prefix' => 'helloworld',
], function () {
    Route::get('/', 'HelloWorldController@index');
});

建立View

把视图文件建立在src/resources/views下,将其命名为welcome.blade.php

<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Laravel</title>

    <!-- Fonts -->
    <link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">

    <!-- Styles -->
    <style>
        html, body {
            background-color: #fff;
            color: #636b6f;
            font-family: 'Raleway', sans-serif;
            font-weight: 100;
            height: 100vh;
            margin: 0;
        }

        .full-height {
            height: 100vh;
        }

        .flex-center {
            align-items: center;
            display: flex;
            justify-content: center;
        }

        .position-ref {
            position: relative;
        }

        .top-right {
            position: absolute;
            right: 10px;
            top: 18px;
        }

        .content {
            text-align: center;
        }

        .title {
            font-size: 84px;
        }

        .links > a {
            color: #636b6f;
            padding: 0 25px;
            font-size: 12px;
            font-weight: 600;
            letter-spacing: .1rem;
            text-decoration: none;
            text-transform: uppercase;
        }

        .m-b-md {
            margin-bottom: 30px;
        }
    </style>
</head>
<body>
<div class="flex-center position-ref full-height">
    @if (Route::has('login'))
        <div class="top-right links">
            @auth
                <a href="{{ url('/home') }}">Home</a>
            @else
                <a href="{{ route('login') }}">Login</a>
                <a href="{{ route('register') }}">Register</a>
            @endauth
        </div>
    @endif

    <div class="content">
        <div class="title m-b-md">
            {{ $message }}
        </div>

        <div class="links">
            <a href="https://laravel.com/docs">Documentation</a>
            <a href="https://laracasts.com">Laracasts</a>
            <a href="https://laravel-news.com">News</a>
            <a href="https://forge.laravel.com">Forge</a>
            <a href="https://github.com/laravel/laravel">GitHub</a>
        </div>
    </div>
</div>
</body>
</html>

创建Migration

将数据库迁移文件创建在src/publishable/databases/migrations/下,我们按照当前日期将其命名为:2017_12_17_000000_create_package_demo_table.php,内容如下:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePackageDemoTable extends Migration
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('package_demo', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->unsignedInteger('user_id');
            $table->unsignedInteger('checklist_id');
            $table->boolean('is_published');
            $table->boolean('is_archived');
            $table->timestamps();
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
    public function down()
    {
        Schema::dropIfExists('package_demo');
    }
}

创建配置文件

将配置文件创建在src/publishable/config/下,我们将其命名为helloworld.php,内容如下:

<?php

return [
    "message" => "Hello World",
];

配置文件的文件名不允许随意定义,不要与Laravel已有的配置文件文件名冲突,后期再项目的其他地方需要引用。

建立Controller

根据上面路由的定义,把控制器文件放到src/Http/Controllers下。

<?php

namespace Curder\HelloWorld\Http\Controllers;

use App\Http\Controllers\Controller;

class HelloWorldController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $message = config("helloworld.message");
        return view('HelloWorld::welcome', compact('message'));
    }
}

修改Service Provider

<?php

namespace Curder\HelloWorld;

use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;

class HelloWorldServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        Schema::defaultStringLength(191);

        $this->loadRoutesFrom(__DIR__ . '/routes/web.php' .
            '');
        $this->loadViewsFrom(__DIR__ . '/resources/views', 'HelloWorld');
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->registerPublishables();
    }

    private function registerPublishables()
    {
        $basePath = __DIR__;

        $arrPublishable = [
            'migrations' => [
                "$basePath/publishable/databases/migrations" => database_path('migrations'),
            ],
            'config' => [
                "$basePath/publishable/config/helloworld.php" => config_path('helloworld.php'),
            ],
        ];

        foreach ($arrPublishable as $group => $paths) {
            $this->publishes($paths, $group);
        }
    }
}

执行发布命令

php artisan vendor:publish

执行完上面的命令后,就能看到如下的界面

输入Curder\HelloWorld\HelloWorldServiceProvider的内容进行发布。

另外对于已经发布的内容如果需要覆盖,在上面的发布命令中加入 --force 参数。但是在执行这个命令之前请确保对修改过的数据已有备份。

访问效果

上传到GitHub

设定package的命名空间

目前在本地开发的这个package由于是搭配MyPackage项目测试,所以将PSR-4root namespace设定在MyPackage项目的composer.json

但发布package之后,不可能要使用者也手动在自己项目的composer.json加上命名空间,所以我们要将命名空间设定在package自己的composer.json

我们来到项目的目录下packages/curder/helloworld下执行如下命令,生成composer.json文件:

composer init

下面是我们从上面的命令中生成的composer.json,添加上PSR-4的自动加载。

{
    "name": "curder/helloworld",
    "description": "A Laravel Package For Demo.",
    "license": "MIT",
    "authors": [
        {
            "name": "curder",
            "email": "[email protected]"
        }
    ],
    "minimum-stability": "dev",
    "require": {},
    "autoload": {
        "psr-4": {
            "Curder\\HelloWorld\\": "src/"
        }
    },
     "extra": {
        "laravel": {
            "providers": [
                "Curder\\HelloWorld\\HelloWorldServiceProvider"
            ]
        }
    }
}

建立本地Git仓库

cd packages/curder/helloworld
git init
git add .
git commit -m "Initial commit."

建立远程git仓库

推送到远程仓库

git remote add origin [email protected]:curder/helloworld.git
git push -u origin master
git tag -a 1.0.0 -m "First version"
git push --tags

上传Packagist

登入Packagist

登录至Packagist,按右上角Submit上传package。

提交Github网址

贴上package在Github Repository的网址。

确认提交

因为Packagist已经有很多package名字叫做helloworld,Packagist让你确认是否要上传。

上传成功

测试Package

建立测试项目

composer create-project laravel/laravel MyTestPackage --prefer-dist

安裝Package

cd MyTestPackage
composer require oomusou/helloworld

由于Laravel5.5之后新增了包的自动发现功能,所以我们并不需要在config/app.config中手动引入ServiceProvider

发布配置和迁移文件

php artisan vendor:publish

浏览器测试

Copyright © http://blog.webfsd.com 2018 all right reserved,powered by Gitbook该文件修订时间: 2019-05-21 04:55:26

results matching ""

    No results matching ""