「12步」製作 Laravel 外掛 (一)

coding01發表於2018-01-20

在Laravel 開發過程中,用了很多諸如:laravel-admin,Guzzle,Intervention Image 等優秀的外掛,看他們的 star 很多,得到很多人的關注,就想著自己能不能寫個有價值的外掛,共享給大家使用。

今天就讓我們來說說如何建立一個簡單的外掛:「數字轉中文大寫金額」

具體只需要以下「12」個步驟:

1. 建立 Laravel 5.5 專案

// 下載最新 Laravel

composer global require "laravel/installer"

// 建立專案
Laravel new packagelearning
複製程式碼

2. 建立外掛資料夾

在 Laravel 專案 vendor 資料夾放的是各種第三方外掛,我們隨便看看,可以發現這些外掛基本遵循下面的檔案目錄格式:

「12步」製作 Laravel 外掛 (一)

如,monolog 外掛,目錄結構為 [VENDOR or CREATOR] / [PACKAGE NAME],而且 src 資料夾基本用於儲存外掛原始碼,還有一個 composer.json 用於配置外掛基本資訊和引入其它第三方外掛等資訊。

我們在 packagelearning 專案建立 packages 資料夾:

「12步」製作 Laravel 外掛 (一)

3. 建立 composer.json

我們可以利用「composer」命令來初始化 composer.json 檔案:

「12步」製作 Laravel 外掛 (一)

輸入外掛的基本資訊後:

「12步」製作 Laravel 外掛 (一)

4. PSR-4 autoload namespace mapping

在 composer.json 加入 autoload 配置:

「12步」製作 Laravel 外掛 (一)

5. 建立 Service Providers

正如 Laravel 官網所說:

Service providers are the connection points between your package and Laravel. A service provider is responsible for binding things into Laravel's service container and informing Laravel where to load package resources such as views, configuration, and localization files.

所以我們需要建立一個 Service Provider 來告訴 Laravel 使用該外掛是,什麼 Controller 被執行了,Routes 和 Views 在哪載入等等。

// 在 Laravel專案根目錄執行命令

php artisan make:provider Num2nmbServiceProvider
複製程式碼

再將 Num2nmbServiceProvider.php 檔案移動到外掛 src 資料夾下,並修改namespace 名為:Fanly\Num2nmb

「12步」製作 Laravel 外掛 (一)

這也正如官網的說明一樣,service provider 主要包括兩個方法:register 和 boot方法。

A service provider extends the Illuminate\Support\ServiceProvider class and contains two methods: register and boot. The base ServiceProvider class is located in the illuminate/support Composer package, which you should add to your own package's dependencies. To learn more about the structure and purpose of service providers, check out their documentation.

有了 Service Provider,我們可以先加入到 config/app.php 中。

「12步」製作 Laravel 外掛 (一)

接下來讓我們跟常規開發一樣,建立功能的 Controller,Route 和 View。

6. 建立 Controller

從網上 copy 了一段「數字金額轉中文大寫金額」功能,直接上程式碼:

<?php
/**
 * Created by PhpStorm.
 * User: ye
 * Date: 2018/1/10
 * Time: 下午9:49
 */

namespace Fanly\Num2nmb;


use App\Http\Controllers\Controller;

class Num2nmbController extends Controller {

    public function index($num) {
        $nmb = $this->num2nmb($num);
        return view('num2nmb::nmb', compact('nmb'));
    }

    private function num2nmb($num) {
        $c1 = "零壹貳叄肆伍陸柒捌玖";
        $c2 = "分角元拾佰仟萬拾佰仟億";

        //精確到分後面就不要了,所以只留兩個小數位
        $num = round($num, 2);
        //將數字轉化為整數
        $num = $num * 100;

        if (strlen($num) > 10) {
            return "金額太大,請檢查";
        }
        $i = 0;
        $c = "";
        while(1) {
            if ($i == 0) {
                //獲取最後一位數字
                $n = substr($num, strlen($num) - 1, 1);
            } else {
                $n = $num % 10;
            }    //每次將最後一位數字轉化為中文
            $p1 = substr($c1, 3 * $n, 3);
            $p2 = substr($c2, 3 * $i, 3);
            if ($n != '0' || ($n == '0' && ($p2 == '億' || $p2 == '萬' || $p2 == '元'))) {
                $c = $p1 . $p2 . $c;
            } else {
                $c = $p1 . $c;
            }
            $i = $i + 1;
            //去掉數字最後一位了
            $num = $num / 10;
            $num = (int) $num;
            //結束迴圈
            if ($num == 0) {
                break;
            }
        }
        $j = 0;
        $slen = strlen($c);
        while ($j < $slen) {
            //utf8一個漢字相當3個字元
            $m = substr($c, $j, 6);
            //處理數字中很多0的情況,每次迴圈去掉一個漢字“零”
            if ($m == '零元' || $m == '零萬' || $m == '零億' || $m == '零零') {
                $left = substr($c, 0, $j);
                $right = substr($c, $j + 3);
                $c = $left . $right;
                $j = $j - 3;
                $slen = $slen - 3;
            }
            $j = $j + 3;
        }

        //這個是為了去掉類似23.0中最後一個“零”字
        if (substr($c, strlen($c) - 3, 3) == '零') {
            $c = substr($c, 0, strlen($c) - 3);
        }

        //將處理的漢字加上“整”
        if (empty($c)) {
            return "零元整";
        } else {
            return $c . "整";
        }
    }
}
複製程式碼

7. 建立 View

這個很簡單了,從 welcome.blade.php 直接 copy 過來,放在 src/views/nmb.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">
    <div class="content">
        <div class="title m-b-md">
            {{ $nmb }}
        </div>
        <div class="links">
            <a href="https://laravel.com/docs">fanly</a>
        </div>
    </div>
</div>
</body>
</html>
複製程式碼

8. 新增 Route

在 src目錄下,建立 routes.php 檔案

Route::get('num2nmb/{num}', 'Fanly\Num2nmb\Num2nmbController@index');
複製程式碼

9. 配置 Service Provider

有了 controller、view 和路由,直接在 Num2nmbServiceProvider 配置相關資訊即可:

在 boot 函式中,加入程式碼:

$this->loadViewsFrom(__DIR__.'/views', 'num2nmb');
複製程式碼

在 register 函式加入程式碼:

「12步」製作 Laravel 外掛 (一)

10. 測試

如圖:

「12步」製作 Laravel 外掛 (一)

11. Publishing the Views

最後,view 層是高度自定義層,所以有必要將 views 試圖 publish 到專案中,我們就可以改動顯示效果,而不至於去變化外掛中 views 的程式碼了,而且這本身也是不允許的。

可以在 boot 函式中加入程式碼:

$this->publishes([
            __DIR__.'/views' => base_path('resources/views/num2nmb'),
        ]);
複製程式碼

最後,執行命令:

「12步」製作 Laravel 外掛 (一)

「12步」製作 Laravel 外掛 (一)

12. 使用「包自動發現」

Laravel 5.5 增加了一個新的功能 「Package Auto Discovery」。這個功能使得 Laravel 能更容易地對包進行安裝和啟用的管理。

包的開發者可以在 composer.json 檔案中新增一個新的部分,用來告訴框架應該註冊哪些服務提供器或者它們的外觀。

我們可以試試這個功能,在外掛的 composer.json 中加入如下程式碼:

"extra": {
        "laravel": {
            "providers": [
                "Barryvdh\\Debugbar\\ServiceProvider"
            ]
        }
    }
複製程式碼

注: 有關「Package Auto Discovery」功能的說明和使用,可以參考:

1. 深入瞭解 Laravel 5.5 Package Auto Discovery zhuanlan.zhihu.com/p/27518011

2. Laravel 5.5 支援包自動發現(新功能早知道)laravel-china.org/articles/49…

3. Laravel Package Auto-Discovery laravel-news.com/package-aut…

4. Package Auto-Discovery In Laravel 5.5 medium.com/@taylorotwe…

總結

下一步,我們需要將做好的外掛包提交伺服器,供其他人使用。

「未完待續」


coding01 期待您繼續關注

qrcode

相關文章