# :-: 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();
}
更高级的应用(任务重叠,任务输出,任务钩子等),看文档,我没有试
~~~
## 邮件
## 测试