Laravel – MySQL – 繞過資料庫外鍵的條件約束,強制刪除
MySQL 下指令 SET FOREIGN_KEY_CHECKS=0,可以將被關聯的來源強制刪除,有時候我們僅是要做測試的時候,會非常好用,不會被卡死。
在 Laravel 可以透過這樣的方式,來刪除紀錄或清空資料表
1 2 3 4 |
DB::statement('SET FOREIGN_KEY_CHECKS=0'); WalletDetail::truncate(); |
偷懶是程設師的美德
MySQL 下指令 SET FOREIGN_KEY_CHECKS=0,可以將被關聯的來源強制刪除,有時候我們僅是要做測試的時候,會非常好用,不會被卡死。
在 Laravel 可以透過這樣的方式,來刪除紀錄或清空資料表
1 2 3 4 |
DB::statement('SET FOREIGN_KEY_CHECKS=0'); WalletDetail::truncate(); |
通常我們在 php 檔案最前方加入
1 2 3 |
header('Access-Control-Allow-Origin: *'); |
但在 Laravel 當然也可以直接寫在 web.php / api.php 最前方,但我通常會建立一份 middleware 結構處理。
1 2 3 |
php artisan make:middleware Cros |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<?php namespace App\Http\Middleware; use Closure; class Cros { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { $response = $next($request); $response->header('Access-Control-Allow-Origin', '*'); return $response; } } |
首先安裝這個套件,先匯出 DB Schema 到 migration
1 2 3 |
composer require --dev "xethron/migrations-generator" |
Laravel 5.5 以後的版本,下載好後就不需安裝任何的 Providers。使用方法如:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 所有資料表 php artisan migrate:generate // 指定資料表 php artisan migrate:generate table1,table2,table3,table4,table5 // 所有資料表但排除某些表,可加參數 --ignore="table3,table4,table5" // 檢視所有可選用的參數 php artisan help migrate:generate |
不過資料表欄位的型態,若是 Enum 的時候,目前版本 v2.0.2 會出錯,請修改 src/Xethron/MigrationsGenerator/Generators/FieldGenerator.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
protected function setEnum(array $fields, $table) { foreach ($this->getEnum($table) as $column) { $column_name = isset($column->column_name) ? $column->column_name : $column->COLUMN_NAME; $column_type = isset($column->column_type) ? $column->column_type : $column->COLUMN_TYPE; $fields[$column_name]['type'] = 'enum'; $fields[$column_name]['args'] = str_replace('enum(', 'array(', $column_type); } return $fields; } |
主要是 MySQL 8 返回的欄位名稱是大寫, MariaDB 返回的是小寫,需要稍作修改就可以了。我提出了合併請求,不過我看目前開發者合併停滯在 2017 年,因為這個功能僅單次使用,我也就不再 fork 了,手改一下就好。
接著產出 seed,就下載這個套件
1 2 3 |
composer require orangehill/iseed |
一樣 Laravel 5.4 以後不需要做任何安裝設定。比較麻煩的是要個別指定匯出的資料表名稱,使用方法如
1 2 3 4 5 6 7 8 9 10 11 |
// 匯出所需資料 php artisan iseed my_table php artisan iseed my_table,another_table // 產出的 seeder class 名稱加入前綴 php artisan iseed my_table --classnamesuffix=Customizations // 強制覆蓋已存在的 seed php artisan iseed users --force |
預設只推送給 connect 單一 client 端,那如果要推送給所有人呢?可以藉由搭配訂閱的功能。
除了透過 composer 安裝 workerman 之外,還需要安裝 Channel分佈式通訊組件: workerman/channel
1 2 3 4 |
composer require workerman/workerman composer require workerman/channel |
接著貼上 start.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<?php require_once __DIR__ . '/vendor/autoload.php'; use Workerman\Worker; use Channel\Client; use Channel\Server; // 初始化一个Channel服务端 $channel_server = new Server('0.0.0.0', 2206); // Create a Websocket server $ws_worker = new Worker("websocket://0.0.0.0:2346"); // 4 processes $ws_worker->count = 4; $ws_worker->onWorkerStart = function ($worker) { // Channel客户端连接到Channel服务端 Client::connect('0.0.0.0', 2206); // 订阅broadcast事件,并注册事件回调 Client::on('broadcast', function ($event_data) use ($worker) { // 向当前worker进程的所有客户端广播消息 foreach ($worker->connections as $connection) { $connection->send($event_data); } }); }; // Emitted when data received $ws_worker->onMessage = function ($connection, $data) use ($ws_worker) { // 向所有worker进程发布broadcast事件 Channel\Client::publish('broadcast', $data); }; // Emitted when connection closed $ws_worker->onClose = function ($connection) { echo "Connection closed\n"; }; // Run worker Worker::runAll(); |
接著啟動服務,我們透過 php 運行
1 2 3 |
php start.php |
建立 Client 端部分
1 2 3 4 |
<input type="text" class="name" placeholder="請輸入姓名" autofocus> <input type="submit" value="發送" onclick="send_msg(); "> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
var wsServer = 'ws://0.0.0.0:2346'; var websocket = new WebSocket(wsServer); websocket.onopen = function (evt) { console.log("成功連接到 WebSocket 服務"); }; websocket.onclose = function (evt) { console.log("關閉連接 WebSocket 服務"); }; websocket.onmessage = function (evt) { console.log('伺服器顯示:' + evt.data); }; websocket.onerror = function (evt, e) { console.log('發生錯誤: ' + evt.data); }; // 發送訊息給所有人 const send_msg = function (){ var name = document.getElementsByClassName('name')[0].value; var msg = JSON.stringify({ message: '你好,我是' + name, }) websocket.send(msg) } |
把 hostname 位置在 127.0.0.1 的資料庫 testdb ,匯出到 dump.sql
1 2 3 |
mysqldump -h 127.0.0.1 -u root -p testdb > dump.sql |
將 dump.sql 匯入到資料庫 testdb
1 2 3 |
mysql -u root -p testdb < dump.sql |