# laravel model
8.61 可以用 --all
建立
model
factory
seeder
policy
controller
migrate
## cast (larvel 8^)
https://www.youtube.com/watch?v=i4RGuYj7zi0&ab_channel=Laracasts
## touch


## 不可變的carbon 在casts
8.5以後
https://www.youtube.com/watch?v=UekvqwHvWp4&ab_channel=Laratips
## 自訂relation
https://stitcher.io/blog/laravel-custom-relation-classes
## view
https://stitcher.io/blog/eloquent-mysql-views
## morphMap
比morphMap 好 會檢查 也不用重新build

## 自定relation
through可能不好用 可以自訂
https://stitcher.io/blog/laravel-custom-relation-classes
## update_at關掉
https://learnku.com/laravel/t/5199/the-laravel-lumen-eloquent-model-removes-one-of-the-created-at-and-updated-at
## creating saveing差異
https://medium.com/@lynnlin827/laravel-eloquent-%E4%BA%8B%E4%BB%B6%E4%B8%AD%E7%9A%84-updated-%E5%92%8C-saved-%E5%8E%9F%E4%BE%86%E4%B8%8D%E4%B8%80%E6%A8%A3-caa8ef0ddbc
## Default Attribute Values




## upsert

## 訪問器
https://chebincarl.github.io/2020/06/11/Laravel-Database-Eloquent-Model%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%EF%BC%88%E4%B8%8A%EF%BC%89/
## 數組對象和集合轉換
儘管標準array鑄件足以滿足許多應用,但它確實有一些缺點。由於array強制轉換返回原始類型,因此無法直接改變數組的偏移量。例如,以下代碼將觸發 PHP 錯誤:
```
$user = User::find(1);
$user->options['key'] = $value;
```
為了解決這個問題,Laravel 提供了一個AsArrayObject將 JSON 屬性轉換為ArrayObject類的轉換。這個特性是使用 Laravel 的自定義轉換實現來實現的,它允許 Laravel 智能地緩存和轉換變異對象,以便可以修改單個偏移量而不會觸發 PHP 錯誤。要使用AsArrayObject演員表,只需將其分配給一個屬性:
```
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'options' => AsArrayObject::class,
];
```
同樣,Laravel 提供了一個AsCollection轉換,將你的 JSON 屬性轉換為 Laravel Collection實例:
## casts 抓取自己的屬性
```
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Set the user's first name.
*
* @param string $value
* @return void
*/
public function setFirstNameAttribute($value)
{
$this->attributes['first_name'] = strtolower($value);
}
}
```
mutator 將接收在屬性上設置的值,允許您操縱該值並在 Eloquent 模型的內部$attributes屬性上設置操縱值。要使用我們的 mutator,我們只需要first_name在 Eloquent 模型上設置屬性:
```
use App\Models\User;
$user = User::find(1);
$user->first_name = 'Sally';
```
在此示例中,setFirstNameAttribute將使用 value 調用該函數Sally。然後,mutator 將該strtolower函數應用於名稱並將其結果值設置在內部$attributes數組中。
## 關聯必看
https://learnku.com/articles/65733
## 外键的默认名称
另一个不同是外键的默认名称,不再是类名 + 主键名,而是关联名 + 主键名:
```
if (is_null($foreignKey)) {
$foreignKey = Str::snake($relation).'_'.$instance->getKeyName();
}
```
## 获取中间表中的关联关系数据
在多对多关系中,您定义的中间表里面可能会包含扩展字段,甚至可能包含其它的关联关系。
下面生成一个中间表模型:
php artisan make:model RoleUser --pivot
然后,给 belongsToMany() 指定 ->using() 方法。下面就是见证奇迹的时刻:
```
// in app/Models/User.php
public function roles()
{
return $this->belongsToMany(Role::class)
->using(RoleUser::class)
->withPivot(['team_id']);
}
// app/Models/RoleUser.php: 注意继承的是 Pivot, 不是 Model
use Illuminate\Database\Eloquent\Relations\Pivot;
class RoleUser extends Pivot
{
public function team()
{
return $this->belongsTo(Team::class);
}
}
// 在控制器里面就可以直接使用如下方式获取中间表 RoleUser 的 Team 信息:
$firstTeam = auth()->user()->roles()->first()->pivot->team->name;
```
## 多個資料庫獲取資料(會用到在看)
https://www.youtube.com/watch?v=KJAXLf78QPs
## 自帶get魔術方法
解釋為什麼能抓到他屬性
https://www.youtube.com/watch?v=zbA-zchIZbI
## 一張表兩個model用
https://www.youtube.com/watch?v=R5fMcpDGuGg

上面的好像會有問題
反正下面比較好
這種跟用repository
覆蓋newQuery 跟 create
## ORM
透過ORM操作
是一個active的設計模式
Laravel 的 Eloquent 会维护实例的两个数组,分别是 original 和 attributes。
https://learnku.com/articles/6657/model-events-and-observer-in-laravel
## 強制使用eager loading

這時候用到延遲加載
Illuminate\Database\LazyLoadingViolationException 會丟出這個例外
## 使用trait
model只要用
trait就會跑
boot + trait名稱的function
原因在這
https://github.com/tkeer/how-laravel-soft-deletes
記得在這bootfunction內
就是全域了
所以不用再覆寫boot方法
然後paren::boot()了
## mutator and Casting(轉換跟顯示)()

getAttribute 這個相對來說比較靈活一點 可以理解為他就是你這張表的一個欄位
所以像是repository get出來的時候是collection 然後你collection的pluck也可以抓得到這個model的欄位
增加欄位的用getAttribute 因為 getAttribute如果用自己本身欄位的會全域影響 所以要對自己欄位轉換用present
present 是资料显示不同资料
因為present每個new的都不一樣
### mutator
https://www.youtube.com/watch?v=rie3Ot7C1Ek
都是get or set開頭 attribute都是結尾
#### get

必定要get開頭 雖然casts也會有 但不會用到的感覺
你可以追看看他會顯示
他是負責轉換大小寫那樣
#### set
改便他的值
例如都 * 100這樣
### 資料型態轉換用 casts
https://laracasts.com/series/whats-new-in-laravel-7/episodes/3
ex boolean
在資料庫應該要true false
### 自定義casts
可以直接建立一個 extent的就照官網的範例
你可你點進來看
裡面有set 跟 get
用來表示存進去 跟取出來
然後再casts註冊
當然你也可以不寫在casts專門class裡面
一開始先經過model _get方法
在網內你看到你有->casts或->attributs

在網內

前面的transform是排序

先訪問器 getAttribute那種

再來casts
再來屬性
**用處**
很多model用到相同casts就可以寫這樣
**注意**
就算你有關連 你可能會被這個搶掉
因為他是先轉換器先的
小心用
## get set 8.77進階版本

## api Appends 添加字段
https://www.youtube.com/watch?v=FNU3gYgiEgQ
如果你今天create時間想要顯示不一樣
但create還要留著
但又不必要開欄位
因為只是多一個欄位 是轉換的
可以用get轉換器
加上 append
$proteced $append = [];

但這樣不太好 全域的
所以最好是get轉換
加上你要顯示的那個collection最後加上append

## 必看
has whereHas
https://www.youtube.com/watch?v=sqQE4TgitSU
關聯多的
不要加s
{{ $poll->votes()->count() }}
要這樣
{{ $poll->votes->count() }}
抓那個屬性 不是查詢的
基本觀念
https://blog.quickadminpanel.com/eloquent-relationships-the-ultimate-guide/
一對多還是...
只要對上的是多的
https://laraveldaily.com/did-you-know-five-additional-filters-in-belongsto-or-hasmany/
https://github.com/LaravelDaily/laravel-tips
基本多對多到高級
https://www.youtube.com/watch?v=V5xINbA-z9o
分層
repository裡面的用fiter設計,但不一定要
可以直接this->model->create之類的 去看model文黨
this->model 最好用繼承不會麻煩
然後
再把
hasOne
關係
filtter
變數宣告之類的分開
hasOne之類的用trait引入
這想法來自
Laravel jet stream(laravel 8 的auth)
(trait原因 有很多funtion 但 helper只能一個一個註冊 不如用class全包起來 屬於誰這樣)
https://www.youtube.com/watch?v=q6u_4-q0ArI
## 強制改變屬性 不經過fillable
實際應用在uuid配合觀察者
可以看最下面uuid的介紹
```
// 修改後的密碼、重新生成 remember_token
$user->forceFill([
'password' => bcrypt($password),
'remember_token' => Str::random(60),
])->save();
```
## morphMap
## 外key的名稱
規定依照駝峰
但可在第二參數自訂義
所以a hasMany b (如果再belonTo的外key叫a_id 那這邊第二參數要叫a_id)
b belongTO
### 預設
會以外function 的小駝峰變成 snake命名方式 _去分割 預設是id
ex
blogPost 變成 blog_post_id 這樣
ex
```
public function blogPost()
{
return $this->belongto('App\blogPost','blog_post_id')
}
```
### 自定義多態類型
默認情況下,Laravel將使用完全限定的類名稱來存儲相關模型的類型。例如,給出上面的一對多示例,其中Comment可能屬於Post或Video,則默認commentable_type分別為App\Models\Post或App\Models\Video。但是,您可能希望將資料庫與應用程式的內部結構脫鉤。在這種情況下,您可以定義"morph map"來指示Eloquent為每個模型使用自定義名稱而不是類名稱:
```
use Illuminate\Database\Eloquent\Relations\Relation;
Relation::morphMap([
'posts' => 'App\Models\Post',
'videos' => 'App\Models\Video',
]);
```
## relation 計算數量
member->good->count()
vs
member->good()->count()
用第二種
第一種是會抓去所有關聯
調用的是collecion的count
但第二種
是利用關係的 調用裡面的count()涵式
## bolonTo 的 withDefault
https://learnku.com/articles/5148/withdefault-method-of-belongsto-association
兩個可以共用一個主題
belongTo主題
```
/**
* 主題..
*/
public function category(): BelongsTo
{
return $this->belongsTo(config('morph-map.customer_service_category'))
->withDefault([
'type' => self::TYPE_MEMBER,
'name' => '未分類',
]);
}
```
## model collection
https://laravel.com/docs/8.x/eloquent-collections
## with load loadMissing
急切加載
通過使用with()您可以在**查詢父模型**時“急切加載”關係:
`$book = Book::with('author')->find($id);`
延遲加載
要在檢索到父模型後預先加載關係:
`$book->load('author');`
這也可以用於僅急切加載丟失的內容
`$book->loadMissing('author');`
與load()方法相反,loadMissing()方法過濾給定的關係,並且只有在尚未加載時才懶惰地“急切”加載它們
load會加載,但loadMissing會看他有沒有加載過,結論loadMissing>load
技術長也這樣用
## 查詢大量資料 lazy Collection
https://iter01.com/574559.html
https://www.oulub.com/zh-TW/Laravel/collections-lazy-collections
但好像要千萬級別,當做增加知識就好
## 原生文黨中間的save
可以看到update是 fill 在save
所以save裡面的option要搞清楚
可以看這篇
https://stackoverflow.com/questions/32891883/what-are-the-available-options-for-eloquents-modelsave-method
update比save好
https://medium.com/@lynnlin827/laravel-eloquent-%E4%BA%8B%E4%BB%B6%E4%B8%AD%E7%9A%84-updated-%E5%92%8C-saved-%E5%8E%9F%E4%BE%86%E4%B8%8D%E4%B8%80%E6%A8%A3-caa8ef0ddbc
## Eloquent where 日期方法
雄辯,請與功能的日期whereDay(),whereMonth(),
whereYear(),whereDate()和whereTime()
```
$products = Product::whereDate('created_at', '2018-01-31')->get();
$products = Product::whereMonth('created_at', '12')->get();
$products = Product::whereDay('created_at', '31')->get();
$products = Product::whereYear('created_at', date('Y'))->get();
$products = Product::whereTime('created_at', '=', '14:13:58')->get();
```
## All() find
在調用 Eloquent 的 時Model::all(),您可以指定要返回的列。
find也可以
`$ users = User :: all ([ 'id' , 'name' , 'email' ]);
$ users = User :: find ([ 1 , 2 , 3 ]);
`
## 更改 Created_at 和 Updated_at 的格式
要更改格式,created_at您可以在模型中添加一個方法,如下所示:
```
public function getCreatedAtFormattedAttribute()
{
return $this->created_at->format('H:i d, M Y');
}
```
所以你可以$entry->created_at_formatted在需要的時候使用它。它將返回這樣的created_at屬性:04:19 23, Aug 2020
## 將數組類型存儲到 JSON 中
如果您有接受數組的輸入字段,並且必須將其存儲為 JSON,則可以$casts在模型中使用屬性。這images是一個 JSON 屬性。
```
protected $casts = [
'images' => 'array',
];
```
因此,您可以將其存儲為 JSON,但是當從數據庫中檢索時,它可以用作數組。
## 減少內存
https://www.infyom.com/blog/tobase-function-in-laravel-eloquent
有時我們需要將大量數據加載到內存中。例如:
`$orders = Order::all();`
但是如果我們有非常大的數據,這可能會很慢,因為 Laravel 準備了 Model 類的對象。在這種情況下,Laravel 有一個方便的功能toBase()
## 親子的3層結構計算數量
你有一個 3 層的親子結構,比如一個電子商店的分類,並且你想在第三級顯示產品的數量,你可以使用with('yyy.yyy')然後添加withCount()作為條件
```
class HomeController extend Controller
{
public function index()
{
$categories = Category::query()
->whereNull('category_id')
->with(['subcategories.subcategories' => function($query) {
$query->withCount('products');
}])->get();
}
}
```
```
class Category extends Model
{
public function subcategories()
{
return $this->hasMany(Category::class);
}
public function products()
{
return $this->hasMany(Product::class);
}
}
```
```
<ul>
@foreach($categories as $category)
<li>
{{ $category->name }}
@if ($category->subcategories)
<ul>
@foreach($category->subcategories as $subcategory)
<li>
{{ $subcategory->name }}
@if ($subcategory->subcategories)
<ul>
@foreach ($subcategory->subcategories as $subcategory)
<li>{{ $subcategory->name }} ({{ $subcategory->product_count }})</li>
@endforeach
</ul>
@endif
</li>
@endforeach
</ul>
@endif
</li>
@endforeach
</ul>
```
## whereIn取代方法
但個人覺得
多重Where的話還是用whereIn
find最好當結尾
之前踩過雷
`return Product::whereIn('id', $this->productIDs)->get();`
`return Product::find($this->productIDs)`
whereIn 是吃 array
## 查詢丟出404
```
$model = Flight::where('legs', '>', 3)->firstOr(function () {
// ...
})
```
## findOrFail 跟 optional()
```
$product = Product::findOrFail($id); // shows 404 if not found
$product->update($productDataArray);
```
可簡化成
`optional(Product::find($id))->update($productDataArray);`
## belongTo 默認
belongsTo關係中分配一個默認模型,以避免在調用它時出現致命錯誤,就像{{ $post->user->name }}$post->user 不存在一樣
```
public function user()
{
return $this->belongsTo('App\User')->withDefault();
}
```
## with用法
初級
`$users = App\Book::with('author:id,name')->get();`
進階
`$users = App\Book::with('author:id,name')->get();`
## 不要使用belongsTo,使用hasMany
可參考 盡量從父層開始
belongsTo關係,在創建子記錄時不要傳遞父母的ID,而是使用hasMany關係來製作更短的句子
```
// if Post -> belongsTo(User), and User -> hasMany(Post)...
// Then instead of passing user_id...
Post::create([
'user_id' => auth()->id(),
'title' => request()->input('title'),
'post_text' => request()->input('post_text'),
]);
// Do this
auth()->user()->posts()->create([
'title' => request()->input('title'),
'post_text' => request()->input('post_text'),
]);
```
## 檢查關係方法是否存在
可以用php用法
`method_exists($object, $methodName)`
```
$user = User::first();
if (method_exists($user, 'roles')) {
// Do something with $user->roles()->...
}
```
## 關聯表 多對多的
**前提是你的關聯表有要做別的事情,不然多此一舉**
跑這個
php artisan make:model RoleUser --pivot
在belongsToMany()with->using()方法中指定它。然後你就可以施展魔法了,就像例子中那樣
```
// in app/Models/User.php
public function roles()
{
return $this->belongsToMany(Role::class)
->using(RoleUser::class)
->withPivot(['team_id']);
}
// app/Models/RoleUser.php: notice extends Pivot, not Model
use Illuminate\Database\Eloquent\Relations\Pivot;
class RoleUser extends Pivot
{
public function team()
{
return $this->belongsTo(Team::class);
}
}
// Then, in Controller, you can do:
$firstTeam = auth()->user()->roles()->first()->pivot->team->name;
```
## 按首字母分組
```
$ users = User :: all ()-> groupBy ( function ( $ item ) {
return $ item -> name [ 0 ];
});
```
## 驗證 Model 是否被儲存
isDirty、isClean
```
$user = User::create([
'first_name' => 'Taylor',
'last_name' => 'Otwell',
'title' => 'Developer',
]);
$user->title = 'Painter';
$user->isDirty(); // true
$user->isDirty('title'); // true
$user->isDirty('first_name'); // false
$user->isClean(); // false
$user->isClean('title'); // false
$user->isClean('first_name'); // true
$user->save();
$user->isDirty(); // false
$user->isClean(); // true
```
## 一對一 一對多 多對多
## attach可接受集合 所以應該是看model是一對多等型態

## 注意事項
第一 laravel 6 . 7的id默認都是biginterger
在原本表單改成increments或連接的外key用big連接
第二 刪除外key
刪除一個外鍵,可以使用dropForeign方法
第三 重點非常重要
onUpdate 則是主鍵表中被參考字段的值更新
onDelete 是指在主鍵表中刪除一條記錄
on update 和 on delete 后面可以跟的詞語有四個
no action , set null , set default ,cascade
no action 表示 不做任何操作,
set null 表示在外鍵表中將相應字段設置為null
set default 表示設置為默認值
cascade 表示級聯操作(一般都用這個)
就是說,如果主鍵表中被參考字段更新,外鍵表中也更新,主鍵表中的記錄被刪除,外鍵表中改行也相應刪除
多數人都只寫delete 這必加 不然你主表crud的地方會掛掉 update沒加我沒掛掉
*** 一些基本要注意的
$blog->comments 會跑出all 跟has不一樣 BlogPost::has 是找全部關聯 這是被聯的
$blog->comments() 看他是甚麼關聯 return
## 一對一
https://www.latech.tw/2017/02/laravel-migrationmodeldb.html
基本互存
hasOne $author->profile()->save($profile);
belognto $profile->author()->associate($author)->save();
## 一對多
```
class Post extends Model
{
/**
* Get the comments for the blog post.
*/
public function comments()
{
return $this->hasMany('App\Comment');
}
}
```
- 原廠設定
記住,Eloquent將自動確定Comment模型上正確的外鍵列。按照慣例,Eloquent將採用擁有模型的“蛇皮套”名稱,並在其後綴_id。因此,對於此示例,Eloquent將假定Comment模型上的外鍵為post_id。
## 一對多(逆向)
- 原廠設定
post_id將Comment模型中的匹配到模型id上的Post。Eloquent通過檢查關係方法的名稱並在方法名稱後加上_主鍵列的名稱作為後綴,從而確定默認的外鍵名稱。但是
## 多對多 注意
關聯表 -- 兩個表相加 重點重點****兩個表相加不用s
ex BlogPost tag
關聯表名字 Blog_post_tag
`大地雷小心`
這邊的where('id',$id);
不能用find();
因為要對上query builder
我猜是要看find的那個句子

## 多對多 新增移除
新增 attach
`$user->roles()->attach($roleId);`
```
$user->roles()->attach($roleId1->id,$roleId2->id);
這句記得它們user id一樣 只存的那邊 role的id不一樣
```
移除 detach
```
// 從使用者上移除單一身份...
$user->roles()->detach($roleId);
// 從使用者上移除所有身份...
$user->roles()->detach();
```
sync雖然是只增加要得 其他的移除
但他有第二個參數
**可以只加不移除**
`sync($a,false)`
## 多對多 參數
除了自定義聯接表的名稱之外,還可以通過將其他參數傳遞給belongsToMany方法來自定義表上鍵的列名。第三個參數是您要在其上定義關係的模型的外鍵名稱,而第四個參數是您要加入的模型的外鍵名稱:
```
return $this-
>belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
```
第一個關聯的 第二表名 第三自己名字 第四 外key
### 關聯
- withPivot
默認情況下,只有模型關鍵點會出現在對pivot像上。如果數據透視表包含額外的屬性,則在定義關係時必須指定它們:
`return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');`
- wherePivot,wherePivotIn,wherePivotNotIn
通過中間表列過濾關係
```
return $this->belongsToMany('App\Role')->wherePivot('approved', 1);
return $this->belongsToMany('App\Role')->wherePivotIn('priority', [1, 2]);
return $this->belongsToMany('App\Role')->wherePivotNotIn('priority', [1, 2]);
```
## 自定義中間表模型
```
class Role extends Model
{
/**
* The users that belong to the role.
*/
public function users()
{
return $this->belongsToMany('App\User')->using('App\RoleUser');
}
}
```
如果您定義了使用自定義樞紐模型的多對多關係,並且該樞紐模型具有自動遞增的主鍵,則應確保自定義樞紐模型類定義了一個incrementing設置為的屬性true。
`public $incrementing = true;`
## a->b->c 直接a->c 命名 中間先在連過去的 ex useCar
```
class Mechanic extends Model
{
/**
* Get the car's owner.
*/
public function carOwner()
{
return $this->hasOneThrough('App\Owner', 'App\Car');
}
}
```
傳遞給該hasOneThrough方法的第一個參數是我們希望訪問的最終模型的名稱,而第二個參數是中間模型的名稱。
自訂的話
如果您想自定義關係的鍵,則可以將它們作為方法的第三個和第四個參數傳遞hasOneThrough。第三個參數是中間模型上外鍵的名稱。第四個參數是最終模型上外鍵的名稱。第五個參數是本地鍵,而第六個參數是中間模型的本地鍵:
```
return $this->hasOneThrough(
'App\Owner',
'App\Car',
'mechanic_id', // Foreign key on cars table...
'car_id', // Foreign key on owners table...
'id', // Local key on mechanics table...
'id' // Local key on cars table...
);
```
## 多态关联
https://www.kancloud.cn/curder/laravel/408493
多态关联允许一个模型在单个关联下属于多个不同父模型。常见的多态关联就是评论,评论内容可能是属于文章或视频。
## 檢查是否有任何字段被更改
可以搭配觀察者
https://www.youtube.com/watch?v=_xluet13xxE

## model 查詢方法
### 關於Query builder ORM
在Laravel中有兩種操作DB的方法,
DB Query builder
Eloquent ORM
先來淺談一下兩者
| |DB Query builder | Eloquent ORM |
| -------- | -------- | -------- |
| 使用方式 | DB::table()…語法 | 需建立與維護Model |
| 回傳型態 | array | Collection |
| 方便程度 | 普通 | 很方便 |
| 彈性 | 很彈性 | 普通 |
| 維護 | 若沒有寫class,就需要到處維護 | 只需維護Model |
| 易用程度 | 普通 | 較易用 |
以上是我兩者使用過後的小心得,不一定是都是對的,
因為遇到的情況有些差異,所以有一些不一樣的感受,
但兩者都會自己轉為sql語法進行操作,
看完這個簡單的差異之後,讓我們來看看各自的用法吧!
### 建立關聯
User::find(1)->roles()->save($role);
上面的例子裡,新的 Role 模型物件被儲存,
同時附加關聯到 user 模型。也可以傳入屬性陣列,
把資料加到關聯資料表:
```
hasOne $profile->author()->associate($author)->save();
belognto 原本是 $author->profile()->save($profile);
```
當然你可以直接賦值去
### 查詢關聯
不用with的方法
可以直接調用 ex $profile->author
另外沒有關聯前 不會顯示出來 ex
```
$profile = Profile::find(1); 不會跑出來關聯
$profile->author();
$profile;
```
這時才回跑出來 因為有呼叫了
### with用法
```
$author = Author::with('Profile')->whereKey(1)->first();
一次with多個
$author = Author::with(['Profile','comment'])->whereKey(1)->first();
```
`::find() === whereKey(1)->first();` 原本寫法
### 查詢有沒有關聯 關聯用has where查自己屬性
### where 特別用法 Book::where("title",'like','%xxxx%')->get()
<!-- 查詢自己的屬性 -->
### 查詢關聯的有沒有這個屬性的 裡面有沒有符合 這是查詢沒有的
```
BlogPost::doesntHave('comments')->get();
BlogPost::has('comments')->get();
```
### 關聯的有沒有這個屬性的 裡面有沒有符合 這是查尋有的
`BlogPost::whereDoesntHave('comments',function($query){$query->where('content','like','%a%');})->get();`
### Book::sum('price')
計算總價
### Book::avg('price')
平均
https://www.youtube.com/watch?v=oQHEddn6ItI
### 關聯要注意的事情 Eager Loading lazy loaded 所謂的n+1問題
官網
https://laravel.com/docs/7.x/eloquent-relationships#constraining-eager-loads
#### 如果要查詢裡面的裡面 ex 本書的所有作者和所有作者的個人聯繫人
用.去連接 ex
`$books = App\Book::with('author.contacts')->get();`

預設是lazy loaded
所以盡量用 With去關聯
### 關於updateOrCreate firstOrCreate 差別
firstOrCreate第一個參數是判斷 第二是要加入的

updateOrCreate第一個參數是判斷 第二是加入的 但是但是create是兩個參數合併
像這張圖是加username eamil password

## softDelete 軟刪除
**表有更動都要composer dump-autoload**
### 基本寫法子從關係刪除
外key請加上 `onDelete('cascade')`
然後`另外建立`migrate
```
記住有() 跟 timestamps一樣
up寫 $table->softDeletes();
down寫 $table->dropSoftDeletes()
```
最基礎寫法
### even寫法
施工
#### 復原連同子關係都復原

## model查詢的複製
https://www.youtube.com/watch?v=nM5SRNAd78Y
## 日期轉換器
預設情況下,Eloquent 將會把 created_at 和 updated_at 欄位轉換成 Carbon 的實例,它提供了各式各樣有用的方法,並繼承了 PHP 原生的 DateTime 類別。
你可以在你的模型中自訂哪些欄位要自動地被修改,或甚至完全禁止修改,只要藉由覆寫模型的 $dates 屬性:
`protected $dates = ['created_at', 'updated_at', 'deleted_at'];`
但最好寫在Casting會比較好
## uuid
https://stackoverflow.com/questions/37948764/laravel-uuid-generation/54301345
之後可以先嘗試 stackoverflow的 第一個解答
不行再用公司的解答
```
<?php
namespace Dolfan\Traits;
use Illuminate\Support\Str;
trait Uuidable
{
/**
* Indicates if the UUIDs are auto-generating.
*
* @var bool
*/
public $generating = true;
/**
* The uuid key for the model.
*
* @var string
*/
protected $uuidKey = 'uuid';
/**
* Get the value indicating whether the UUIDs are generating.
*
* @return bool
*/
public function getGenerating()
{
return $this->generating;
}
/**
* Get the uuid key for the model.
*
* @return string
*/
public function getUuidKeyName()
{
return $this->uuidKey;
}
public function firstOrFailByUUID(string $uuid)
{
return $this->where($this->getUuidKeyName(), $uuid)->firstOrFail();
}
public function findByUUID(string $uuid)
{
return $this->where($this->getUuidKeyName(), $uuid)->first();
}
/**
* Boot function from Laravel.
*/
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
if ($model->getGenerating()) {
if (empty($model->{$model->getUuidKeyName()})) {
$model->{$model->getUuidKeyName()} = Str::uuid()->toString();
}
}
});
}
}
```
另外一種寫法
用觀察者
```
<?php
namespace App\Observers;
use Illuminate\Support\Str;
use TWJOIN\AdminPanel\Models\AdminUser;
class AdminUserObserver
{
/**
* Listen to the Media creating event.
*/
public function creating(AdminUser $user): void
{
$user->forceFill(['uuid' => Str::uuid()]);
}
}
```
## triat
初始化 跟 自動run
https://medium.com/swlh/laravel-booting-and-initializing-models-with-traits-2f77059b1915
###### tags: `Laravel`