瀏覽分類:

Laravel

Laravel 輔助函數 – Array篇

以下對每個方法做自我理解的解釋,皆會擷取官網範例,更佳釐清方法用法。

陣列

Arr::accessible 檢查參數是不是陣列或Collection

use Illuminate\Support\Arr;
use Illuminate\Support\Collection;

$isAccessible = Arr::accessible(['a' => 1, 'b' => 2]);

// true

$isAccessible = Arr::accessible(new Collection);

// true

$isAccessible = Arr::accessible('abc');

// false

$isAccessible = Arr::accessible(new stdClass);

// false

Arr::add([array],[key],[value]) 陣列中如果第二個傳入參數key值,如果「不存在」或 key 的值為 null 寫入陣列

use Illuminate\Support\Arr;
use Illuminate\Support\Collection;

$isAccessible = Arr::accessible(['a' => 1, 'b' => 2]);

// true

$isAccessible = Arr::accessible(new Collection);

// true

$isAccessible = Arr::accessible('abc');

// false

$isAccessible = Arr::accessible(new stdClass);

// false

Arr::collapse 將多個陣列合併成一個

use Illuminate\Support\Arr;

$array = Arr::collapse([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);

// [1, 2, 3, 4, 5, 6, 7, 8, 9]

Arr::crossJoin 這叫笛卡兒積,返回所有陣列

use Illuminate\Support\Arr;

$matrix = Arr::crossJoin([1, 2], ['a', 'b']);

/*
    [
        [1, 'a'],
        [1, 'b'],
        [2, 'a'],
        [2, 'b'],
    ]
*/

$matrix = Arr::crossJoin([1, 2], ['a', 'b'], ['I', 'II']);

/*
    [
        [1, 'a', 'I'],
        [1, 'a', 'II'],
        [1, 'b', 'I'],
        [1, 'b', 'II'],
        [2, 'a', 'I'],
        [2, 'a', 'II'],
        [2, 'b', 'I'],
        [2, 'b', 'II'],
    ]
*/

Arr::divide 陣列返回一個二維陣列,將key 以及 value 拆成兩個陣列,如下範例

use Illuminate\Support\Arr;

[$keys, $values] = Arr::divide(['name' => 'Desk']);

// $keys: ['name']

// $values: ['Desk']

Arr::dot 函數會把多為陣列中的key 平鋪成一為陣列,新的陣列將使用「.」符號來表示階層

use Illuminate\Support\Arr;

$array = ['products' => ['desk' => ['price' => 100]]];

$flattened = Arr::dot($array);

// ['products.desk.price' => 100]

Arr::except 移除某個鍵值元素,如下範例將price刪除

use Illuminate\Support\Arr;

$array = ['name' => 'Desk', 'price' => 100];

$filtered = Arr::except($array, ['price']);

// ['name' => 'Desk']

Arr::exists 如下所示,檢查陣列中是否有 name 或 salary 鍵值的存在

use Illuminate\Support\Arr;

$array = ['name' => 'John Doe', 'age' => 17];

$exists = Arr::exists($array, 'name');

// true

$exists = Arr::exists($array, 'salary');

// false

Arr::first 返回陣列第一個元素

use Illuminate\Support\Arr;

$array = ['name' => 'John Doe', 'age' => 17];

$exists = Arr::exists($array, 'name');

// true

$exists = Arr::exists($array, 'salary');

// false

Arr::flatten 將多為陣列的值全部取出,並且平鋪成一維陣列

use Illuminate\Support\Arr;

$array = ['name' => 'John Doe', 'age' => 17];

$exists = Arr::exists($array, 'name');

// true

$exists = Arr::exists($array, 'salary');

// false

Arr::forget 傳入一個陣列以及字串,字串使用「.」的方式表階層,將陣列中的對應階層移除。

use Illuminate\Support\Arr;

$array = ['products' => ['desk' => ['price' => 100]]];

Arr::forget($array, 'products.desk');

// ['products' => []]

Arr::get 傳入一個陣列以及字串,字串使用「.」的方式表示階層,用這樣的方式方面取出對應的值以可以指令預設值。

use Illuminate\Support\Arr;

$array = ['products' => ['desk' => ['price' => 100]]];

$price = Arr::get($array, 'products.desk.price');

// 100

$discount = Arr::get($array, 'products.desk.discount', 0);

// 0

Arr::has 函數使用「.」方式表示陣列階層,確認陣列中是否有存在該階層的值,可以一比對兩個,「皆存在」才會顯示 true。

use Illuminate\Support\Arr;

$array = ['product' => ['name' => 'Desk', 'price' => 100]];

$contains = Arr::has($array, 'product.name');

// true

$contains = Arr::has($array, ['product.price', 'product.discount']);

// false

Arr::hasAny 如上檢查陣列是否有對應的鍵值存在,「任一個」存在就回傳 true

use Illuminate\Support\Arr;

$array = ['product' => ['name' => 'Desk', 'price' => 100]];

$contains = Arr::hasAny($array, 'product.name');

// true

$contains = Arr::hasAny($array, ['product.name', 'product.discount']);

// true

$contains = Arr::hasAny($array, ['category', 'product.discount']);

// false

Arr::isAssoc 判斷陣列的key 有設定自訂鍵值,如果為預設的鍵值將回傳false

use Illuminate\Support\Arr;

$isAssoc = Arr::isAssoc(['product' => ['name' => 'Desk', 'price' => 100]]);

// true

$isAssoc = Arr::isAssoc([1, 2, 3]);

// false

$isAssoc = Arr::isAssoc(["0" => 'a', "1" => 'b', "2" => 'c'])); 

// false

$isAssoc = Arr::isAssoc(["1" => 'a', "0" => 'b', "2" => 'c'])); 

// true

$isAssoc = Arr::isAssoc(["a" => 'a', "b" => 'b', "c" => 'c'])); 

// true

Arr::last 回傳滿足指定條件的最後一個元素值,如下所示200與300接大於等於150回傳最後一個符合結果300,已可指定預設值,如果沒有找到回傳預設值。

use Illuminate\Support\Arr;

$array = [100, 200, 300, 110];

$last = Arr::last($array, function ($value, $key) {
    return $value >= 150;
});

// 300

$default = 0;

$last = Arr::last($array, function ($value, $key, $default) {
    return $value >= 301;
});

// 0

Arr::only 處理陣列是如果只要某幾個元素,可以一個陣列,並且帶入需要的key值即可得到只有這幾個結果的陣列

use Illuminate\Support\Arr;

$array = ['name' => 'Desk', 'price' => 100, 'orders' => 10];

$slice = Arr::only($array, ['name', 'price']);

// ['name' => 'Desk', 'price' => 100]

Arr::pluck 這個Victor我還蠻常使用的,可以在複雜的階層陣列中,找出某個位置的值,如下找出developer底下的name的key值,回傳全部的陣列。

use Illuminate\Support\Arr;

$array = [
    ['developer' => ['id' => 1, 'name' => 'Taylor']],
    ['developer' => ['id' => 2, 'name' => 'Abigail']],
];

$names = Arr::pluck($array, 'developer.name');

// ['Taylor', 'Abigail']

也可以如下範例所示將developer的id設定對應的key值。

$names = Arr::pluck($array, 'developer.name', 'developer.id');

// [1 => 'Taylor', 2 => 'Abigail']

Arr::prepend 元素存入陣列的第一個位置

use Illuminate\Support\Arr;

$array = ['one', 'two', 'three', 'four'];

$array = Arr::prepend($array, 'zero');

// ['zero', 'one', 'two', 'three', 'four']

亦可指定鍵值並插入陣列的第一個位置

use Illuminate\Support\Arr;

$array = ['price' => 100];

$array = Arr::prepend($array, 'Desk', 'name');

// ['name' => 'Desk', 'price' => 100]

Arr::pull 取得需要的元素,並刪除元陣列的該元素,如下所示,將key 等於name回傳,並將陣列內的name元素刪除。

use Illuminate\Support\Arr;

$array = ['name' => 'Desk', 'price' => 100];

$name = Arr::pull($array, 'name');

// $name: Desk

// $array: ['price' => 100]

$value = Arr::pull($array, $key, $default);  // 可以設定不存在時,返回預設值,原陣列不改變

Arr::query 將陣列的內容,轉為查詢的字串,就是網址後面常常看到的query。

use Illuminate\Support\Arr;

$array = ['name' => 'Taylor', 'order' => ['column' => 'created_at', 'direction' => 'desc']];

Arr::query($array);

// name=Taylor&order[column]=created_at&order[direction]=desc

Arr::random 隨意取出陣列中的一個值

use Illuminate\Support\Arr;

$array = [1, 2, 3, 4, 5];

$random = Arr::random($array);

// 4 - (retrieved randomly)

Arr::set 傳入三個參數,預計修改的陣列、字串、值,可以在陣列中,依照中間傳入的字串,格式使用「.」的方式再多維陣列中加入元素。

use Illuminate\Support\Arr;

$array = ['products' => ['desk' => ['price' => 100]]];

Arr::set($array, 'products.desk.price', 200);

// ['products' => ['desk' => ['price' => 200]]]

Arr::shuffle 隨機排序陣列內的元素

use Illuminate\Support\Arr;

$array = Arr::shuffle([1, 2, 3, 4, 5]);

// [3, 2, 5, 1, 4] - (generated randomly)

Arr::sort 陣列正序排序

use Illuminate\Support\Arr;

$array = ['Desk', 'Table', 'Chair'];

$sorted = Arr::sort($array);

// ['Chair', 'Desk', 'Table']

亦可以指定使用某個key做排序。

use Illuminate\Support\Arr;

$array = [
    ['name' => 'Desk'],
    ['name' => 'Table'],
    ['name' => 'Chair'],
];

$sorted = array_values(Arr::sort($array, function ($value) {
    return $value['name'];
}));

/*
    [
        ['name' => 'Chair'],
        ['name' => 'Desk'],
        ['name' => 'Table'],
    ]
*/

Arr::sortRecursive 有點不太知道用意,稍後再補~

use Illuminate\Support\Arr;

$array = [
    ['Roman', 'Taylor', 'Li'],
    ['PHP', 'Ruby', 'JavaScript'],
    ['one' => 1, 'two' => 2, 'three' => 3],
];

$sorted = Arr::sortRecursive($array);

/*
    [
        ['JavaScript', 'PHP', 'Ruby'],
        ['one' => 1, 'three' => 3, 'two' => 2],
        ['Li', 'Roman', 'Taylor'],
    ]
*/

Arr::where 過濾陣列,寫入特定過濾條件過濾

use Illuminate\Support\Arr;

$array = [100, '200', 300, '400', 500];

$filtered = Arr::where($array, function ($value, $key) {
    return is_string($value);
});

// [1 => '200', 3 => '400']

Arr::wrap 將值轉為陣列,如果原本已經是陣列將不會有任何變化。

use Illuminate\Support\Arr;

$string = 'Laravel';

$array = Arr::wrap($string);

// ['Laravel']

如果給定的值為 null

use Illuminate\Support\Arr;

$nothing = null;

$array = Arr::wrap($nothing);

// []

data_fill 如果有對應的key值,將元素加入

$data = ['products' => ['desk' => ['price' => 100]]];

data_fill($data, 'products.desk.price', 200);

// ['products' => ['desk' => ['price' => 100]]]

data_fill($data, 'products.desk.discount', 10);

// ['products' => ['desk' => ['price' => 100, 'discount' => 10]]]

亦可使用 「*」 如下所示,將子陣列缺少 products 下一層全部的子陣列,如果缺少price並設定值200,已有的陣列則不改變。

$data = [
    'products' => [
        ['name' => 'Desk 1', 'price' => 100],
        ['name' => 'Desk 2'],
    ],
];

data_fill($data, 'products.*.price', 200);

/*
    [
        'products' => [
            ['name' => 'Desk 1', 'price' => 100],
            ['name' => 'Desk 2', 'price' => 200],
        ],
    ]
*/

data_get


data_set 函數使用「.」符號從多維陣列或物件中根據指定鍵檢索回傳值,亦可以給予預設值,在未找到的情況下回傳預設值。

$data = ['products' => ['desk' => ['price' => 100]]];

$price = data_get($data, 'products.desk.price');

// 100

$discount = data_get($data, 'products.desk.discount', 0);

// 0

亦可以在還數中使用 「*」通配符找尋所有匹配的值

$data = [
    'product-one' => ['name' => 'Desk 1', 'price' => 100],
    'product-two' => ['name' => 'Desk 2', 'price' => 150],
];

data_get($data, '*.name');

// ['Desk 1', 'Desk 2'];

head 返回第一個值

$array = [100, 200, 300];

$first = head($array);

// 100

last 返回最後一個值

$array = [100, 200, 300];

$last = last($array);

// 300

以上就是Laravel操作陣列的函數,後面幾種函數有些與Arr類別相同,差別在於可以不用建立Arr類別的實體,以上提供給讀者參考,Victor使用自己的方式些一遍主要是增加我的印象,最完整的請參考Laravel 官方文件或框架原始碼 Arr類別。

Laravel Queue – 失敗任務處理

版本

Laravel 8


config/queue.php 陣列中 failed 區塊,可以設定失敗任務的連結設定。

'failed' => [
    'driver' => env('QUEUE_FAILED_DRIVER', 'database'),
    'database' => env('DB_CONNECTION', 'mysql'),
    'table' => 'failed_jobs',
],

監聽任務時如果沒有指定任務失敗的次數,任務將會一直嘗試例請在 JOB handle 函數中增加以下程式碼

public function handle()
{
    // 領取任務後的處理程式
}

當執行的時候,將會一直不斷的嘗試執行不會停止,如果指定 --tries 次數,任務會在執行指定的次數之後刪除任務並將任務放置到失敗的任務 failed_job 資料表中,等待確認問題點後,再讓 job 重新執行,確認沒問題後可以重新執行失敗 job 的指令如下,或者可以用 crontab 定時執行。

$ php artisan queue:retry all

這下好了,如果使用者收不到應該收到的信件或其他資訊怎麼辦,我們必續嘗試監聽失敗,在失敗時通知我們立即處理,有兩種方法。

閱讀更多

Laravel 正確的地方寫正確的程式

php artisan 指令有一大堆可以建立的東西,筆記一下並簡單跟大家分享,要寫什麼邏輯應該要寫在什麼地方,已下次我再釐清思緒隨筆寫下來的文字,Victor 日後再找時間值整理。

Model 資料表對應的相關設定

Controller 設定要送給哪一個方法執行

Mail 設定要送的電子郵件,標題、內文、指向哪個模板

Job 收到隊列排隊的項目,拿回來的資料要怎麼處理的邏輯

Service 商業邏輯,協助 Controller,Controller 呼叫這裡的法(須自行新建檔案)

Repository 協助Model,存一些SQL方法給Service 呼叫 (須自行新建檔案)

event 定義這個系統的事件,例如人生中「吃飯前」要洗手,吃飯前就是事件,當這件事情發生以後,可以外加上各種處理。

Notifications 可以設定,這個通知例如「洗手」需要提醒你,可以設定 傳送mail(可以呼叫定義好的Mail 這裡設定通知誰),或寫入資料庫、寄簡訊,各種管道,

migration 程式碼的方式產生資料庫的資料表

factory 撰寫產生資料庫測試的假資料

command 撰寫可以使用 php artisan 自訂的指令,例如需要固定時間執行的程式,就可以把它寫成指令,每天執行,或其他週期時觸發。

test 產生功能測試或單元測試的檔案,這些測試檔案都是用來撰寫測試程式是否正常運作的方法,常與產生假資料的factory 工廠一起使用。

observer 使用model 操作資料庫時,會有各種狀態正在新增、新增完成,每個階段都可以在這個檔案中加上額外的程式,例如觸發某個事件,修改資料表的某個欄位。

seeder 撰寫預設的資料庫資料,例如資料庫內某個資料表必定有台灣的所有縣市資料,可以產生一個對應的seeder寫在裡面,也可已在檔案中撰寫呼叫factory 的程式,填充很多測試的假資料進入。

request 請求時,例如送出一個表單,會有各種欄位,按下確定發送一個請求到伺服器,可以在這邊檢查請求是否符合規定,如果不符合回傳對應訊息,例如:新建動物的請求,可以建立一個StoreAnimalRequet。 更細的rule 在寫在另一篇

resource 請求就會有回應,這就是伺服器處理完的資料,處理完成時要送到客戶端(使用者)時,在做一些格式轉換的處理,並且可以統一輸出,例如動物的個資源,可以建立一個 AnimalResource 經過這個resource 轉換後,單一比動物的資料,可能包含(年齡、性別…)轉換成最後的要顯示的樣子。

Policy 轉門撰寫這個功能有沒有全線做,這裡指的是已具有權限的會員,例如Victor 我已經是某間公司的員工,我有識別證可以感應進入公司,但我有一些區域,不能進去,例如機房、廚房…或是我今天入住的飯店有分樓層管理,我住在6樓 我已經有今天入住的資格,但我的卡片也只能讓我坐電梯到六樓,這種設定就寫在這裡。

middleware 如果你有較大範圍的設定,可以當作過濾所有的請求,也可以撰寫成最後要回傳的訊息,大範圍的加上其他資訊,例如我想要在每一個回傳訊息,加上Victor 設計的API系統資訊。或是在一進入的請求過濾這個請求是不是會員,或是有沒有符合某些條件,例如:是否年買20歲…

listener 這個檔案可能會跟事件搞混、監聽事件因為常常連再一起說,拆開來事件,就像生活中發生的任何事,在中午12點時或鬧鐘響時,可以撰寫對應的動作,例如中午12點這件事件發生,要去吃午餐的程式…那監聽呢?就是剛剛說的不同的事件綁在一起,例如剛剛說12點到吃午餐,綁在一起,也可以在幫重送消息…

exception 可以自訂例外,Laravel 框架原始也有一些自訂的例外ModelNotFoundException 使用Model 的方式去找資料庫的資料,如果沒有找到,送出這個例外,寫程式的人可以對這個例外做攔截,並做相對應的處理,自訂例外可以在裡面撰寫一些log儲存起來,並撰寫要回傳什麼訊息。

component 跟前端View綁在一起,再另外說明

cast 基本上Model 輸出每個欄位都是文字的資料,可以在casts轉換資料的屬性比如說整數int… ,cast 可以自訂自己的轉換方式,並在Model 的cats 屬性設定個類別,因而產生的類別檔案。

以上這些也都只是定義產生出來的檔案都是Class 類別,如果沒有用Laravel 這樣的設計模式也可以參考,簡單把每個職責分得越清楚,維護起來越容易。

如果你是前端看了有一點點霧煞煞,簡單來說可以把它想像成

css 專門寫樣式

js 專門寫互動

但是這是不同程式語言,不過意思差不多或者可以把它想像成較進階的前端工程師會把css分別建立多個scss 專門寫按鈕、layout 、預設的參數… 最後再用工具打包成一個CSS 這樣的道理一樣,整個是伺服器,Laravel 定義了很多PHP 的class 讓你在對應的地方寫對應的程式。

laravel

還原Git Server clone 回來的Laravel專案

最近很夯的PHP框架 Laravel 除了自己建 Laravel 專案以外,有時候也會 clone 回來專案, 完成後會發現無法執行。

因為Laravel 初始化就有 .gitignore檔案,你可以在根目錄找找看。因為 .gitignore 設定的原因,並沒有所有檔案都加入版本控制,所以抓下來後必須要有重建,整個專案才會運行。

閱讀更多

Laravel CSRF 排除部分功能

app/Http/VerifyCsrfToken.php

/**
 * The URIs that should be excluded from CSRF verification.
 *
 * @var array
 */
 protected $except = [
     //這裡填入相對應的網址
     'test/*'
 ];

如上方程式碼顯示,排除test 開頭的所有網址

LARAVEL 權限設定筆記

新建一個原則policy

php artisan make:policy PostPolicy -m Post

註冊policy

AuthServiceProvider.php檔案中有一個policies 屬性,將每一個實體對應到新建的原則。指定 Post 模型的原則是 PostPilicy 類別:
app/Providers/AuthServiceProvider.php

   /**
     * 應用程式的原則對應。
     *
     * @var array
     */
    protected $policies = [
        Post::class => PostPolicy::class,
    ];
閱讀更多

Laravel 5.4 [ReflectionException] Class seed does not exist 錯誤 解決辦法

開發的過程中!,使用git同步或者是修改了Laravel seed 的檔名

使用 CMD 要下指令

php artisan db:seed 

會出現   Class [seed檔名] does not exist 的錯誤訊息。

解決辦法:

你需要先確任 顯示錯誤的 seed 檔 是否和DatabaseSeeder.php 放在同一個資料夾(5.4預設在\database\seeds 中)

CMD下指令

composer dump-autoload

產生新的映像檔(目前Victor知道的是這樣)

在執行一次

php artisan db:seed

Victor在5.4版本執行,可以成功執行。