laravel基於remote model思想實現快速服務化(入門篇)

fengchezhi發表於2021-10-11

快速預覽

安裝laravel5.5 - laravel8之間的版本,然後安裝快速服務化的package

composer require windawake/laravelremodel dev-master

首先執行命令vendor:publish把./vendor/windawake/laravelremodel/examples/Models目錄下面的OrderDetailRemote.php、OrderRemote.php、 ProductRemote.php三個檔案複製到app資料夾下面。

php artisan vendor:publish --provider="Laravel\Remote2Model\RemoteModelServiceProvider"

laravel58
├── app
│ ├── Console
│ │ └── Kernel.php
│ ├── Exceptions
│ │ └── Handler.php
│ ├── Http
│ │ ├── Controllers
│ │ ├── Kernel.php
│ │ └── Middleware
│ ├── Models
│ │ ├── OrderDetailRemote.php
│ │ ├── OrderRemote.php
│ │ └── ProductRemote.php

然後執行 php ./vendor/windawake/laravelremodel/examples/sqlite/build.php 建立sqlite的資料庫檔案test.db

phpunit.xml增加sqlite的配置並且增加testsuite Remote

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>

        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>

        <testsuite name="Remote">
                <directory>./vendor/windawake/laravelremodel/tests</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <server name="APP_ENV" value="testing"/>
        <server name="BCRYPT_ROUNDS" value="4"/>
        <server name="CACHE_DRIVER" value="array"/>
        <server name="MAIL_DRIVER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
        <server name="DB_CONNECTION" value="sqlite"/>
        <server name="DB_DATABASE" value="./test.db"/>
    </php>
</phpunit>

    </php>
</phpunit>

最後執行測試命令 ./vendor/bin/phpunit --testsuit=Remote
執行結果如下所示,18個orm例子測試通過。

root@DESKTOP-VQOELJ5:/web/linux/php/laravel/laravel58# ./vendor/bin/phpunit --testsuit=Remote
PHPUnit 7.5.20 by Sebastian Bergmann and contributors.

..................                                                18 / 18 (100%)

Time: 208 ms, Memory: 20.00 MB

OK (18 tests, 21 assertions)

功能特性

  1. app後端的程式碼不需要重構,漸進式地跟業務基礎服務介面對接。
  2. 支援懶載入,避免了1+n查詢api。
  3. 支援連表,聯表,原生sql查詢,聚合查詢,子查詢等等,laravel orm特性幾乎可以使用。
  4. 使用了laravel服務容器寫法,所以query編譯器,分散式事務方法可以自定義。(分散式事務暫未實現)。

原理解析

remote model是遠端資料模型的意思。基礎服務的api介面被封裝成ORM。app後端的model只是虛擬的model,是業務基礎服務model的一個映象。

例如紫色的ProductModel是映象,但是OrderLogic使用它跟使用白色的ProductModel幾乎一樣。
這樣子做有什麼好處呢?可以複用laravel model的所有特性。因為現在很多package包針對model做了很多新功能,不用它們太可惜了。

如何使用

新建一個ProductRemote類繼承RemoteModel類。

<?php
namespace App\Models;

use Laravel\Remote2Model\RemoteModel;

class ProductRemote extends RemoteModel {
    const CREATED_AT = null;
    const UPDATED_AT = null;

    protected $primaryKey = 'pid';
    protected $table = 'product';
    public $timestamps = false;

    public function getHandle()
    {
        /**
         * @var RemoteTool
         */
        $remoteTool = app('remote.tool');
        $condition = $remoteTool->queryToCondition($this->queryBuilder);

        $client = new \GuzzleHttp\Client();
        $res = $client->request('GET', 'http://127.0.0.1:18001/api/product', [
            'query' => [
                'condition' => $condition
            ],
        ]);
        $json = $res->getBody()->getContents();

        $list = json_decode($json, true);
        return $list;
    }

}

這裡以查詢getHandle為例子。預設提供getHandle,updateHandle,insertGetIdHandle,deleteHandle和existsHandle 這5個方法。繼承RemoteModel類後,不定義getHandle等這些方法,它會預設走db驅動,跟普通的Model類一樣。

model方法 類似mysql語法 用途
getHandle select 查詢列表,查詢詳情,查詢聚合運算(count,max等)
updateHandle update 更新記錄
insertGetIdHandle insert 插入記錄
deleteHandle delete 刪除記錄
existsHandle select 判斷是否存在

個人總結

這一次是入門篇,下一次估計會出原始碼篇。寫了那麼多年的程式碼,老是會發現服務化介面,就是查詢一張表資料然後返回。搞得我經常懷疑人生。現在我堅定起來了,平時,我經常跟同事說laravel可以實現一秒服務化,他們都不相信。這次我可以證明給他們看。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章