🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
<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">&lt;?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">&lt;?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">&lt;?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">&lt;?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">&lt;?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">&lt;?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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">'&gt;'</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">&gt;</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">&gt;</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">&gt;</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">&lt;?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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&lt;?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">&gt;</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">&lt;?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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&lt;?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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&lt;?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">&gt;</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">'&gt;'</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">&lt;?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">&gt;</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">&lt;?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">&gt;</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">'&gt;'</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&lt;?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">&gt;</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">'&gt;'</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">&gt;</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">&gt;</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">&gt;</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">&gt;</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">&lt;?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">&gt;</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">&gt;</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">&lt;?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">&gt;</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">&gt;</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">&lt;?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">&lt;?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>