laravel框架應用和composer擴充套件包開發

Sunday發表於2018-07-18

laravel5.5+


laravel官方地址

laravel是目前最流行的php框架,發展勢頭迅猛,應用非常廣泛,有豐富的擴充套件包可以應付你能想到的各種應用場景,laravel框架思想前衛,跟隨時代潮流,提倡優雅程式碼,自稱為“web工匠”,其中的routeblade模板引擎、console、容器以及composer擴充套件包為業務的開發提供了極大的便利。

國內目前已經有眾多的laravel社群,比如

當然還有更多可供開發者學習和交流的網站,可以自行google或者百度。

不過如果看文件的話,建議檢視英文網站官網(如果英語允許的話),官網也有一個對應的社群,供開發者問答,不過貌似沒有那麼活躍,提問題的話也需要有一定的英文基礎,至少可以看懂stackoverflow上的問答。

言歸正傳,這裡會介紹一下laravel5.5的簡易上手教程,如果你需要理解laravel框架整體的設計和實現原理的話,MVC、設計模式(尤其是工廠模式)、路由、管道、容器、控制反轉、依賴注入等都是必須要理解的,這裡並不深入探討,否則本作者寶寶就要吐血寫個系列了,想想都覺著累(經常加班啊沒時間啦!)。

本教程可以讓你在短時間內按照123步驟完成一個網站的應用,貫穿laravel各個層級,對於一個剛接觸該框架的開發者來說,先應用,後深入,這也是登堂入室的學習方式,何樂而不為呢?

Ok, Here we go!!!

前期準備

  1. 安裝php7(最好加入環境變數)。可以上官網或者軟體包管理工具安裝,例如: brew install php7
  2. 安裝composer
  3. 安裝mysql

建立laravel專案

1. 終端執行命令
composer create-project laravel/laravel blog
2. 進入blog資料夾,執行
php -S localhost:80 -t public
3. 瀏覽器訪問 http://localhost
4. 執行命令 php artisan

如果3、4步驟執行成功,則一切無礙,可以進行下一步。

5. 利用你的編輯工具,以sublime為例,開啟blog專案,Ctrl+P 找到web.php,寫入如下程式碼,進行路由註冊:
Route::get(`/test`, function () {
    return "<h1>Hi Sunday.</h1>";
});

這裡簡單解釋一下,路由在routes目錄之下,有三個檔案:web.phpconsole.phpchannel.php
其中,web.php是負責網站路由,也就是當php是以http請求的方式執行時才會用到,
console.php是在命令列執行模式下執行artisan命令的,這個後續會講到,
channel.php是廣播訊息時會用到,這個本篇略過,需要看的可以檢視文件
gethttp請求方式,路由註冊時也可以用post/put/delete/patch等,laravel-router還提供了便利的restful風格的路由註冊resource方法,可以對後續業務處理增刪改查等。
上述例子為一個匿名函式,其實一般情況下會有路由分組,字首,中介軟體(後面會講到),別名,匹配等的鏈式呼叫:Route::prefix(`prefix_example`)->middleware([`m_exaple_1`,`m_example_2`])->group(Route_Closure);
下面給一個完整的示例:

Route::prefix(`hi`)->middleware([`hi_m`])->namespace(`sd`)->group(function () {
    Route::post(`sunday`, `SundayController@sunday`)->name(`hi.sunday.post`);
    Route::put(`sunday`, `SundayController@sunday`)->name(`hi.sunday.put`);
})

怎麼樣?laravel路由的註冊風格是不是非常友好,非常靈活多變?其中Route也可以使用app(`router`)訪問,app()是一個輔助方法,這個輔助方法在vendorlaravelframeworksrcIlluminateFoundationhelpers.php中,其中也有很多其他好用的輔助方法。app()涉及到容器的思想和facade門面註冊,這裡不詳述。

6. 訪問以下剛剛註冊的路由,http://localhost/test
7. 手動在app/Http/Controllers下新建或命令列生成一個控制器:php artisan make:controller sd/SundayController,這時你會看到app/Http/sd下面有一個SundayController.php,將下面的程式碼寫入:
    public function sunday()
    {
        return "Hi sunday";
    }
8. web.php註冊路由,併成功訪問:
Route::prefix(`hi`)->namespace(`sd`)->group(function () {
    Route::get(`sunday`, `SundayController@sunday`)->name(`hi.sunday.get`);
})
9. 中介軟體,執行命令php artisan make:middleware MyMiddleware,會生成一個標準中介軟體,開啟MyMiddleware.php可以看到裡面有兩個方法handleterminate
public function handle($request, $next)
{
    // 上面兩個入參,你不用管,這個是laravel路由分發時自動注入的引數,$request是laravel封裝的請求物件,IlluminateHttpRequest,你可以獲取到所有超級變數的資料,也可以獲得對應的一些請求處理方法如session(),getClientIp().
    // 這個方法是在進入Controller之前執行的,目的是對本次請求進行預處理或者校驗等。
    app(`log`)->info(`記錄一個日誌`);
}

public function terminate($request, $response)
{
    // 這個方法是在請求即將關閉時執行的,可以處理一些響應相關的邏輯。
    app(`log`)->info(`再記錄一下日誌`);
}
10. 中介軟體註冊,開啟app/Http/Kernel.php ,在$middleware中加入
appHttpMiddlewareMyMiddleware::class
11. 檢視 storage/logs/laravel.log(如果你config/app.php配置了日誌channeldaily,那麼應該看到的是日期格式的檔案),裡面應該有上一步中記錄的日誌資訊,以及對應的日誌級別,laravel的日誌使用monolog,可以使用多種驅動去記錄日誌,也可以配置上報策略,實現了loggerinterface介面,符合psr3的規範。
12. 檢視層,在剛剛的方法 SundayController@sunday 中,將返回值改為:
    return view(`test.test`, [`name` => `sunday`, `testArray` => [1,2,3]]);

在前端模板所在目錄 resources/views下建一個目錄test,建一個blade模板test.blade.php,程式碼如:


@if ($name )
<h1>{{$name}},你好</h1>
@else
<h1>無名氏,你好</h1>
@endif

@foreach ($testArray as $testNumber)
    <li>{{$testNumber}}</li>
@endforeach

在控制器返回檢視時,第一個引數是以.號表示resources/views下的目錄層級的,上面的test.test則表示檢視檔案是在test/test.blade.php,第二個引數是一個傳遞給檢視層的陣列,裡面應當是key => value關聯陣列,因為在blade模板引擎中,會直接將對應的key轉化成一個可使用的變數,在返回給檢視之前,如果你定義了檢視繫結,如在ComposerServiceProvider中的boot方法中註冊了對應的檢視繫結的話,那麼會先處理這一步,然後再將資料傳給目的檔案。
在這個例子中,test.blade.php得到了引數之後,會通過blade引擎分析模板檔案,解析語法,轉化成正常的html文字。
{{$name}}{!!$name!!}語法相當於<?=$name>,前者為防止xss會過濾掉一些specialchar,後者則會直接輸出文字,不安全。
@if ... @endif則是條件判斷語句,行後面可以跟一個簡短的php邏輯判斷
@foreach ... @endforeach 輪詢陣列
其他語法請參考 官方文件

以上的步驟,僅僅是完成了從路由到檢視的簡單處理,下面看一下資料模型,Model

13. 配置資料庫

database.php

// config/database.php
    `mysql` => [
        `driver` => `mysql`,
        `host` => env(`DB_HOST`, `127.0.0.1`), // 主機
        `port` => env(`DB_PORT`, `3306`), // 埠
        `database` => env(`DB_DATABASE`, `forge`), // 這裡需要配置你的資料庫
        `username` => env(`DB_USERNAME`, `forge`), // 配置你的使用者名稱
        `password` => env(`DB_PASSWORD`, ``), // 密碼
        `unix_socket` => env(`DB_SOCKET`, ``),
        `charset` => `utf8mb4`,
        `collation` => `utf8mb4_unicode_ci`,
        `prefix` => ``,
        `strict` => true,
        `engine` => null,
    ],

.env

// .env檔案
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=test #這裡需要你手動在資料庫建立一下資料庫
DB_USERNAME=root #你自己的使用者名稱
DB_PASSWORD=pwd #你自己的密碼
14. 執行artisan命令 php artisan make:auth
15. 執行artisan命令 php artisan make:migration 建立user表和密碼錶,進入你的資料庫中檢視是否建立成功
16. 這時,開啟網站首頁,你會看到有一個登入標誌,當你註冊成功之後,你會看到user表中多了一條資料,表示資料庫連線是成功的。

model可以通過php artisan make:model TestModel來建立,如果你沒有特殊要求的話,它會出現在app目錄下。
進入該Model你會看到它繼承了一個EloquentModel,這個ORM model可以為你提供多種多樣的CURD方法,具體可見文件,在Model裡面需要自定義一些屬性,例如table、fillable、guards等,支援軟刪除use SoftDeletes,但對應表中必須要有deleted_at欄位。
你也可以用DB匿名類或者app(`db`)來得到一個比EloquentModel更加原始的模型物件,這會讓你對資料庫的操作更加原生,詳見 文件

以上就是對應的MVC使用的簡單介紹

下面,讓我們看看console的使用
  1. 終端進入專案目錄,執行php artisan可以檢視所有可執行命令
  2. 執行 php artisan route:list可以檢視已成功註冊的路由列表
  3. php artisan make:command NewCommand建立一個新的命令
  4. 開啟app/Console/Commands/NewCommand.php,在$signature後定義一個命令的名稱如:test:test {--O|op= : 這是我的測試引數},在handle()方法中寫入你的邏輯。如:
$this->info(`我第一個命令`); // 會在終端上輸出該文字
$this->error(`我的命令錯了`); // 會在終端上輸出該文字
$this->confirm(`確認我的命令?`); // 選擇yes/no
$this->choice(`我還有其他選擇:`, ["A", "B"]); // 選擇一個
$this->output->progress(); //進度條
echo $this->option(`op`); // 獲取所定義引數值

之後,在app/Console/Kernel.php $commands註冊命令AppConsoleCommandsTestCommand::class,執行php artisan test:test --op=1,成功輸出1,這條命令算是完工了。

如果你想要加入定時任務,可以將命令加在schedule()中, $schedule->cron("0 0 0 0 0")這裡填寫crontab的格式。
你可以執行php artisan schedule:run來執行定時任務
laravel會在你專案維護或迭代時自動完成定時任務的重啟

composer擴充套件包

如果你有心,當你建立一個laravel專案的時候,就會注意到,composer會在專案中建立一個vendor目錄,這個目錄下儲存著各式各樣的擴充套件包,如:laravel/framework、symphony/console、monolog/monolog等,這些擴充套件包是laravel的寶庫,為你的開發提供了極大便利。

所有的擴充套件包都需要符合psr4載入規範,通過spl_autoload_register()方法自動加在,composer會生成一個autoload_classmap.php你可以找到所有載入到的類和檔案。

如何開發一個composer擴充套件包呢?

1.新建目錄test,進入執行 composer init

這裡type一般選擇project/librarylicense一般選擇MIT協議(一種開源授權協議)

2.開啟composer.json,加入psr4規則:

 "autoload": {
    "psr-4": {
        "Name1\Name2\": "name/src/Name" // 這裡表示按照psr4規範,對於name/src/Name目錄下的所有檔案,載入名稱空間以Name1\Name2\為字首的類。
    }
}

3.建立name/src/Name目錄,在Name目錄下建立檔案NameServiceProvider.php,程式碼如下:

<?php
namespace Name1Name2;

use IlluminateSupportServiceProvider;

class NameServiceProvider extends ServiceProvider
{
    public function boot()
    {
        require __DIR__ . `/helpers.php`;
        log_info(`我進來了`);
    }
}

由於log_info()這個方法我們沒有定義過,所以可以在helpers.php中進行定義:

<?php

if (!function_exist(`log_info`)) {
    function log_info($message) {
        echo $message . PHP_EOL;
    }
}

我們也可以建立一個更深層次的目錄,如Handlers,在其下建立一個TestYou.php:

namespace Name1Name2Handlers;

class TestYou
{
    public function test()
    {
        log_info("test");
    }
}

建立一個匿名類Facades/Test.php:

namespace Name1Name2Facades;

use IlluminateSupportFacadesFacade;

class Test extends Facade 
{
    protected static function getFacadeAccessor()
    {
        return "test";
    }
}

材料已準備完畢,下面開始切菜:

// NameServiceProvider

public function register () 
{
    $this->app->bind(`test`, Name1Name2HandlersTestYou::class);
}

為什麼一定要定義匿名類呢?因為laravel框架本身要求就是少去關注工具類的實現,多關注業務本身,所以所有的sdk或者擴充套件包都在接入時儘量提供便利,其中$this->app->bind()也體現了一個依賴注入控制反轉的思想,使得定義了匿名類的,可以在config/app.php中註冊相應匿名類TestNameServiceProvider之後可以以極為便利的方式使用,如:Test::test(),或者app(`test`)->test(),不需要管他們的名稱空間。

上述的擴充套件包功能已經基本成形,你需要將它放到相應的程式碼託管倉庫中,如githubhttps://packagist.org(推薦),你可以嘗試在laravel中使用命令composer require {你的package名字}進行安裝。

後語

本文由於初次編寫,必然有諸多不合理之處,希望讀者們多多給出優化意見,以後在文章中會考慮到,大家共同成長,一起發財。

stay hungry, stay foolish.

相關文章