<article><h1>Eloquent: 入門</h1><ul><li><a href="#introduction">簡介</a></li><li><a href="#defining-models">定義模型</a><ul><li><a href="#eloquent-model-conventions">Eloquent 模型約定</a></li></ul></li><li><a href="#retrieving-models">取回多個模型</a><ul><li><a href="#collections">集合</a></li><li><a href="#chunking-results">分塊結果</a></li></ul></li><li><a href="#retrieving-single-models">取回單個模型或集合</a><ul><li><a href="#retrieving-aggregates">取回集合</a></li></ul></li><li><a href="#inserting-and-updating-models">添加和更新模型</a><ul><li><a href="#inserts">基本添加</a></li><li><a href="#updates">基本更新</a></li><li><a href="#mass-assignment">批量賦值</a></li><li><a href="#other-creation-methods">其他創建方法</a></li></ul></li><li><a href="#deleting-models">刪除模型</a><ul><li><a href="#soft-deleting">軟刪除</a></li><li><a href="#querying-soft-deleted-models">查詢被軟刪除的模型</a></li></ul></li><li><a href="#query-scopes">查詢作用域</a><ul><li><a href="#global-scopes">全局作用域</a></li><li><a href="#local-scopes">本地作用域</a></li></ul></li><li><a href="#events">事件</a><ul><li><a href="#observers">觀察器</a></li></ul></li></ul><p><a name="introduction"></a></p><h2><a href="#introduction">簡介</a></h2><p>Laravel 的 Eloquent ORM 提供了漂亮、簡潔的 ActiveRecord 實現來和數據庫進行交互。每個數據庫表都有一個對應的「模型」可用來跟數據表進行交互。你可以通過模型查詢數據表內的數據,以及將記錄添加到數據表中。</p><p>在開始之前,請確認你已在 <code class=" language-php">config<span class="token operator">/</span>database<span class="token punctuation">.</span>php</code> 文件中設置好了數據庫連接。更多數據庫的設置信息請查看 <a href="/docs/5.4/database#configuration">數據庫設置</a> 文檔。</p><p><a name="defining-models"></a></p><h2><a href="#defining-models">定義模型</a></h2><p>開始之前,讓我們先來創建一個 Eloquent 模型。模型通常放在 <code class=" language-php">app</code> 目錄中,不過你可以將他們隨意放在任何可通過 <code class=" language-php">composer<span class="token punctuation">.</span>json</code> 自動加載的地方。所有的 Eloquent 模型都繼承自 <code class=" language-php">Illuminate\<span class="token package">Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span></code> 類。</p><p>創建模型實例的最簡單方法是使用 <code class=" language-php">make<span class="token punctuation">:</span>model</code> <a href="/docs/5.4/artisan">Artisan 命令</a>:</p><pre class=" language-php"><code class=" language-php">php artisan make<span class="token punctuation">:</span>model User</code></pre><p>當你生成一個模型時想要順便生成一個 <a href="/docs/5.4/migrations">數據庫遷移</a>,可以使用 <code class=" language-php"><span class="token operator">--</span>migration</code> 或 <code class=" language-php"><span class="token operator">-</span>m</code> 選項:</p><pre class=" language-php"><code class=" language-php">php artisan make<span class="token punctuation">:</span>model User <span class="token operator">--</span>migration
php artisan make<span class="token punctuation">:</span>model User <span class="token operator">-</span>m</code></pre><p><a name="eloquent-model-conventions"></a></p><h3>Eloquent 模型約定</h3><p>現在,讓我們來看一個 <code class=" language-php">Flight</code> 模型類的例子,我們將會用它從 <code class=" language-php">flights</code> 數據表中取回與保存信息:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true"> //
</span><span class="token punctuation">}</span></code></pre><h4>數據表名稱</h4><p>請注意,我們并沒有告訴 Eloquent <code class=" language-php">Flight</code> 模型該使用哪一個數據表。除非數據表明確地指定了其它名稱,否則將使用類的「蛇形名稱」、復數形式名稱來作為數據表的名稱。因此在此例子中,Eloquent 將會假設 <code class=" language-php">Flight</code> 模型被存儲記錄在 <code class=" language-php">flights</code> 數據表中。你可以在模型上定義一個 <code class=" language-php">table</code> 屬性,用來指定自定義的數據表名稱:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 與模型關聯的數據表
*
* @var string
*/</span>
<span class="token keyword">protected</span> <span class="token variable">$table</span> <span class="token operator">=</span> <span class="token string">'my_flights'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre><h4>主鍵</h4><p>Eloquent 也會假設每個數據表都有一個叫做 <code class=" language-php">id</code> 的主鍵字段。你也可以定義一個 <code class=" language-php"><span class="token variable">$primaryKey</span></code> 屬性來重寫這個約定。</p><p>此外,Eloquent 假定主鍵是一個遞增的整數值,這意味著在默認情況下主鍵將自動的被強制轉換為 <code class=" language-php">int</code>。 如果你想使用非遞增或者非數字的主鍵,你必須在你的模型 public <code class=" language-php"><span class="token variable">$incrementing</span></code> 屬性設置為<code class=" language-php"><span class="token boolean">false</span></code>。</p><h4>時間戳</h4><p>默認情況下,Eloquent 會認為在你的數據庫表有 <code class=" language-php">created_at</code> 和 <code class=" language-php">updated_at</code> 字段。如果你不希望讓 Eloquent 來自動維護這兩個字段,可在模型內將 <code class=" language-php"><span class="token variable">$timestamps</span></code> 屬性設置為 <code class=" language-php"><span class="token boolean">false</span></code>:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 該模型是否被自動維護時間戳
*
* @var bool
*/</span>
<span class="token keyword">public</span> <span class="token variable">$timestamps</span> <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre><p>如果你需要自定義自己的時間戳格式,可在模型內設置 <code class=" language-php"><span class="token variable">$dateFormat</span></code> 屬性。這個屬性決定了日期應如何在數據庫中存儲,以及當模型被序列化成數組或 JSON 格式:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 模型的日期字段保存格式。
*
* @var string
*/</span>
<span class="token keyword">protected</span> <span class="token variable">$dateFormat</span> <span class="token operator">=</span> <span class="token string">'U'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre><h4>數據庫連接</h4><p>默認情況下,所有的 Eloquent 模型會使用應用程序中默認的數據庫連接設置。如果你想為模型指定不同的連接,可以使用 <code class=" language-php"><span class="token variable">$connection</span></code> 屬性:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 此模型的連接名稱。
*
* @var string
*/</span>
<span class="token keyword">protected</span> <span class="token variable">$connection</span> <span class="token operator">=</span> <span class="token string">'connection-name'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre><p><a name="retrieving-models"></a></p><h2><a href="#retrieving-models">取回多個模型</a></h2><p>一旦你創建并 <a href="/docs/5.4/schema">關聯了一個模型到數據表</a> 上,那么你就可以從數據庫中獲取數據。可把每個 Eloquent 模型想像成強大的 <a href="/docs/5.4/queries">查詢構造器</a>,它讓你可以流暢地查詢與模型關聯的數據表。例如:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span>
<span class="token variable">$flights</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">all<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$flights</span> <span class="token keyword">as</span> <span class="token variable">$flight</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">echo</span> <span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">name</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre><h4>增加額外的限制</h4><p>Eloquent 的 <code class=" language-php">all</code> 方法會返回在模型數據表中的所有結果。由于每個 Eloquent 模型都可以當作一個 <a href="/docs/5.4/queries">查詢構造器</a>,所以你可以在查詢中增加規則,然后使用 <code class=" language-php">get</code> 方法來獲取結果:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$flights</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'active'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
<span class="token operator">-</span><span class="token operator">></span><span class="token function">orderBy<span class="token punctuation">(</span></span><span class="token string">'name'</span><span class="token punctuation">,</span> <span class="token string">'desc'</span><span class="token punctuation">)</span>
<span class="token operator">-</span><span class="token operator">></span><span class="token function">take<span class="token punctuation">(</span></span><span class="token number">10</span><span class="token punctuation">)</span>
<span class="token operator">-</span><span class="token operator">></span><span class="token function">get<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><blockquote class="has-icon tip"><p><div class="flag"><span class="svg"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" version="1.1" x="0px" y="0px" width="56.6px" height="87.5px" viewBox="0 0 56.6 87.5" enable-background="new 0 0 56.6 87.5" xml:space="preserve"><path fill="#FFFFFF" d="M28.7 64.5c-1.4 0-2.5-1.1-2.5-2.5v-5.7 -5V41c0-1.4 1.1-2.5 2.5-2.5s2.5 1.1 2.5 2.5v10.1 5 5.8C31.2 63.4 30.1 64.5 28.7 64.5zM26.4 0.1C11.9 1 0.3 13.1 0 27.7c-0.1 7.9 3 15.2 8.2 20.4 0.5 0.5 0.8 1 1 1.7l3.1 13.1c0.3 1.1 1.3 1.9 2.4 1.9 0.3 0 0.7-0.1 1.1-0.2 1.1-0.5 1.6-1.8 1.4-3l-2-8.4 -0.4-1.8c-0.7-2.9-2-5.7-4-8 -1-1.2-2-2.5-2.7-3.9C5.8 35.3 4.7 30.3 5.4 25 6.7 14.5 15.2 6.3 25.6 5.1c13.9-1.5 25.8 9.4 25.8 23 0 4.1-1.1 7.9-2.9 11.2 -0.8 1.4-1.7 2.7-2.7 3.9 -2 2.3-3.3 5-4 8L41.4 53l-2 8.4c-0.3 1.2 0.3 2.5 1.4 3 0.3 0.2 0.7 0.2 1.1 0.2 1.1 0 2.2-0.8 2.4-1.9l3.1-13.1c0.2-0.6 0.5-1.2 1-1.7 5-5.1 8.2-12.1 8.2-19.8C56.4 12 42.8-1 26.4 0.1zM43.7 69.6c0 0.5-0.1 0.9-0.3 1.3 -0.4 0.8-0.7 1.6-0.9 2.5 -0.7 3-2 8.6-2 8.6 -1.3 3.2-4.4 5.5-7.9 5.5h-4.1H28h-0.5 -3.6c-3.5 0-6.7-2.4-7.9-5.7l-0.1-0.4 -1.8-7.8c-0.4-1.1-0.8-2.1-1.2-3.1 -0.1-0.3-0.2-0.5-0.2-0.9 0.1-1.3 1.3-2.1 2.6-2.1H41C42.4 67.5 43.6 68.2 43.7 69.6zM37.7 72.5H26.9c-4.2 0-7.2 3.9-6.3 7.9 0.6 1.3 1.8 2.1 3.2 2.1h4.1 0.5 0.5 3.6c1.4 0 2.7-0.8 3.2-2.1L37.7 72.5z"></path></svg></span></div> 由于 Eloquent 模型是查詢構造器,因此你應當去閱讀所有 <a href="/docs/5.4/queries">查詢構造器</a> 中可用的方法。你可在 Eloquent 查詢中使用這其中的任何方法。</p></blockquote><p><a name="collections"></a></p><h3>集合</h3><p>類似 <code class=" language-php">all</code> 以及 <code class=" language-php">get</code> 之類的可以取回多個結果的 Eloquent 方法,將會返回一個 <code class=" language-php">Illuminate\<span class="token package">Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Collection</span></code> 實例。<code class=" language-php">Collection</code> 類提供 <a href="/docs/5.4/eloquent-collections#available-methods">多種輔助函數</a> 來處理你的 Eloquent 結果。</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$flights</span> <span class="token operator">=</span> <span class="token variable">$flights</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">reject<span class="token punctuation">(</span></span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$flight</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">cancelled</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p>當然,你也可以簡單地像數組一樣來遍歷集合:</p><pre class=" language-php"><code class=" language-php"><span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$flights</span> <span class="token keyword">as</span> <span class="token variable">$flight</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">echo</span> <span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">name</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre><p><a name="chunking-results"></a></p><h3>分塊結果</h3><p>如果你需要處理數以千計的 Eloquent 查找結果,則可以使用 <code class=" language-php">chunk</code> 命令。<code class=" language-php">chunk</code> 方法將會獲取一個 Eloquent 模型的「分塊」,并將它們送到指定的 <code class=" language-php">閉包 <span class="token punctuation">(</span>Closure<span class="token punctuation">)</span></code> 中進行處理。當你在處理大量結果時,使用 <code class=" language-php">chunk</code> 方法可節省內存:</p><pre class=" language-php"><code class=" language-php"><span class="token scope">Flight<span class="token punctuation">::</span></span><span class="token function">chunk<span class="token punctuation">(</span></span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$flights</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$flights</span> <span class="token keyword">as</span> <span class="token variable">$flight</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment" spellcheck="true"> //
</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p>傳遞到方法的第一個參數表示每次「分塊」時你希望接收的數據數量。閉包則作為第二個參數傳遞,它將會在每次從數據取出分塊時被調用。</p><h4>使用游標</h4><p><code class=" language-php">cursor</code> 允許你使用游標來遍歷數據庫數據,一次只執行單個查詢。在處理大數據量請求時 <code class=" language-php">cursor</code> 方法可以大幅度減少內存的使用:</p><pre class=" language-php"><code class=" language-php"><span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token scope">Flight<span class="token punctuation">::</span></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'foo'</span><span class="token punctuation">,</span> <span class="token string">'bar'</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">cursor<span class="token punctuation">(</span></span><span class="token punctuation">)</span> <span class="token keyword">as</span> <span class="token variable">$flight</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment" spellcheck="true"> //
</span><span class="token punctuation">}</span></code></pre><p><a name="retrieving-single-models"></a></p><h2><a href="#retrieving-single-models">取回單個模型/集合</a></h2><p>當然,除了從指定的數據表取回所有記錄,你也可以通過 <code class=" language-php">find</code> 和 <code class=" language-php">first</code> 方法來取回單條記錄。但這些方法返回的是單個模型的實例,而不是返回模型的集合:</p><pre class=" language-php"><code class=" language-php"><span class="token comment" spellcheck="true">// 通過主鍵取回一個模型...
</span><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">find<span class="token punctuation">(</span></span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">
// 取回符合查詢限制的第一個模型 ...
</span><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'active'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">first<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p>你也可以用主鍵的集合為參數調用<code class=" language-php">find</code>方法,它將返回符合條件的集合:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$flights</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">find<span class="token punctuation">(</span></span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><h4>「未找到」異常</h4><p>有時候你可能希望在找不到模型時拋出一個異常,這在路由或是控制器內特別有用。<code class=" language-php">findOrFail</code> 以及 <code class=" language-php">firstOrFail</code> 方法會取回查詢的第一個結果。如果沒有找到相應結果,則會拋出一個 <code class=" language-php">Illuminate\<span class="token package">Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>ModelNotFoundException</span></code>:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$model</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">findOrFail<span class="token punctuation">(</span></span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token variable">$model</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'legs'</span><span class="token punctuation">,</span> <span class="token string">'>'</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">firstOrFail<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p>如果該異常沒有被捕獲,則會自動返回 HTTP <code class=" language-php"><span class="token number">404</span></code> 響應給用戶,因此當使用這些方法時,你沒有必要明確的編寫檢查來返回 <code class=" language-php"><span class="token number">404</span></code> 響應:</p><pre class=" language-php"><code class=" language-php"><span class="token scope">Route<span class="token punctuation">::</span></span><span class="token function">get<span class="token punctuation">(</span></span><span class="token string">'/api/flights/{id}'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$id</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">findOrFail<span class="token punctuation">(</span></span><span class="token variable">$id</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p><a name="retrieving-aggregates"></a></p><h3>取回集合</h3><p>當然,你也可以使用 <code class=" language-php">count</code>、<code class=" language-php">sum</code>、<code class=" language-php">max</code>,和其它 <a href="/docs/5.4/queries">查詢構造器</a> 提供的 <a href="/docs/5.4/queries#aggregates">聚合函數</a>。這些方法會返回適當的標量值,而不是一個完整的模型實例:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$count</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'active'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">count<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token variable">$max</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'active'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">max<span class="token punctuation">(</span></span><span class="token string">'price'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p><a name="inserting-and-updating-models"></a></p><h2><a href="#inserting-and-updating-models">添加和更新模型</a></h2><p><a name="inserts"></a></p><h3>基本添加</h3><p>要在數據庫中創建一條新記錄,只需創建一個新模型實例,并在模型上設置屬性和調用 <code class=" language-php">save</code> 方法即可:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Flight</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers<span class="token punctuation">\</span>Controller</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">FlightController</span> <span class="token keyword">extends</span> <span class="token class-name">Controller</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 創建一個新的航班實例。
*
* @param Request $request
* @return Response
*/</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">store<span class="token punctuation">(</span></span>Request <span class="token variable">$request</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true"> // 驗證請求...
</span>
<span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Flight</span><span class="token punctuation">;</span>
<span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">name</span> <span class="token operator">=</span> <span class="token variable">$request</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">name</span><span class="token punctuation">;</span>
<span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">save<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre><p>在這個例子中,我們把來自 HTTP 請求中的 <code class=" language-php">name</code> 參數簡單地指定給 <code class=" language-php">App\<span class="token package">Flight</span></code> 模型實例的 <code class=" language-php">name</code> 屬性。當我們調用 <code class=" language-php">save</code> 方法,就會添加一條記錄到數據庫中。當 <code class=" language-php">save</code> 方法被調用時,<code class=" language-php">created_at</code> 以及 <code class=" language-php">updated_at</code> 時間戳將會被自動設置,因此我們不需要去手動設置它們。</p><p><a name="updates"></a></p><h3>基本更新</h3><p><code class=" language-php">save</code> 方法也可以用于更新數據庫中已經存在的模型。要更新模型,則須先取回模型,再設置任何你希望更新的屬性,接著調用 <code class=" language-php">save</code> 方法。同樣的,<code class=" language-php">updated_at</code> 時間戳將會被自動更新,所以我們不需要手動設置它的值:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">find<span class="token punctuation">(</span></span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token property">name</span> <span class="token operator">=</span> <span class="token string">'New Flight Name'</span><span class="token punctuation">;</span>
<span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">save<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><h4>批量更新</h4><p>也可以針對符合指定查詢的任意數量模型進行更新。在這個例子中,所有 <code class=" language-php">active</code> 并且 <code class=" language-php">destination</code> 為 <code class=" language-php">San Diego</code> 的航班,都將會被標識為延遲:</p><pre class=" language-php"><code class=" language-php"><span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'active'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
<span class="token operator">-</span><span class="token operator">></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'destination'</span><span class="token punctuation">,</span> <span class="token string">'San Diego'</span><span class="token punctuation">)</span>
<span class="token operator">-</span><span class="token operator">></span><span class="token function">update<span class="token punctuation">(</span></span><span class="token punctuation">[</span><span class="token string">'delayed'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p><code class=" language-php">update</code> 方法會期望收到一個含有字段與值對應的數組,而這些字段的內容將會被更新。</p><blockquote class="has-icon note"><p><div class="flag"><span class="svg"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" version="1.1" x="0px" y="0px" width="90px" height="90px" viewBox="0 0 90 90" enable-background="new 0 0 90 90" xml:space="preserve"><path fill="#FFFFFF" d="M45 0C20.1 0 0 20.1 0 45s20.1 45 45 45 45-20.1 45-45S69.9 0 45 0zM45 74.5c-3.6 0-6.5-2.9-6.5-6.5s2.9-6.5 6.5-6.5 6.5 2.9 6.5 6.5S48.6 74.5 45 74.5zM52.1 23.9l-2.5 29.6c0 2.5-2.1 4.6-4.6 4.6 -2.5 0-4.6-2.1-4.6-4.6l-2.5-29.6c-0.1-0.4-0.1-0.7-0.1-1.1 0-4 3.2-7.2 7.2-7.2 4 0 7.2 3.2 7.2 7.2C52.2 23.1 52.2 23.5 52.1 23.9z"></path></svg></span></div> 當通過“Eloquent”批量更新時,<code class=" language-php">saved</code>和<code class=" language-php">updated</code>模型事件將不會被更新后的模型代替。這是因為批量更新時,模型從來沒有被取回。</p></blockquote><p><a name="mass-assignment"></a></p><h3>批量賦值</h3><p>你也可以使用 <code class=" language-php">create</code> 方法通過一行代碼來保存一個新模型。被插入數據庫的模型實例將會返回給你。不過,在這樣做之前,你需要先在你的模型上定義一個 <code class=" language-php">fillable</code> 或 <code class=" language-php">guarded</code> 屬性,因為所有的 Eloquent 模型都針對批量賦值(Mass-Assignment)做了保護。</p><p>當用戶通過 HTTP 請求傳入了非預期的參數,并借助這些參數更改了數據庫中你并不打算要更改的字段,這時就會出現批量賦值(Mass-Assignment)漏洞。例如,惡意用戶可能會通過 HTTP 請求發送 <code class=" language-php">is_admin</code> 參數,然后對應到你模型的 <code class=" language-php">create</code> 方法,此操作能讓該用戶把自己升級為一個管理者。</p><p>所以,在開始之前,你應該定義好哪些模型屬性是可以被批量賦值的。你可以在模型上使用 <code class=" language-php"><span class="token variable">$fillable</span></code> 屬性來實現。例如,讓我們讓 <code class=" language-php">Flight</code> 模型的 <code class=" language-php">name</code> 屬性可以被批量賦值:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 可以被批量賦值的屬性。
*
* @var array
*/</span>
<span class="token keyword">protected</span> <span class="token variable">$fillable</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre><p>一旦我們已經設置好可以被批量賦值的屬性,便能通過 <code class=" language-php">create</code> 方法來添加一條新記錄到數據庫。<code class=" language-php">create</code> 方法將返回已經被保存的模型實例:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">create<span class="token punctuation">(</span></span><span class="token punctuation">[</span><span class="token string">'name'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'Flight 10'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><h4>Guarding Attributes</h4><p><code class=" language-php"><span class="token variable">$fillable</span></code> 作為一個可以被批量賦值的屬性「白名單」。另外你也可以選擇使用 <code class=" language-php"><span class="token variable">$guarded</span></code>。<code class=" language-php"><span class="token variable">$guarded</span></code> 屬性應該包含一個你不想要被批量賦值的屬性數組。所有不在數組里面的其它屬性都可以被批量賦值。因此,<code class=" language-php"><span class="token variable">$guarded</span></code> 的功能更類似一個「黑名單」。使用的時候應該只選擇 <code class=" language-php"><span class="token variable">$fillable</span></code> 或 <code class=" language-php"><span class="token variable">$guarded</span></code> 中的其中一個。 下面這個例子中,<strong>除了 <code class=" language-php">price</code></strong> 所有的屬性都可以被批量賦值:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 不可被批量賦值的屬性。
*
* @var array
*/</span>
<span class="token keyword">protected</span> <span class="token variable">$guarded</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'price'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre><p>如果你想讓所有的屬性都可以被批量賦值,你應該定義 <code class=" language-php"><span class="token variable">$guarded</span></code>為空數組。</p><pre class=" language-php"><code class=" language-php"><span class="token comment" spellcheck="true">/**
* 不可被批量賦值的屬性。
*
* @var array
*/</span>
<span class="token keyword">protected</span> <span class="token variable">$guarded</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span></code></pre><p><a name="other-creation-methods"></a></p><h3>其它創建的方法</h3><p>還有兩種其它方法,你可以用來通過屬性批量賦值創建你的模型:<code class=" language-php">firstOrCreate</code> 和 <code class=" language-php">firstOrNew</code>。<code class=" language-php">firstOrCreate</code> 方法將會使用指定的字段/值對,來嘗試尋找數據庫中的記錄。如果在數據庫中找不到模型,則會使用指定的屬性來添加一條記錄。</p><p><code class=" language-php">firstOrNew</code> 方法類似 <code class=" language-php">firstOrCreate</code> 方法,它會嘗試使用指定的屬性在數據庫中尋找符合的紀錄。如果模型未被找到,將會返回一個新的模型實例。請注意 <code class=" language-php">firstOrnew</code> 返回的模型還尚未保存到數據庫。你需要通過手動調用 <code class=" language-php">save</code> 方法來保存它:</p><pre class=" language-php"><code class=" language-php"><span class="token comment" spellcheck="true">// 用屬性取回航班,當結果不存在時創建它...
</span><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">firstOrCreate<span class="token punctuation">(</span></span><span class="token punctuation">[</span><span class="token string">'name'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'Flight 10'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">
// 用屬性取回航班,當結果不存在時實例化一個新實例...
</span><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">firstOrNew<span class="token punctuation">(</span></span><span class="token punctuation">[</span><span class="token string">'name'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token string">'Flight 10'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p><a name="deleting-models"></a></p><h2><a href="#deleting-models">刪除模型</a></h2><p>要刪除模型,必須在模型實例上調用 <code class=" language-php">delete</code> 方法:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$flight</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">find<span class="token punctuation">(</span></span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">delete<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><h4>通過鍵來刪除現有的模型</h4><p>在上面的例子中,我們在調用 <code class=" language-php">delete</code> 方法之前會先從數據庫中取回模型。不過,如果你已知道了模型中的主鍵,則可以不用取回模型就能直接刪除它。若要直接刪除,請調用 <code class=" language-php">destroy</code> 方法:</p><pre class=" language-php"><code class=" language-php"><span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">destroy<span class="token punctuation">(</span></span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">destroy<span class="token punctuation">(</span></span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">destroy<span class="token punctuation">(</span></span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><h4>通過查詢來刪除模型</h4><p>當然,你也可以運行在一組模型刪除查詢。在這個例子中,我們會刪除被標記為不活躍的所有航班。 像批量更新那樣,批量刪除不會刪除的任何被刪除的模型的事件:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$deletedRows</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'active'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">delete<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><blockquote class="has-icon note"><p><div class="flag"><span class="svg"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" version="1.1" x="0px" y="0px" width="90px" height="90px" viewBox="0 0 90 90" enable-background="new 0 0 90 90" xml:space="preserve"><path fill="#FFFFFF" d="M45 0C20.1 0 0 20.1 0 45s20.1 45 45 45 45-20.1 45-45S69.9 0 45 0zM45 74.5c-3.6 0-6.5-2.9-6.5-6.5s2.9-6.5 6.5-6.5 6.5 2.9 6.5 6.5S48.6 74.5 45 74.5zM52.1 23.9l-2.5 29.6c0 2.5-2.1 4.6-4.6 4.6 -2.5 0-4.6-2.1-4.6-4.6l-2.5-29.6c-0.1-0.4-0.1-0.7-0.1-1.1 0-4 3.2-7.2 7.2-7.2 4 0 7.2 3.2 7.2 7.2C52.2 23.1 52.2 23.5 52.1 23.9z"></path></svg></span></div> 當使用 Eloquent 批量刪除語句時,<code class=" language-php">deleting</code> 和 <code class=" language-php">deleted</code> 模型事件不會在被刪除模型實例上觸發。因為刪除語句執行時,不會檢索回模型實例。</p></blockquote><p><a name="soft-deleting"></a></p><h3>軟刪除</h3><p>除了從數據庫中移除實際記錄,Eloquent 也可以「軟刪除」模型。當模型被軟刪除時,它們并不會真的從數據庫中被移除。而是會在模型上設置一個 <code class=" language-php">deleted_at</code> 屬性并將其添加到數據庫。如果模型有一個非空值 <code class=" language-php">deleted_at</code>,代表模型已經被軟刪除了。要在模型上啟動軟刪除,則必須在模型上使用 <code class=" language-php">Illuminate\<span class="token package">Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>SoftDeletes</span></code> trait 并添加 <code class=" language-php">deleted_at</code> 字段到你的 <code class=" language-php"><span class="token variable">$dates</span></code> 屬性上:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>SoftDeletes</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Flight</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span>
<span class="token punctuation">{</span>
<span class="token keyword">use</span> <span class="token package">SoftDeletes</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">/**
* 需要被轉換成日期的屬性。
*
* @var array
*/</span>
<span class="token keyword">protected</span> <span class="token variable">$dates</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'deleted_at'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre><p>當然,你也應該添加 <code class=" language-php">deleted_at</code> 字段到數據表中。Laravel <a href="/docs/5.4/migrations">結構生成器</a> 包含了一個用來創建此字段的輔助函數:</p><pre class=" language-php"><code class=" language-php"><span class="token scope">Schema<span class="token punctuation">::</span></span><span class="token function">table<span class="token punctuation">(</span></span><span class="token string">'flights'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$table</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$table</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">softDeletes<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p>現在,當你在模型上調用 <code class=" language-php">delete</code> 方法時,<code class=" language-php">deleted_at</code> 字段將會被設置成目前的日期和時間。而且,當查詢有啟用軟刪除的模型時,被軟刪除的模型將會自動從所有查詢結果中排除。</p><p>要確認指定的模型實例是否已經被軟刪除,可以使用 <code class=" language-php">trashed</code> 方法:</p><pre class=" language-php"><code class=" language-php"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">trashed<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment" spellcheck="true"> //
</span><span class="token punctuation">}</span></code></pre><p><a name="querying-soft-deleted-models"></a></p><h3>查詢被軟刪除的模型</h3><h4>包含被軟刪除的模型</h4><p>如上所述,被軟刪除的模型將會自動從所有的查詢結果中排除。不過,你可以通過在查詢中調用 <code class=" language-php">withTrashed</code> 方法來強制查詢已被軟刪除的模型:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$flights</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">withTrashed<span class="token punctuation">(</span></span><span class="token punctuation">)</span>
<span class="token operator">-</span><span class="token operator">></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'account_id'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
<span class="token operator">-</span><span class="token operator">></span><span class="token function">get<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p><code class=" language-php">withTrashed</code> 方法也可以被用在 <a href="/docs/5.4/eloquent-relationships">關聯</a> 查詢:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">history<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">withTrashed<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">get<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><h4>只取出軟刪除數據</h4><p><code class=" language-php">onlyTrashed</code> 會只取出軟刪除數據:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$flights</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">onlyTrashed<span class="token punctuation">(</span></span><span class="token punctuation">)</span>
<span class="token operator">-</span><span class="token operator">></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'airline_id'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
<span class="token operator">-</span><span class="token operator">></span><span class="token function">get<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><h4>恢復被軟刪除的模型</h4><p>有時候你可能希望「取消刪除」一個已被軟刪除的模型。要恢復一個已被軟刪除的模型到有效狀態,則可在模型實例上使用 <code class=" language-php">restore</code> 方法:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">restore<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p>你也可以在查詢上使用 <code class=" language-php">restore</code> 方法來快速地恢復多個模型:</p><pre class=" language-php"><code class=" language-php"><span class="token scope">App<span class="token punctuation">\</span>Flight<span class="token punctuation">::</span></span><span class="token function">withTrashed<span class="token punctuation">(</span></span><span class="token punctuation">)</span>
<span class="token operator">-</span><span class="token operator">></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'airline_id'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
<span class="token operator">-</span><span class="token operator">></span><span class="token function">restore<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p>與 <code class=" language-php">withTrashed</code> 方法類似,<code class=" language-php">restore</code> 方法也可以被用在 <a href="/docs/5.4/eloquent-relationships">關聯</a> 查詢上:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">history<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">restore<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><h4>永久地刪除模型</h4><p>有時候你可能需要真正地從數據庫移除模型。要永久地從數據庫移除一個已被軟刪除的模型,則可使用 <code class=" language-php">forceDelete</code> 方法:</p><pre class=" language-php"><code class=" language-php"><span class="token comment" spellcheck="true">// 強制刪除單個模型實例...
</span><span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">forceDelete<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">
// 強制刪除所有相關模型...
</span><span class="token variable">$flight</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">history<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">forceDelete<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p><a name="query-scopes"></a></p><h2><a href="#query-scopes">查詢作用域</a></h2><p><a name="global-scopes"></a></p><h3>全局作用域</h3><p>全局作用域允許我們為給定模型的所有查詢添加條件約束。Laravel 自帶的 <a href="#soft-deleting">軟刪除功能</a> 就使用了全局作用域來從數據庫中拉出所有沒有被刪除的模型。編寫自定義的全局作用域可以提供一種方便的、簡單的方式,來確保給定模型的每個查詢都有特定的條件約束。</p><h4>編寫全局作用域</h4><p>自定義全局作用域很簡單,首先定義一個實現 <code class=" language-php">Illuminate\<span class="token package">Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Scope</span></code> 接口的類,該接口要求你實現一個方法:<code class=" language-php">apply</code>。需要的話可以在 <code class=" language-php">apply</code> 方法中添加 <code class=" language-php">where</code> 條件到查詢:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Scopes</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Scope</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Builder</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">AgeScope</span> <span class="token keyword">implements</span> <span class="token class-name">Scope</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 應用作用域
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">apply<span class="token punctuation">(</span></span>Builder <span class="token variable">$builder</span><span class="token punctuation">,</span> Model <span class="token variable">$model</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token variable">$builder</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'age'</span><span class="token punctuation">,</span> <span class="token string">'>'</span><span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre><blockquote class="has-icon tip"><p><div class="flag"><span class="svg"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" version="1.1" x="0px" y="0px" width="56.6px" height="87.5px" viewBox="0 0 56.6 87.5" enable-background="new 0 0 56.6 87.5" xml:space="preserve"><path fill="#FFFFFF" d="M28.7 64.5c-1.4 0-2.5-1.1-2.5-2.5v-5.7 -5V41c0-1.4 1.1-2.5 2.5-2.5s2.5 1.1 2.5 2.5v10.1 5 5.8C31.2 63.4 30.1 64.5 28.7 64.5zM26.4 0.1C11.9 1 0.3 13.1 0 27.7c-0.1 7.9 3 15.2 8.2 20.4 0.5 0.5 0.8 1 1 1.7l3.1 13.1c0.3 1.1 1.3 1.9 2.4 1.9 0.3 0 0.7-0.1 1.1-0.2 1.1-0.5 1.6-1.8 1.4-3l-2-8.4 -0.4-1.8c-0.7-2.9-2-5.7-4-8 -1-1.2-2-2.5-2.7-3.9C5.8 35.3 4.7 30.3 5.4 25 6.7 14.5 15.2 6.3 25.6 5.1c13.9-1.5 25.8 9.4 25.8 23 0 4.1-1.1 7.9-2.9 11.2 -0.8 1.4-1.7 2.7-2.7 3.9 -2 2.3-3.3 5-4 8L41.4 53l-2 8.4c-0.3 1.2 0.3 2.5 1.4 3 0.3 0.2 0.7 0.2 1.1 0.2 1.1 0 2.2-0.8 2.4-1.9l3.1-13.1c0.2-0.6 0.5-1.2 1-1.7 5-5.1 8.2-12.1 8.2-19.8C56.4 12 42.8-1 26.4 0.1zM43.7 69.6c0 0.5-0.1 0.9-0.3 1.3 -0.4 0.8-0.7 1.6-0.9 2.5 -0.7 3-2 8.6-2 8.6 -1.3 3.2-4.4 5.5-7.9 5.5h-4.1H28h-0.5 -3.6c-3.5 0-6.7-2.4-7.9-5.7l-0.1-0.4 -1.8-7.8c-0.4-1.1-0.8-2.1-1.2-3.1 -0.1-0.3-0.2-0.5-0.2-0.9 0.1-1.3 1.3-2.1 2.6-2.1H41C42.4 67.5 43.6 68.2 43.7 69.6zM37.7 72.5H26.9c-4.2 0-7.2 3.9-6.3 7.9 0.6 1.3 1.8 2.1 3.2 2.1h4.1 0.5 0.5 3.6c1.4 0 2.7-0.8 3.2-2.1L37.7 72.5z"></path></svg></span></div> Laravel 沒有規定你需要把這些類放置于哪個文件夾,你可以自由在 <code class=" language-php">app</code> 文件夾下創建 <code class=" language-php">Scopes</code> 文件夾來存放。</p></blockquote><h4>應用全局作用域</h4><p>要將全局作用域分配給模型,需要重寫給定模型的 <code class=" language-php">boot</code> 方法并使用 <code class=" language-php">addGlobalScope</code> 方法:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Scopes<span class="token punctuation">\</span>AgeScope</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 數據模型的啟動方法
*
* @return void
*/</span>
<span class="token keyword">protected</span> <span class="token keyword">static</span> <span class="token keyword">function</span> <span class="token function">boot<span class="token punctuation">(</span></span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token scope"><span class="token keyword">parent</span><span class="token punctuation">::</span></span><span class="token function">boot<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token scope"><span class="token keyword">static</span><span class="token punctuation">::</span></span><span class="token function">addGlobalScope<span class="token punctuation">(</span></span><span class="token keyword">new</span> <span class="token class-name">AgeScope</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre><p>添加作用域后,如果使用 <code class=" language-php"><span class="token scope">User<span class="token punctuation">::</span></span><span class="token function">all<span class="token punctuation">(</span></span><span class="token punctuation">)</span></code> 查詢則會生成如下SQL語句:</p><pre class=" language-php"><code class=" language-php">select <span class="token operator">*</span> from `users` where `age` <span class="token operator">></span> <span class="token number">200</span></code></pre><h4>匿名的全局作用域</h4><p>Eloquent 還允許我們使用閉包定義全局作用域,這在實現簡單作用域的時候特別有用,這樣的話,我們就沒必要定義一個單獨的類了:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Builder</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 數據模型的啟動方法
*
* @return void
*/</span>
<span class="token keyword">protected</span> <span class="token keyword">static</span> <span class="token keyword">function</span> <span class="token function">boot<span class="token punctuation">(</span></span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token scope"><span class="token keyword">parent</span><span class="token punctuation">::</span></span><span class="token function">boot<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token scope"><span class="token keyword">static</span><span class="token punctuation">::</span></span><span class="token function">addGlobalScope<span class="token punctuation">(</span></span><span class="token string">'age'</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span>Builder <span class="token variable">$builder</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$builder</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'age'</span><span class="token punctuation">,</span> <span class="token string">'>'</span><span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre><p>我們還可以通過以下方式,利用 <code class=" language-php">age</code> 標識符來移除全局作用:</p><pre class=" language-php"><code class=" language-php"><span class="token scope">User<span class="token punctuation">::</span></span><span class="token function">withoutGlobalScope<span class="token punctuation">(</span></span><span class="token string">'age'</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">get<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><h4>移除全局作用域</h4><p>如果想要在給定查詢中移除指定全局作用域,可以使用 <code class=" language-php">withoutGlobalScope</code>:</p><pre class=" language-php"><code class=" language-php"><span class="token scope">User<span class="token punctuation">::</span></span><span class="token function">withoutGlobalScope<span class="token punctuation">(</span></span><span class="token scope">AgeScope<span class="token punctuation">::</span></span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">get<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p>如果你想要移除某幾個或全部全局作用域,可以使用 <code class=" language-php">withoutGlobalScopes</code> 方法:</p><pre class=" language-php"><code class=" language-php"><span class="token scope">User<span class="token punctuation">::</span></span><span class="token function">withoutGlobalScopes<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">get<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token scope">User<span class="token punctuation">::</span></span><span class="token function">withoutGlobalScopes<span class="token punctuation">(</span></span><span class="token punctuation">[</span><span class="token scope">FirstScope<span class="token punctuation">::</span></span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token scope">SecondScope<span class="token punctuation">::</span></span><span class="token keyword">class</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">get<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p><a name="local-scopes"></a></p><h3>本地作用域</h3><p>本地作用域允許我們定義通用的約束集合以便在應用中復用。例如,你可能經常需要獲取最受歡迎的用戶,要定義這樣的一個作用域,只需簡單在對應 Eloquent 模型方法前加上一個 <code class=" language-php">scope</code> 前綴,作用域總是返回查詢構建器:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 限制查詢只包括受歡迎的用戶。
*
* @return \Illuminate\Database\Eloquent\Builder
*/</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">scopePopular<span class="token punctuation">(</span></span><span class="token variable">$query</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token variable">$query</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'votes'</span><span class="token punctuation">,</span> <span class="token string">'>'</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment" spellcheck="true">/**
* 限制查詢只包括活躍的用戶。
*
* @return \Illuminate\Database\Eloquent\Builder
*/</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">scopeActive<span class="token punctuation">(</span></span><span class="token variable">$query</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token variable">$query</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'active'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre><h4>利用查詢范圍</h4><p>一旦定義了范圍,則可以在查詢模型時調用范圍方法。在進行方法調用時不需要加上 <code class=" language-php">scope</code> 前綴。你甚至可以鏈式調用不同的范圍,如:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$users</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>User<span class="token punctuation">::</span></span><span class="token function">popular<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">active<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">orderBy<span class="token punctuation">(</span></span><span class="token string">'created_at'</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">get<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><h4>動態范圍</h4><p>有時候,你可能希望定義一個可接受參數的范圍。這時只需給你的范圍加上額外的參數即可。范圍參數應該被定義在 <code class=" language-php"><span class="token variable">$query</span></code> 參數之后:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 限制查詢只包括指定類型的用戶。
*
* @return \Illuminate\Database\Eloquent\Builder
*/</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">scopeOfType<span class="token punctuation">(</span></span><span class="token variable">$query</span><span class="token punctuation">,</span> <span class="token variable">$type</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token variable">$query</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">where<span class="token punctuation">(</span></span><span class="token string">'type'</span><span class="token punctuation">,</span> <span class="token variable">$type</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre><p>現在,你可以在范圍調用時傳遞參數:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$users</span> <span class="token operator">=</span> <span class="token scope">App<span class="token punctuation">\</span>User<span class="token punctuation">::</span></span><span class="token function">ofType<span class="token punctuation">(</span></span><span class="token string">'admin'</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">get<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre><p><a name="events"></a></p><h2><a href="#events">事件</a></h2><p>Eloquent 模型會觸發許多事件,讓你在模型的生命周期的多個時間點進行監控: <code class=" language-php">creating</code>, <code class=" language-php">created</code>, <code class=" language-php">updating</code>, <code class=" language-php">updated</code>, <code class=" language-php">saving</code>, <code class=" language-php">saved</code>, <code class=" language-php">deleting</code>, <code class=" language-php">deleted</code>, <code class=" language-php">restoring</code>, <code class=" language-php">restored</code>.</p><p>事件讓你每當有特定的模型類在數據庫保存或更新時,執行代碼。</p><p>當一個新模型被初次保存將會觸發 <code class=" language-php">creating</code> 以及 <code class=" language-php">created</code> 事件。如果一個模型已經存在于數據庫且調用了 <code class=" language-php">save</code> 方法,將會觸發 <code class=" language-php">updating</code> 和 <code class=" language-php">updated</code> 事件。在這兩種情況下都會觸發 <code class=" language-php">saving</code> 和 <code class=" language-php">saved</code> 事件。</p><p>開始前,在你的 Eloquent 模型上定義一個 <code class=" language-php"><span class="token variable">$events</span></code> 屬性,將 Eloquent 模型的生命周期的多個點映射到你的 <a href="/docs/5.4/providers">服務提供者</a> 。</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Events<span class="token punctuation">\</span>UserSaved</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Events<span class="token punctuation">\</span>UserDeleted</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Notifications<span class="token punctuation">\</span>Notifiable</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Auth<span class="token punctuation">\</span>User</span> <span class="token keyword">as</span> Authenticatable<span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token keyword">extends</span> <span class="token class-name">Authenticatable</span>
<span class="token punctuation">{</span>
<span class="token keyword">use</span> <span class="token package">Notifiable</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">/**
* 模型的時間映射。
*
* @var array
*/</span>
<span class="token keyword">protected</span> <span class="token variable">$events</span> <span class="token operator">=</span> <span class="token punctuation">[</span>
<span class="token string">'saved'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token scope">UserSaved<span class="token punctuation">::</span></span><span class="token keyword">class</span><span class="token punctuation">,</span>
<span class="token string">'deleted'</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token scope">UserDeleted<span class="token punctuation">::</span></span><span class="token keyword">class</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre><p><a name="observers"></a></p><h3>觀察者</h3><p>如果你在一個給定的模型中監聽許多事件,您可以使用觀察者將所有監聽器變成一個類。觀察者類里的方法名應該反映Eloquent想監聽的事件。 每種方法接收 model 作為其唯一的參數。 Laravel不包括觀察者默認目錄,所以你可以創建任何你喜歡你的目錄來存放:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Observers</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">UserObserver</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 監聽用戶創建的事件。
*
* @param User $user
* @return void
*/</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">created<span class="token punctuation">(</span></span>User <span class="token variable">$user</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true"> //
</span> <span class="token punctuation">}</span>
<span class="token comment" spellcheck="true">/**
* 監聽用戶刪除事件。
*
* @param User $user
* @return void
*/</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">deleting<span class="token punctuation">(</span></span>User <span class="token variable">$user</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true"> //
</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre><p>要注冊一個觀察者,需要用模型中的<code class=" language-php">observe</code>方法去觀察。你可以在你的服務提供商之一的<code class=" language-php">boot</code>方法中注冊觀察者。在這個例子中,我們將在<code class=" language-php">AppServiceProvider</code>注冊觀察者:</p><pre class=" language-php"><code class=" language-php"><span class="token delimiter"><?php</span>
<span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Providers</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>User</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Observers<span class="token punctuation">\</span>UserObserver</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>ServiceProvider</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">AppServiceProvider</span> <span class="token keyword">extends</span> <span class="token class-name">ServiceProvider</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">/**
* 運行所有應用.
*
* @return void
*/</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">boot<span class="token punctuation">(</span></span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token scope">User<span class="token punctuation">::</span></span><span class="token function">observe<span class="token punctuation">(</span></span><span class="token scope">UserObserver<span class="token punctuation">::</span></span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment" spellcheck="true">/**
* 注冊服務提供.
*
* @return void
*/</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">register<span class="token punctuation">(</span></span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true"> //
</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre><h2>譯者署名</h2><table><thead><tr><th>用戶名</th><th>頭像</th><th>職能</th><th>簽名</th></tr></thead><tbody><tr><td><a href="https://github.com/dongli0">@LXY</a></td><td><img class="avatar-66 rm-style" src="https://dn-phphub.qbox.me/uploads/avatars/5832_1473813539.jpeg?imageView2/1/w/380/h/380"></td><td>翻譯</td><td>PHP 小學生。</td></tr></tbody></table></article>
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- 請求周期
- 開發環境部署
- Valet
- Homestead
- 核心概念
- 服務提供者
- Facades
- Contracts
- 服務容器
- HTTP 層
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- Session
- 表單驗證
- 前端
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全
- API 認證
- 用戶認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- Redis
- 數據填充
- Eloquent ORM
- Eloquent ORM快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- 序列化
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 錯誤與日志
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度