Laravel控制器
php artisan make:controller TaskController
# 通過Artisan命令快速創(chuàng)建一個控制器
# 該命令會在 app/Http/Controllers 目錄下創(chuàng)建一個新的名為 TaskController.php 的文件
php artisan make:controller PostController --resource
# 使用 Artisan 生成器來生成一個資源控制器(在之前命名后加上 --resource 選項)
# 打開 app/Http/Controllers/PostController.php 文件肿嘲,可看到 PostController 代碼
Route::resource('post', 'PostController');
# 寫在web.php文件中亿蒸,一次注冊包含上面列出的所有路由
php artisan route:list
# Artisan命令,查看應(yīng)用的所有路由
資源控制器方法列表
路由進階使用
Route::fallback(function(){
return '我是最后的屏障';
});
# 兜底路由展哭,請求無法匹配到的URL時返回的內(nèi)容
Route::middleware('throttle:60,1')->group(function(){
Route::get('/user', function(){
//
});
})
# 一分鐘能只能訪問路由分組的內(nèi)路由(如 /user)60 次匪蟀,超過此限制會返回 429 狀態(tài)碼并提示請求過于頻繁
# 通過內(nèi)置的throttle中間件來實現(xiàn)椎麦,接受兩個參數(shù),第一個是次數(shù)上限材彪,另一個是指定時間段(單位:分鐘
Route::middleware('throttle:rate_limit,1')->group(function () {
Route::get('/user', function () {
// 在 User 模型中設(shè)置自定義的 rate_limit 屬性值
});
Route::get('/post', function () {
// 在 Post 模型中設(shè)置自定義的 rate_limit 屬性值
});
});
php artisan route:cache
# 將所有路由定義轉(zhuǎn)化為控制器路由或資源路由后才能執(zhí)行路由緩存命令
php artisan route:clear
# 刪除路由緩存
表單方法偽造與跨站請求偽造攻擊防護
HTML 表單僅支持 GET 和 POST 兩種方式观挎,
如果要使用其他的方式琴儿,則需要自己來定義實現(xiàn)
/**
* Laravel 路由支持的 HTTP 請求方式
*
* @var array
*/
public static $verbs = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'];
Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);
# 相應(yīng)的路由定義方法
<form action="/task/1" method="POST">
<input type="hidden" name="_method" value="DELETE">
</form>
# 表單請求方法偽造
# 在表單中加一個名為'_method'的隱藏字段,字段值是 PUT嘁捷、DELETE造成、 PATCH
視圖入門
return view('以.分隔的視圖模板路徑');
# 視圖的定義方式
# 使用 view 輔助函數(shù)在路由中返回視圖
Route::get('/', function () {
// 該函數(shù)會在 resources/views 目錄下查找 home.blade.php 或 home.php 視圖文件,
// 加載文件內(nèi)容并解析 PHP 變量或語句普气,然后傳遞給響應(yīng)谜疤,最終呈現(xiàn)給用戶
return view('home');
});
return view('home')->with('tasks', Task::all());
return view('home', ['tasks' => Task::all()]);
# 傳遞數(shù)據(jù)給視圖的方法佃延,將tasks數(shù)據(jù)變量傳遞到視圖以便在視圖中引用
view()->share('siteName', 'Laravel學(xué)院');
view()->share('siteUrl', 'https://xueyuanjun.com');
# 通過視圖對象提供的share方法實現(xiàn)在視圖間共享變量
# 比如在AppServiceProvider 的 boot 方法中定義共享的視圖變量
# 然后就可以在各個視圖中使用 $siteName 和 $siteUrl 這兩個變量了(其它變量定義方式類似)
Blade入門篇
# Blade模板代碼實例
<h1>{{ $group->title }}</h1>
{!! $group->imageHtml() !!}
@forelse ($users as $user)
{{ $user->username }} {{ $user->nickname }}<br>
@empty
該組中沒有任何用戶
@endforelse
# 通過 {{ }} 渲染 PHP 變量(最常用)
# 通過 {!! !!} 渲染原生 HTML 代碼(用于富文本數(shù)據(jù)渲染)
# 通過以 @ 作為前綴的 Blade 指令執(zhí)行一些控制結(jié)構(gòu)和繼承现诀、引入之類的操作
# Blade 模板代碼存放在以 .blade.php 后綴結(jié)尾的視圖文件中
# 編譯后的代碼位于 storage/framework/views 目錄下
{{ $variable }}
# 編譯后的最終代碼(避免XSS攻擊):
<?php echo htmlentities($variable); ?>
# 對于當(dāng)前端框架也用{{}}輸出js變量的情況
# 需要在渲染前端js變量的{{}}前面加上@前綴
# Blade 引擎會將其編譯為對應(yīng)的 PHP 代碼
{{ $phpData }}
# Blade 引擎編譯時會移除 @,保留 {{ $vueData }} 結(jié)構(gòu)
@{{ $vueData }}
# 條件語句
@if (count($students) === 1)
操場上只有一個同學(xué)
@elseif (count($students) === 0)
操場上一個同學(xué)也沒有
@else
操場上有 {{ count($students) }} 個同學(xué)
@endif
# 表示和 @if 條件相反的條件
@unless ($user->hasPaid())
用戶沒有支付
@endunless
# 和 isset() empty() 方法等價
@isset($records)
// 記錄被設(shè)置
@endisset
@empty($records)
// 記錄為空
@endempty
@switch($i)
@case(1)
// $i = 1 做什么
@break
@case(2)
// $i = 2 做什么
@break
@default
// 默認(rèn)情況下做什么
@endswitch
// for 循環(huán)
@for ($i = 0; $i < $talk->slotsCount(); $i++)
The number is {{ $i }}<br>
@endfor
// foreach 循環(huán)
@foreach ($talks as $talk)
{{ $talk->title }} ({{ $talk->length }} 分鐘)<br>
@endforeach
// while 循環(huán)
@while ($item = array_pop($items))
{{ $item->orSomething() }}<br>
@endwhile
@forelse ($students as $student)
// do something ...
@empty
// do something else ...
@endforelse
# 用于處理一下的PHP代碼邏輯:
<?php
if ($students) {
foreach ($students as $student) {
// do something ...
}
} else {
// do something else ...
}
?>
Blade進階篇
1.通過
@yield
和@section/@show
在布局文件中定義插槽履肃。
2.通過@extends
和@section/@endsection
在子視圖實現(xiàn)繼承仔沿。
3.通過@include
引入其他視圖組件
4.通過@each
指令循環(huán)引入單個組件,支持多個參數(shù)尺棋。
5.通過@slot
和@component
實現(xiàn)更加靈活的內(nèi)容分發(fā)封锉。
Blade高級篇
不知道寫啥...
使用Bootstrap、Vue
composer require laravel/ui #通過Composer下載安裝
# 初始化前端腳手架
php artisan ui bootstrap
php artisan ui vue
npm install # 安裝應(yīng)用的前端依賴
npm run dev
# 編寫Vue組件
# 將Vue組件寫在 resources/js/components目錄下
# 在resources/js/app.js中全局注冊
Vue.component('welcome-component', require('./components/WelcomeComponent.vue').default);
const app = new Vue({
el: '#app'
});
# 完了修改welcome.blade.php代碼膘螟,再 npm run dev就好啦~
# Vue組件名開頭一定要大寫
使用Laravel Mix編譯前端資源
npm install # 安裝需要的依賴
npm run dev # 運行所有 Mix 任務(wù)
npm run watch # 監(jiān)控成福,發(fā)現(xiàn)修改后自動重新編譯文件
mix.less('resources/assets/less/app.less', 'public/css'); # 編譯 less 文件
mix.less('resources/assets/less/app.less', 'public/stylesheets/styles.css'); # 自定義編譯后文件的輸出位置
mix.sass('resources/assets/sass/app.scss', 'public/css'); # 編譯 sass 文件,同上
mix.stylus('resources/assets/stylus/app.styl', 'public/css'); # 編譯 stylus 文件
mix.js('resources/assets/js/app.js', 'public/js'); # 處理js
mix.js('resources/assets/js/app.js', 'public/js')
.extract(['vue']) # 提取 Vendor 庫
mix.react('resources/assets/js/app.jsx', 'public/js'); # 支持 React
mix.copy('node_modules/foo/bar.css', 'public/css/bar.css'); # 拷貝文件/目錄
mix.js('resources/assets/js/app.js', 'public/js')
.version(); # 緩存刷新
<link rel="stylesheet" href="{{ mix('css/app.css') }}"> # 在視圖中使用 Laravel 全局的 Mix 函數(shù)加載前端資源
mix.browserSync('my-domain.test');
// Or...
// https://browsersync.io/docs/options
mix.browserSync({
proxy: 'my-domain.test'
});
# 自動監(jiān)控文件修改
通過遷移文件定義數(shù)據(jù)表結(jié)構(gòu)
$table->string('name', 100)->comment('用戶名'); # 為字段額外添加注釋信息
Schema::dropIfExists('user'); # 刪除表(在down()方法中
php artisan make:migration alter_users_add_nickname --table=users
# 修改表應(yīng)在新增遷移文件中操作
$table->string('nickname', 100)->after('name')->nullable()->comment('用戶昵稱'); # 新增 nickname 字段
$table->dropColumn('nickname'); # 刪除一個已存在的字段
composer require doctrine/dbal # 對已存在的數(shù)據(jù)表字段修改荆残,先安裝擴展包
$table->string('nickname', 50)->change(); # 修改字段長度
$table->renameColumn('name', 'username'); # 重命名字段
$table->string('email')->unique(); # 添加唯一索引
$table->increments('id'); # 創(chuàng)建自動增長的主鍵索引
$table->index(['name', 'email']); # 支持一次傳入多個字段奴艾,構(gòu)建混合索引
# ↓不推薦使用,影響數(shù)據(jù)庫性能
$table->foreign('user_id')->references('id')->on('users');
# 建立文章表中的 user_id 字段與用戶表中的 id 之間的關(guān)聯(lián)關(guān)系
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onUpdate('cascade');
# 外鍵約束
$table->dropForeign(['user_id']); # 刪除外鍵索引
php artisan migrate # 執(zhí)行變更
php artisan migrate:rollback # 回滾最后一個遷移文件的變更
php artisan migrate:rollback --step=5 # 回滾多個遷移文件的變更内斯,可以通過 --step= 指定步數(shù)
php artisan migrate:reset # 回滾所有遷移文件的變更蕴潦,將數(shù)據(jù)庫恢復(fù)到初始狀態(tài)
通過填充器快速填充測試數(shù)據(jù)
database/seeds/DatabaseSeeder.php
php artisan db:seed # 一次性調(diào)用所有填充器
# 需要將所有對其他填充器的調(diào)用定義在該方法中↓
$this->call(UsersTableSeeder::class);
php artisan db:seed --class=UsersTableSeeder # 指定某個填充器類的run方法
php artisan make:seeder UsersTableSeeder # 為users表快速創(chuàng)建一個填充器類 UsersTableSeeder
eg: # 填充邏輯
public function run()
{
DB::table('users')->insert([
'name' => \Str::random(10),
'email' => \Str::random(10).'@gmail.com',
'password' => bcrypt('secret'),
]);
}
# laravel 7 str_random()無效,應(yīng)改成如上\Str::random
php artisan db:seed --class=UsersTableSeeder # 運行
# 也可以在DatabaseSeeder 類的 run 方法中運行這個填充器類
# 適用于多個填充器類一次運行的情況↓
public function run()
{
$this->call(UsersTableSeeder::class);
}
# 然后↓
php artisan db:seed
# Laravel 自帶一個用于填充 User 模型的模型工廠 UserFactory.php
php artisan make:factory PostFactory --model=Post # 為模型類創(chuàng)建一個模型工廠
# 在UsersTableSeeder 的 run 方法中通過模型工廠改寫數(shù)據(jù)填充方法↓
# 傳入對應(yīng)模型類和要填充的記錄數(shù)
factory(\App\User::class, 5)->create();
php artisan db:seed --class=UsersTableSeeder
# 運行命令來填充數(shù)據(jù)庫
通過查詢構(gòu)建器實現(xiàn)簡單的增刪改查操作
在laravel中不要通過 DB
門面提供的 statement
方法執(zhí)行原生的 SQL Statement 語句俘闯,比如創(chuàng)建潭苞、刪除、修改數(shù)據(jù)表操作真朗,這些操作可以通過數(shù)據(jù)庫遷移來實現(xiàn)此疹,而且可維護性更好。
# 寫在控制器里
$users = DB::select('select * from `users`'); # 查遮婶,返回所有結(jié)果的對象數(shù)組
# 指定查詢條件蝗碎,借助 PDO 的參數(shù)綁定功能來防范 SQL 注入
$name = 'kong';
$users = DB::select('select * from `users` where `name` = ?', [$name]);
# 改
$name = '空空';
$id = 1;
$affectedRows = DB::update('update `users` set `name` = ? where id = ?', [$name, $id]);
# 刪
$id = 7;
$affectedRows = DB::delete('delete from `users` where id = ?', [$id]);
# 使用查詢構(gòu)建器進行增刪改查
$users = DB::table('users')->get(); # 查
# 指定查詢條件,無需手動設(shè)置參數(shù)綁定來規(guī)避 SQL 注入攻擊
$name = '空空';
$users = DB::table('users')->where('name', $name)->get();
$user = DB::table('users')->where('name', $name)->first(); # 返回查詢結(jié)果中的第一條記錄
$user = DB::table('users')->select('id', 'name', 'email')->where('name', $name)->first(); # 指定查詢的字段
# 增/插入記錄
$flag = DB::table('users')->insert([
'name' => \Str_random(10),
'email' => \Str_random(8) . '@163.com',
'password' => bcrypt('secret')
]);
# 插入之后獲取對應(yīng)記錄的主鍵 ID
$userId = DB::table('users')->insertGetId([
'name' => \Str_random(10),
'email' => \Str_random(8) . '@qq.com',
'password' => bcrypt('secret')
]);
# 支持一次插入多條記錄
# 改/更新
$id = 11;
$affectedRows = DB::table('users')->where('id', '>', $id)->update(['name' => \Str_random(8)]);
# where 方法第二個參數(shù)省略的話蹭睡,默認(rèn)是 =
# 如果不是相等條件需要手動指定該參數(shù)值衍菱, > 大于,< 小于肩豁,和比較運算符一致
# 刪
$id = 11;
$affectedRows = DB::table('users')->where('id', '>=', $id)->delete();
$affectedRows = DB::table('users')->delete(); # 清空
$affectedRows = DB::table('users')->truncate(); # 清空后重置自增ID
通過查詢構(gòu)建器實現(xiàn)復(fù)雜的查詢語句
$name = '空空';
$email = DB::table('users')->where('name', $name)->value('email'); # 直接獲取指定字段的值
$exists = DB::table('users')->where('name', $name)->exists(); # 判斷字段值是否存在
$users = DB::table('users')->where('id', '<', 10)->pluck('name', 'id'); # 構(gòu)建關(guān)聯(lián)數(shù)組
# ↑鍵對應(yīng)的字段在后面脊串,值對應(yīng)的字段在前面
# 避免一次返回所有值超出php內(nèi)存限制的辦法
# 對 users 按照 id 字段升序排序后將獲取的結(jié)果集每次返回5個進行處理辫呻,將用戶名依次放到 $names 數(shù)組中
$names = [];
DB::table('users')->orderBy('id')->chunk(5, function ($users) use (&$names) {
foreach ($users as $user) {
$names[] = $user->name;
}
});
# 聚合函數(shù)
$num = DB::table('users')->count(); # 計數(shù) 9
$sum = DB::table('users')->sum('id'); # 求和 45
$avg = DB::table('users')->avg('id'); # 平均值 5
$min = DB::table('users')->min('id'); # 最小值 1
$max = DB::table('users')->max('id'); # 最大值 9
# 基礎(chǔ)查詢
DB::table('posts')->where('views', 0)->get(); # 此處等號可以省略
DB::table('posts')->where('views', '>', 0)->get(); # 字段名,運算符琼锋,比較值
DB::table('posts')->where('title', 'like', 'Laravel學(xué)院%')->get(); # 模糊查詢
DB::table('posts')->where('id', '<', 10)->where('views', '>', 0)->get(); # 多個條件
DB::table('posts')->where([
['id', '<', 10],
['views', '>', 0]
])->get(); # 另一種寫法
DB::table('posts')->where('id', '<', 10)->orWhere('views', '>', 0)->get(); # or條件的查詢
DB::table('users')->whereBetween('id', [2, 4])->get(); # between查詢
DB::table('users')->whereNotBetween('id', [2, 4])->get(); # 獲取不在指定區(qū)間的記錄
DB::table('posts')->whereIn('id', [1, 3, 5, 7, 9])->get(); # in查詢放闺,還有whereNotIn
DB::table('users')->whereNull('email')->get(); # NULL查詢,還有whereNotNull
# 日期查詢
DB::table('posts')->whereYear('created_at', '2018')->get(); # 年
DB::table('posts')->whereMonth('created_at', '11')->get(); # 月
DB::table('posts')->whereDay('created_at', '28')->get(); # 一個月的第幾天
DB::table('posts')->whereDate('created_at', '2018-11-28')->get(); # 具體日期
DB::table('posts')->whereTime('created_at', '14:00')->get(); # 時間
DB::table('posts')->whereColumn('updated_at', '>', 'created_at')->get(); # 字段相等查詢
DB::table('users')
->where('options->language', 'en')
->get(); # JSON屬性查詢
DB::table('users')
->whereJsonContains('options->languages', 'en_US')
->get();
DB::table('users')
->whereJsonContains('options->languages', ['en_US', 'zh_CN'])
->get(); # 數(shù)組的包含查詢
# 參數(shù)分組
select * from posts where id <= 10 or (views > 0 and created_at < '2018-11-28 14:00');
# 查詢構(gòu)建器的實現(xiàn)↓
DB::table('posts')->where('id', '<=', 10)->orWhere(function ($query) {
$query->where('views', '>', 0)
->whereDate('created_at', '<', '2018-11-28')
->whereTime('created_at', '<', '14:00');
})->get();
# where exists
select * from `users` where exists (select 1 from `posts` where posts.user_id = users.id);
# 查詢構(gòu)建器的實現(xiàn)↓
DB::table('users')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('posts')
->whereRaw('posts.user_id = users.id');
})
->get();
# 子查詢
select * from posts where user_id in (select id from users where email_verified_at is not null);
# 查詢構(gòu)建器的實現(xiàn)↓
$users = DB::table('users')->whereNotNull('email_verified_at')->select('id');
$posts = DB::table('posts')->whereInSub('user_id', $users)->get();
創(chuàng)建并填充posts表
php artisan make:migration create_posts_table --create=posts # 新建 posts 數(shù)據(jù)表
# 在CreatePostsTable 的 up里:
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title')->comment('標(biāo)題');
$table->text('content')->comment('內(nèi)容');
$table->integer('user_id')->unsigned()->default(0);
$table->integer('views')->unsigned()->default(0)->comment('瀏覽數(shù)');
$table->index('user_id');
$table->timestamps();
});
}
php artisan migrate # 創(chuàng)建表
php artisan make:model Post # 創(chuàng)建模型類
php artisan make:factory PostFactory --model=Post # 創(chuàng)建模型工廠
# database/factories/PostFactory.php:
$factory->define(\App\Post::class, function (Faker $faker) {
return [
'title' => $faker->title,
'content' => $faker->text,
'user_id' => mt_rand(1, 15),
'views' => $faker->randomDigit
];
});
php artisan make:seeder PostsTableSeeder # 為posts表創(chuàng)建填充類
# PostsTableSeeder里:
public function run()
{
factory(\App\Post::class, 30)->create();
}
php artisan db:seed --class=PostsTableSeeder # 填充 posts 數(shù)據(jù)表
# 內(nèi)連接
$posts = DB::table('posts')
->join('users', 'users.id', '=', 'posts.user_id')
->select('posts.*', 'users.name', 'users.email')
->get();
# 當(dāng)兩張表有字段名相同的字段并被select指定時缕坎,要區(qū)別名
select('posts.*', 'users.name as username', 'users.email')
# 左連接
$posts = DB::table('posts')
->leftJoin('users', 'users.id', '=', 'posts.user_id')
->select('posts.*', 'users.name', 'users.email')
->get();
# 右連接
$posts = DB::table('posts')
->rightJoin('users', 'users.id', '=', 'posts.user_id')
->select('posts.*', 'users.name', 'users.email')
->get();
DB::table('posts')->orderBy('created_at', 'desc')->get(); # # 按照創(chuàng)建時間進行逆序排序
DB::table('posts')->orderBy('created_at')->get(); # 升序排序
DB::table('posts')->inRandomOrder()->get(); # 隨機排序(結(jié)果集很大的不要用怖侦,性能比較差
# 分組
$posts = DB::table('posts')
->groupBy('user_id')
->selectRaw('user_id, sum(views) as total_views')
->having('total_views', '>=', 10) # 對分組結(jié)果進行過濾
->get();
# 分頁
$posts = DB::table('posts')->orderBy('created_at', 'desc')
->where('views', '>', 0)
->skip(10) # 表示從第幾條記錄開始,也可以用 offset()
->take(5) # 表示一次獲取多少條記錄,也可以用 limit()
->get();
通過 Eloquent 模型實現(xiàn)簡單增刪改查操作
Eloquent 約定模型類映射表名是將類名由駝峰格式轉(zhuǎn)化為小寫+下劃線(含多個單詞的話)谜叹,最后將其轉(zhuǎn)化為復(fù)數(shù)形式匾寝,比如 Post
對應(yīng)表名是 posts
、PostTag
對應(yīng)表名是 post_tags
荷腊。
Eloquent 默認(rèn)約定每張表都有 created_at
和 updated_at
字段(遷移類中 $table->timestamps()
會生成這兩個字段)艳悔,并且在保存模型類時會自動維護這兩個字段。
# 創(chuàng)建模型類
php artisan make:model Post # 這樣生成Post.php在app目錄下
php artisan make:model Models/Post # 如果要指定創(chuàng)建的model到某個目錄女仰,可以先`目錄名稱/model名字`猜年,這里會將Post.php存放到app/Models目錄下
protected $primaryKey = 'post_id'; # 設(shè)置自增主鍵,默認(rèn)為id
public $incrementing = false; # 設(shè)置非自增主鍵
protected $keyType = 'string'; # 設(shè)置非整型主鍵
public $timestamps = false; # 不設(shè)置時間戳
public const CREATED_AT = 'create_time';
public const UPDATED_AT = 'update_time'; # 設(shè)置自定義的創(chuàng)建和更新時間字段
protected $dateFormat = 'U'; # 自定義時間戳的格式疾忍,這里設(shè)置為Unix 時間戳
protected $connection = 'connection_name'; # 為模型類指定使用哪個連接
$posts = Post::all(); # 獲取一張表的所有記錄
foreach ($posts as $post) {
dump($post->title);
} # 獲取指定模型類的字段屬性乔外,遍歷
foreach (Post::cursor() as $post) {
dump($post->title . ':' . $post->content);
} # 每次只獲取一條查詢結(jié)果,最大限度減少內(nèi)存消耗
$posts = Post::where('views', '>', 0)
->select('id', 'title', 'content') # 指定查詢條件和查詢字段
->get();
$posts = Post::where('views', '>', 0)
->orderBy('id', 'desc')
->offset(10)
->limit(5)
->get(); # 排序分頁
$user = User::where('name', '空空')->first(); # 獲取單條記錄
$user = User::find(1); # 簡化↑
# 聚合結(jié)果
$num = User::whereNotNull('email_verified_at')->count(); # 計數(shù)
$sum = User::whereNotNull('email_verified_at')->sum('id'); # 求和
$avg = User::whereNotNull('email_verified_at')->avg('id'); # 平均值
$min = User::whereNotNull('email_verified_at')->min('id'); # 最小值
$max = User::whereNotNull('email_verified_at')->max('id'); # 最大值
# 插入數(shù)據(jù)
$post = new App\Post;
$post->title = '測試文章標(biāo)題';
$post->content = '測試文章內(nèi)容';
$post->user_id = 1;
$post->save();
# 更新
$post = Post::find(31);
$post->title = '測試文章標(biāo)題更新';
$post->save();
Post::where('views', '>', 0)->update(['views' => 100]); # 批量更新
# 刪除
$post = Post::find(31);
$post->delete();
# 一次刪除多條記錄一罩,通過數(shù)組傳遞多個主鍵 ID
Post::destroy([1,2,3]);
# 刪除指定記錄
$user = User::where('name', '空空')->fisrt();
$user->delete();
通過 Eloquent 模型實現(xiàn)批量賦值和軟刪除
$post = new Post([
'title' => '測試文章標(biāo)題',
'content' => '測試文章內(nèi)容'
]); # 將待設(shè)置屬性以關(guān)聯(lián)數(shù)組的方式傳遞構(gòu)造函數(shù)
$post = new Post($request->all()); # 批量賦值杨幼,等同于上面的賦值方式
// 注意:白名單與黑名單不可同時使用
/**
*(白名單) 使用批量賦值的屬性,只有在這里設(shè)置的字段才會批量賦值
* @var array
*/
protected $fillable = [];
/**
* (黑名單) 不使用批量賦值的字段擒抛,如果為星號表示所有字段都不賦值
*
* @var array
*/
protected $guarded = ['*'];
# 更新
$post = Post::findOrFail(1); # 獲取相應(yīng)id的數(shù)據(jù)推汽,沒有相應(yīng)數(shù)據(jù)會報錯404
$post->fill($request->all());
$post->save();
# 通過數(shù)據(jù)庫遷移添加deleted_at字段,實現(xiàn)軟刪除
php artisan make:migration alter_posts_add_deleted_at --table=posts
# 在遷移文件中:
public function up()
{
Schema::table('posts', function (Blueprint $table) {
$table->softDeletes();
});
}
public function down()
{
Schema::table('posts', function (Blueprint $table) {
$table->dropColumn('deleted_at');
});
}
php artisan migrate # 執(zhí)行變更
# 在模型類中:
use SoftDeletes;
# 判斷是否被刪除
$post = Post::findOrFail(2); # 獲取指定id數(shù)據(jù)
$post->delete(); # 刪了它歧沪!
if ($post->trashed()) {
dump('該記錄已刪除');
} # 通過 trashed() 查詢
$post = Post::onlyTrashed()->where('views', 0)->get(); # 獲取被軟刪除的數(shù)據(jù)
$post = Post::onlyTrashed()->where('views', 0)->get(); # 物理刪除歹撒,整條數(shù)據(jù)直接沒咯
在 Eloquent 模型類上設(shè)置訪問器和修改器
# 要實現(xiàn)這樣的邏輯:
if ($user->nickname) {
$user->display_name = $user->nickname; // 顯示用戶名為用戶昵稱
} else {
$user->display_name = $user->name; // 顯示用戶名為注冊時的用戶名
}
# 應(yīng)在user模型類中設(shè)置對應(yīng)方法(訪問器
public function getDisplayNameAttribute()
{
return $this->nickname ? $this->nickname : $this->name;
}
# 方法名不能設(shè)置為 getNameAttribute之類的,這樣會與數(shù)據(jù)庫字段重復(fù)诊胞,報錯
# 在字段值保存到數(shù)據(jù)庫之前進行一定處理滿足需求后再存(修改器
public function setCardNoAttribute($value)
{
$value = str_replace(' ', '', $value); // 將所有空格去掉
$this->attributes['card_no'] = encrypt($value);
}
# 通過模型類保存一個銀行卡號到數(shù)據(jù)庫
$user = User::find(1);
$user->card_no = '6222020903001483077';
$user->save();
# 數(shù)據(jù)&JSON轉(zhuǎn)化
# 新建字段settings(MySQL 5.7以下的版本設(shè)置字段類型為TEXT格式
protected $casts = [
'settings' => 'array'
];
laravel查看數(shù)據(jù)庫的版本dd(DB::select("select version()"));
Eloquent 模型事件和監(jiān)聽方式大全
所有支持的模型事件:
-
retrieved
:獲取到模型實例后觸發(fā) -
creating
:插入到數(shù)據(jù)庫前觸發(fā) -
created
:插入到數(shù)據(jù)庫后觸發(fā) -
updating
:更新到數(shù)據(jù)庫前觸發(fā) -
updated
:更新到數(shù)據(jù)庫后觸發(fā) -
saving
:保存到數(shù)據(jù)庫前觸發(fā)(插入/更新之前暖夭,無論插入還是更新都會觸發(fā)) -
saved
:保存到數(shù)據(jù)庫后觸發(fā)(插入/更新之后,無論插入還是更新都會觸發(fā)) -
deleting
:從數(shù)據(jù)庫刪除記錄前觸發(fā) -
deleted
:從數(shù)據(jù)庫刪除記錄后觸發(fā) -
restoring
:恢復(fù)軟刪除記錄前觸發(fā) -
restored
:恢復(fù)軟刪除記錄后觸
Eloquent 模型關(guān)聯(lián)關(guān)系
1.通過數(shù)據(jù)庫遷移新建表+創(chuàng)建對應(yīng)模型
2.在新表中添加相應(yīng)字段用于建立關(guān)聯(lián)
3.通過模型類建立兩表之間的關(guān)聯(lián)
4.通過填充器寫入數(shù)據(jù)
5.通過關(guān)聯(lián)方法名作為動態(tài)屬性訪問模型實例
一對一撵孤,以user
和user_profile
為例迈着。
# 1.一次完成創(chuàng)建表&對應(yīng)模型
$ php artisan make:model UserProfile -m
# 2.在 user_profile 中新建 user_id 字段
# 3.建立關(guān)聯(lián),這里是在 User 模型類中定義關(guān)聯(lián)
public function profile()
{
return $this->hasOne(UserProfile::class);
}
# 5.訪問實例
$user = User::findOrFail(1);
$profile = $user->profile;
# 建立相對的關(guān)聯(lián)關(guān)系邪码,通過UserProfile 反查所屬的 User 模型
# 3.在 UserProfile 模型類定義與 User 模型的關(guān)聯(lián)
public function user()
{
return $this->belongsTo(User::class);
}
# 5.訪問
$profile = UserProfile::findOrFail(2);
$user = $profile->user;
一對多裕菠,以 users
和 posts
表為例。
# 3.在 `User` 模型類中用 `hasMany` 方法建立關(guān)聯(lián)
public function posts()
{
return $this->hasMany(Post::class);
}
# 5.訪問
$user = User::findOrFail(1);
$posts = $user->posts;
# 建立相對的關(guān)聯(lián)關(guān)系闭专,比如在文章詳細(xì)頁或列表頁顯示作者信息
# 3.
public function user()
{
return $this->belongsTo(User::class);
}
# 5.
$post = Post::findOrFail(29);
$author = $post->user;
# 還可以將 Post 模型中的關(guān)聯(lián)關(guān)系調(diào)方法名修改為 author
# 這樣可手動指定傳入的參數(shù)
# 3.
public function author()
{
return $this->belongsTo(User::class, 'user_id', 'id', 'author');
}
# 5.
$author = $post->author;
與 hasOne
返回的是單個模型實例不一樣奴潘,hasMany
返回的是模型類集合旧烧。
多對多,以文章標(biāo)簽為例(posts
画髓、 tags
掘剪、 post_tags
# 2. 在中間表(post_tags)中新建 post_id 、tag_id 字段
# 3.在 Post 模型中定義其與 Tags 模型類的關(guān)聯(lián)關(guān)系
public function tags()
{
return $this->belongsToMany(Tag::class, 'post_tags');
}
# 5.
$post = Post::findOrFail(1);
$tags = $post->tags;
# 建立相對的關(guān)聯(lián)關(guān)系
# 3. 在 Tag 模型類中建立與 Post 模型的關(guān)聯(lián)關(guān)系
public function posts()
{
return $this->belongsToMany(Post::class, 'post_tags');
}
# 5.
$tag = Tag::with('posts')->where('name', 'ab')->first();
$posts = $tag->posts;
# 返回中間表字段
$post->pivot->tag_id
# 返回額外字段奈虾,在建立關(guān)聯(lián)關(guān)系時手動指定
public function tags()
{
return $this->belongsToMany(Tag::class, 'post_tags')->withPivot('user_id')->withTimestamps();
}
遠(yuǎn)層一對多關(guān)聯(lián)夺谁,以 users
、 posts
肉微、 countries
為例
# 1.2.新建 country 模型及表匾鸥,為 users 表新增 country_id 字段
# 3. 在 Country 模型類中定義關(guān)聯(lián)
public function posts()
{
return $this->hasManyThrough(Post::class, User::class);
} # 第一個參數(shù):關(guān)聯(lián)的模型類,第二個:中間借助的模型類
# 5.
$country = Country::findOrFail(1);
$posts = $country->posts;
# countries(user_id) - user(country_id) - posts(user_id)
一對一的多態(tài)關(guān)聯(lián)浪册,以 images
扫腺、user
、 posts
為例村象,讓用戶和文章共享與圖片的一對一關(guān)聯(lián)。
# 1.2.新建 Image 模型類及表
# 創(chuàng)建 imageable_id 和 imageable_type 兩個字段
# imageable_type 插入完整的類名以表類型 App\User 或 App\Post
$table->morphs('imageable');
# 3.
public function imageable()
{
return $this->morphTo();
}
#5.
$image = Image::findOrFail(1);
$item = $image->imageable;
# 定義相對的關(guān)聯(lián)關(guān)系
# 3.
# 在 User 模型中定義與 Image 模型的關(guān)聯(lián)
public function image()
{
return $this->morphOne(Image::class, 'imageable');
}
# 在 Post 模型中定義其與 Image 模型的關(guān)聯(lián)
public function image()
{
return $this->morphOne(Image::class, 'imageable');
}
# 5.
$post = Post::findOrFail(1);
$image = $post->image;
(插眼)一對多的多態(tài)關(guān)聯(lián)攒至,新建 comment 評論模型類厚者。
#3.
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
模型關(guān)聯(lián)關(guān)系(下)
懶惰式加載
# 基于關(guān)聯(lián)查詢過濾模型實例
# 有結(jié)果過濾
$users = User::has('posts')->get(); # 獲取所有發(fā)發(fā)布過文章的用戶
$users = User::has('posts', '>', 1)->get(); # 過濾發(fā)布文章數(shù)量大于 1 的用戶
$users = User::has('posts.comments')->get(); # 過濾發(fā)布的文章有評論的用戶
$posts = Post::has('comments')->orHas('tags')->get(); # 過濾包含評論或標(biāo)簽的文章
$users = User::whereHas('posts', function ($query) {
$query->where('title', 'like', '空空%');
})->get(); # 基于閉包函數(shù)定義查詢條件
# 無結(jié)果過濾
# 與 has/orHas 方法相對的 doesntHave/orDoesntHave 方法
# 不加載關(guān)聯(lián)模型的情況下統(tǒng)計關(guān)聯(lián)結(jié)果的數(shù)量
# 通過 Eloquent 提供的 withCount 方法
$post = Post::withCount('comments')->findOrFail(32); # 統(tǒng)計某篇文章的評論數(shù)
渴求式加載
$post = Post::with('author')->findOrFail(1);
$author = $post->author;
# 支持一次加載多個關(guān)聯(lián)模型(參數(shù)為對應(yīng)關(guān)聯(lián)方法名
$posts = Post::with('author', 'comments', 'tags')->findOrFail(1);
# 支持嵌套查詢
$post = Post::with('author.profile')->findOrFail(1);
# 指定要加載的字段
$post = Post::with('author:id,name')->findOrFail(1);
# 通過閉包傳入額外的約束條件
$post = Post::with(['comments' => function ($query) {
$query->where('content', 'like', '空空%')
->orderBy('created_at', 'desc');
}])->where('id', '<', 5)->get();
懶惰渴求式加載
通過動態(tài)條件判斷進行渴求式加載或者延遲加載,通過 load
方法實現(xiàn)迫吐。
$users = User::all();
$condition = true;
if ($condition) {
$users->load('posts');
}
# 支持通過閉包傳遞額外的約束條件
$posts = Post::where('id', '<=', 3)->get();
$posts->load(['comments' => function ($query) {
$query->where('content', 'like', 'Laravel學(xué)院%')
->orderBy('created_at', 'desc');
}]);
異步分頁
結(jié)合 Bootstrap 和 Vue 組件實現(xiàn)異步分頁功能库菲,需要在后端定義好分頁數(shù)據(jù)獲取 API 接口。
# 定義后端 API 接口
# 1.在 PostController 中定義一個 fetch 方法用于異步獲取分頁數(shù)據(jù)
# 2.在 routes/api/php 中定義指向該控制器方法的 API 路由
# 測試API 接口志膀,在瀏覽器中請求 http://blog.test/api/posts/fetch
# 3.在控制器的文章首頁列表方法 index 中熙宇,返回一個視圖用于渲染文章列表
# 創(chuàng)建文章列表視圖
# 4.新建 resources/views/post/index.blade.php,編寫視圖代碼
# 創(chuàng)建 Vue 分頁組件
# 5.新建 resources/js/components/PaginationComponent.vue溉浙,初始化代碼并在 resources/js/app.js 中注冊組件
# 6. npm run dev編譯前端資源