# :-: Lravel學習筆記
為了方便以后移植,就全部寫在一個頁面上
基于官方文檔和項目中實際使用的,絕大部分都是我項目中實際用到的
主要是自己記錄,如果你不小心看到了,可以去我個人博客 www.shuxiaoyuan.com 或者郵箱聯系我: sxy@shuxiaoyuan.com
*****
[TOC]
## 一些簡單的配置
Nginx的URL美化
```
location / {
try\_files $uri $uri/ /index.php?$query\_string;
}
```
開啟或關閉維護模式
```
//開啟維護模式,關閉站點
php artisan down
//message:自定義消息,retry:設置 HTTP 請求頭的 RetryAfter:
php artisan down --message="維護數據庫" --retry=60
//關閉維護模式,開啟站點
php artisan up
```
## 路由
寫在web.php里面的路由有CSRF保護,可以在 app/Http/Middleware/VerifyCsrfToken.php中排除掉
```
protected $except = [
'/wx/api/sign/msg_push','openapi/*'
];
```
~~~
//路由方法
Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);
Route::match(['get','post'],'$url',$callback);
//參數必選和可選,相當于給函數傳遞參數
Route::any('test/{id}', 'TestController@index');
在控制器中:public function(Request $request, $id){}
Route::any('test/{id?}', 'TestController@index');
//路由到頁面
Route::any('/', function () {
return view('welcome');
});
//路由到控制器,命名空間為 App\Http\Controllers
Route::any('test', 'TestController@index');
// 路由到控制器,帶命名空間的
Route::any('/wx/api/sign/msg_push', '\App\Http\Controllers\Wx\BaseController@signMsgPush');
//命名空間路由+前綴
Route::namespace('Home')->prefix('home')->group(function () {
Route::get('/index', 'IndexController@index');
});
//命名空間路由+前綴+中間件,多個中間件按照先后順序執行
Route::namespace('Wx')->prefix('wx')->middleware(['check.openid'])->group(function () {
Route::get('/index/{id}', 'IndexController@index');//首頁
});
//可以多層嵌套,執行順序是:outer 、 inner 、 array1 、 array2
//Route::group(['middleware' => 'outer'], function () {
// Route::group(['middleware' => 'inner'], function () {
// Route::group(['middleware' => ['array1', 'array2', 'auth:api']], function () {
// Route::get('test', function () {
// return;
// });
// });
// });
//});
~~~
部署使用路由緩存 ` php artisan route:cache`
清除路由緩存:` php artisan route:clear`
## 中間件
在中間件總處理session的問題,有坑,記錄一二
一、中間件會先走類的構造方法(可能跟依賴注入有關,沒有詳細的了解)
二、請詳細了解laravel一次請求的完整生命周期,如果需要在中間件中保存session在控制器中用,其實大部分情況是失敗的,第二次訪問的時候就好了,因為他是一次請求結束后(return,exit等)才會寫入session,項目中主要是寫了一個微信授權的中間件,詳細可以看我的博客這篇文章:https://www.shuxiaoyuan.com/index.php/Home/Index/article/aid/108
## 控制器
控制器依賴注入:構造函數注入、方法注入
一、構造函數注入
~~~
private $token = '';
private $wx_name = '';
private $wx_isEncryption = '';
public function __construct() {
$this->token = env('WX_TOKEN');
$this->wx_name = env('WX_NAME');
$this->wx_isEncryption = env('WX_TEST');
}
~~~
## HTTP請求和響應(參數輸入輸出,文件上傳下載,表單驗證)
## 視圖,不需要太多
## session
默認使用文件保持session,如需修改,除了在env文件中修改外,還需要在配置文件中做修改
使用database保存session:需要創建表,執行下面兩條語句
`php artisan session:table`
` php artisan migrate`
使用redis保存session:在config/database.php 中為 Redis 配置Session連接
~~~
'redis' => [
'client' => 'predis',
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
],
'session' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 6,
],
],
~~~
## 日志文件記錄
按天保存日志文件:daily
~~~
'log' => env('APP_LOG', 'daily'),
'log_max_files' => 30,//最大日志文件數
'log_level' => env('APP_LOG_LEVEL', 'debug'),
~~~
## 原生和DB操作數據庫
原生查詢:直接寫原生SQL就行
`$results = DB::select('select * from users where id = ?', [1]);`
DB查詢
```
//查詢一條數據
EventStock::where('event_id', $event_id)
->where('shop_code', $store_id)
->where('number','>','100')
->select('stock')->first();
//查詢多條數據
$users = DB::table('users')->where('start', '1')->get();
//根據主鍵取值
$user = DB::table('users')->find(1);
$user = DB::table('users')->find(['1','2','4']);
//聚合查詢
$users = DB::table('users')->count();
$price = DB::table('orders')->max('price');
```
DB新增
```
DB::table('users')->insert([
['email' => 'taylor@example.com', 'votes' => 0],
['email' => 'dayle@example.com', 'votes' => 0]
]);
//獲取自增ID
$id = DB::table('users')->insertGetId(
['email' => 'john@example.com', 'votes' => 0]
);
```
DB更新
```
DB::table('users')->where('id', 1)->update(['votes' => 1]);
DB::table('users')->increment('votes');
DB::table('users')->increment('votes', 5);
DB::table('users')->decrement('votes');
DB::table('users')->decrement('votes', 5);
```
DB刪除
```
DB::table('users')->delete();
DB::table('users')->where('votes', '>', 100)->delete();
//清空表數據并重置自增ID
DB::table('users')->truncate();
```
## 數據庫遷移
生成遷移文件
`php artisan make:migration create_users_table`
運行遷移
`php artisan migrate`
回滾遷移
回滾最后一次:`php artisan migrate:rollback`
回滾最后5次:`php artisan migrate:rollback --step=5`
回滾所有:`php artisan migrate:reset`
刪除所有表并重新遷移:` php artisan migrate:fresh`
具體怎么創建表,看文檔吧
## 數據庫填充
生成填充文件:這個里面隨便寫,循環插入,批量插入,隨便玩,復雜點的用模型工廠來快速生成大量數據
`php artisan make:seeder UsersTableSeeder`
運行填充文件填充數據
`php artisan db:seed`
`php artisan db:seed --class=UsersTableSeeder`
也可以運行其他填充類
`$this->call(UsersTableSeeder::class);`
可能需要重新生成Composer自動加載器
`composer dump-autoload`
## 采用模型工廠來批量寫入假數據
創建一個模型工廠,并指定數據庫模型:
` php artisan make:factory PostFactory --model=Post`
編寫需要寫入的字段數據:
備注:關于更多的Faker數據,請參考以下網址
https://github.com/fzaninotto/Faker
https://packagist.org/packages/fzaninotto/faker
~~~
<?php
use Faker\Generator as Faker;
$factory->define(App\Models\RushBuyEventRecord::class, function (Faker $faker) {
$idCard = new \App\Common\IdCard();
return [
'unionid' => $faker->unique()->uuid,
'event_id' => mt_rand(1,3),
'size' => $faker->numberBetween(30,45),
'city' => $faker->city,
'name' => $faker->firstNameMale,//男性名字
'id_card_number' => $idCard->getIDCard(),
'reserve_time' => $faker->date("Y-m-d H:i:s","2019-07-01"),
'type' => mt_rand(1,2),
'reserve_ip' => $faker->ipv4.', '.$faker->ipv4,
'draw_ip' => $faker->ipv4.', '.$faker->ipv4,
'milli_draw_time' => microtime(true),
'mobile' => $faker->phoneNumber,
];
});
~~~
## Eloquent ORM操作數據庫
Eloquent 模型可以觸發事件,允許你在模型生命周期中的多個時間點調用如下這些方法:
retrieved, creating, created, updating, updated, saving, saved, deleting, deleted, restoring, restored。事件允許你在一個指定模型類每次保存或更新的時候執行代碼
### when用法
~~~
return BuyEventSuccessfuls::where('store_id', $store_id)
->when($event_id, function ($query) use ($event_id) {
return $query->where('event_id', $event_id);
}, function ($query) use ($eventIds) {
return $query->whereIn('event_id', $eventIds);
})->select('id', 'name', 'mobile', 'status')
->where('status', '=', "$status")
->paginate(20)
->toArray();
~~~
### 事務
通過use 來給閉包傳參
~~~
$a = DB::transaction(function () use ($request,$id) {
$data = $request->only('name', 'serial_number', 'addre', 'lng', 'lat', 'channel', 'type', 'area', 'city');
$consume_account = $request->json('accounts');
foreach ($consume_account as $k => $v) {
$consume_account[$k]['store_id'] = $data['serial_number'];
$consume_account[$k]['password'] = password_hash($consume_account[$k]['password'], PASSWORD_BCRYPT);
$consume_account[$k]['cookie_info'] = $v['username'] . ':' . $data['serial_number'] . ':' . time();
$consume_account[$k]['state'] = 0;
$consume_account[$k]['created_at'] = date('Y-m-d H:i:s');
$consume_account[$k]['updated_at'] = date('Y-m-d H:i:s');
}
try {
Store::where('id', $id)->update($data);
DB::table('consume_login')->insert($consume_account);
DB::commit();
return true;
} catch (\Exception $exception) {
DB::rollBack();
return false;
}
});
~~~
### 在使用with的時候,默認是獲取所有字段,可以采用如下方式
指定select字段,注意,一定要有關聯id,如果去掉,會報錯或者取不到數據
~~~
public function getevent() {
return $this->hasOne('App\Models\RushBuyEvents', 'id', 'event_id')
->select('id','event_title', 'consume_start', 'consume_end');
}
public static function getEventInfoByStoreID($store_id) {
$data = RushBuyEventStores::where('store_id', $store_id)
->select('event_id','store_id')
->with('getevent')
->get()
->toArray();
dd($data);
exit;
}
~~~
打印數據為:
~~~
array:5 [
0 => array:3 [
"event_id" => 90
"store_id" => "PN0000"
"getevent" => array:4 [
"id" => 90
"event_title" => "HENDER SCHEME (F36048)"
"consume_start" => "2019-06-25 10:00:00"
"consume_end" => "2019-06-26 18:00:00"
]
]
1 => array:3 [
"event_id" => 91
"store_id" => "PN0000"
"getevent" => array:4 [
"id" => 91
"event_title" => "HENDER SCHEME (F36147)"
"consume_start" => "2019-06-26 10:00:00"
"consume_end" => "2019-06-26 18:00:00"
]
]
]
~~~
## 安全操作(加密,哈希,認證等)
## 緩存(redis)
可以用Redis的管道
發布,訂閱
## 事件
## 通知,廣播,隊列,任務調度
* 任務調度:首先需要在Linux上面創建一條計劃任務,該計劃任務是每分鐘調用laravel的命令
Linux上的命令`crontab -e `
輸入以下內容:
` * * * * * php /項目目錄/artisan schedule:run >> /dev/null 2>&1`
下面就簡單了,在Console/Commands目錄下創建任務文件
~~~
app\Console\Commands\Test.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class ImgTotext extends Command {
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'img_to_text';//命令名稱
/**
* The console command description.
*
* @var string
*/
protected $description = '圖片識別';//命名描述
/**
* Create a new command instance.
*
* @return void
*/
public function __construct() {
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle() {
//這里寫你要干嘛,隨便寫拉。
}
}
然后在 app\Console\Kernel.php文件中填寫如下內容,執行時間看具體文檔
protected function schedule(Schedule $schedule) {
$schedule->command('img_to_text')->everyMinute();
$schedule->command('send_kf_msg')->everyFiveMinutes();
}
更高級的應用(任務重疊,任務輸出,任務鉤子等),看文檔,我沒有試
~~~
## 郵件
## 測試