ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
<article><h1>Eloquent: 修改器</h1><ul><li><a href="#introduction">简介</a></li><li><a href="#accessors-and-mutators">访问器 &amp; 修改器</a><ul><li><a href="#defining-an-accessor">定义一个访问器</a></li><li><a href="#defining-a-mutator">定义一个修改器</a></li></ul></li><li><a href="#date-mutators">日期转换器</a></li><li><a href="#attribute-casting">属性类型转换</a><ul><li><a href="#array-and-json-casting">数组 &amp; JSON 转换</a></li></ul></li></ul><p><a name="introduction"></a></p><h2><a href="#introduction">简介</a></h2><p>访问器和修改器可以让你修改 Eloquent 模型中的属性或者设置它们的值,例如,你可能想要使用 <a href="/docs/5.4/encryption">Laravel 加密器</a> 来加密一个被保存在数据库中的值,当你从 Eloquent 模型访问该属性时该值将被自动解密。</p><p>除了自定义访问器和修改器之外,Eloquent 也会自动将日期字段类型转换成 <a href="https://github.com/briannesbitt/Carbon">Carbon</a> 实例或将 <a href="#attribute-casting">文本字段类型转换成 JSON</a>。</p><p><a name="accessors-and-mutators"></a></p><h2><a href="#accessors-and-mutators">访问器 &amp; 修改器</a></h2><p><a name="defining-an-accessor"></a></p><h3>定义一个访问器</h3><p>若要定义一个访问器,则须在你的模型上创建一个 <code class=" language-php">getFooAttribute</code> 方法。要访问的 <code class=" language-php">Foo</code> 字段需使用「驼峰式」来命名。在这个例子中,我们将为 <code class=" language-php">first_name</code> 属性定义一个访问器。当 Eloquent 尝试获取 <code class=" language-php">first_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">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">/** * 获取用户的名字。 * * @param string $value * @return string */</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">getFirstNameAttribute<span class="token punctuation">(</span></span><span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token function">ucfirst<span class="token punctuation">(</span></span><span class="token variable">$value</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">first_name</code> 属性:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$user</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">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">$firstName</span> <span class="token operator">=</span> <span class="token variable">$user</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">first_name</span><span class="token punctuation">;</span></code></pre><p><a name="defining-a-mutator"></a></p><h3>定义一个修改器</h3><p>若要定义一个修改器,则须在模型上定义一个 <code class=" language-php">setFooAttribute</code> 方法。要访问的 <code class=" language-php">Foo</code> 字段需使用「驼峰式」来命名。让我们再来定义 <code class=" language-php">first_name</code> 属性的修改器。当我们尝试在模型上设置 <code class=" language-php">first_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">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">/** * 设定用户的名字。 * * @param string $value * @return void */</span> <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">setFirstNameAttribute<span class="token punctuation">(</span></span><span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token this">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">attributes</span><span class="token punctuation">[</span><span class="token string">'first_name'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">strtolower<span class="token punctuation">(</span></span><span class="token variable">$value</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span></code></pre><p>修改器会获取属性已经被设置的值,让你可以操作该值并将其设置到 Eloquent 模型内部的 <code class=" language-php"><span class="token variable">$attributes</span></code> 属性上。举个例子,如果我们尝试将 <code class=" language-php">first_name</code> 属性设置成 <code class=" language-php">Sally</code>:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$user</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">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">$user</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">first_name</span> <span class="token operator">=</span> <span class="token string">'Sally'</span><span class="token punctuation">;</span></code></pre><p>在这个例子中,<code class=" language-php">setFirstNameAttribute</code> 函数将会使用 <code class=" language-php">Sally</code> 作为参数来调用。修改器会对该名字使用 <code class=" language-php">strtolower</code> 函数并将其值设置于内部的 <code class=" language-php"><span class="token variable">$attributes</span></code> 数组。</p><p><a name="date-mutators"></a></p><h2><a href="#date-mutators">日期转换器</a></h2><p>默认情况下,Eloquent 将会把 <code class=" language-php">created_at</code> 和 <code class=" language-php">updated_at</code> 字段转换成 <a href="https://github.com/briannesbitt/Carbon">Carbon</a> 实例,它提供了各种各样的方法,并继承了 PHP 原生的 DateTime 类。</p><p>你可以在模型中自定义哪些字段需要被自动修改,或完全禁止修改,可通过重写模型的 <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">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">/** * 应被转换为日期的属性。 * * @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">'created_at'</span><span class="token punctuation">,</span> <span class="token string">'updated_at'</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>当某个字段被认为是日期时,你或许想将其数值设置成一个 UNIX 时间戳、日期字符串(<code class=" language-php">Y<span class="token operator">-</span>m<span class="token operator">-</span>d</code>)、日期时间( <code class=" language-php">date<span class="token operator">-</span>time</code> )字符串,当然还有 <code class=" language-php">DateTime</code> 或 <code class=" language-php">Carbon</code> 实例,然后日期数值将会被自动保存到数据库中:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$user</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">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">$user</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">deleted_at</span> <span class="token operator">=</span> <span class="token scope">Carbon<span class="token punctuation">::</span></span><span class="token function">now<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token variable">$user</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><p>如上所述,在 <code class=" language-php"><span class="token variable">$dates</span></code> 属性中列出的所有属性被获取到时,都将会自动转换成 <a href="https://github.com/briannesbitt/Carbon">Carbon</a> 实例,让你可在属性上使用任何 <code class=" language-php">Carbon</code> 方法:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$user</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">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 keyword">return</span> <span class="token variable">$user</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">deleted_at</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getTimestamp<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 string">'Y-m-d H:i:s'</span></code> 格式化。如果你想要自定义自己的时间戳格式,可在模型中设置 <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><p><a name="attribute-casting"></a></p><h2><a href="#attribute-casting">属性类型转换</a></h2><p><code class=" language-php"><span class="token variable">$casts</span></code> 属性在模型中提供了将属性转换为常见的数据类型的方法。<code class=" language-php"><span class="token variable">$casts</span></code> 属性应是一个数组,且键是那些需要被转换的属性名称,值则是代表字段要转换的类型。支持的转换的类型有:</p><ul><li>integer</li><li>real</li><li>float</li><li>double</li><li>string</li><li>boolean</li><li>object</li><li>array</li><li>collection</li><li>date</li><li>datetime</li><li>timestamp</li></ul><p>例如,<code class=" language-php">is_admin</code> 属性以整数(<code class=" language-php"><span class="token number">0</span></code> 或 <code class=" language-php"><span class="token number">1</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">/** * 应该被转换成原生类型的属性。 * * @var array */</span> <span class="token keyword">protected</span> <span class="token variable">$casts</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token string">'is_admin'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token string">'boolean'</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">is_admin</code> 属性时,它将会被转换成布尔值,即便保存在数据库里的值是一个整数:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$user</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">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 keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$user</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">is_admin</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="array-and-json-casting"></a></p><h3>数组 &amp; JSON 转换</h3><p>若原本字段保存的是被序列化的 JSON,则 <code class=" language-php"><span class="token keyword">array</span></code> 类型转换将会特别有用。例如,在你的数据库中有一个 <code class=" language-php"><span class="token constant">JSON</span></code> 或 <code class=" language-php"><span class="token constant">TEXT</span></code> 字段类型,其包含了 被序列化的 JSON,且对该属性添加了 <code class=" language-php"><span class="token keyword">array</span></code> 类型转换。当你在 Eloquent 模型上访问该属性时,它将会被自动反序列化成一个 PHP 数组:</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">/** * 应该被转换成原生类型的属性。 * * @var array */</span> <span class="token keyword">protected</span> <span class="token variable">$casts</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token string">'options'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token string">'array'</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">options</code> 属性,它将会自动把 JSON 反序列化成一个 PHP 数组。当你设置 <code class=" language-php">options</code> 属性的值时,指定的数组将会被自动序列化成 JSON 以便进行保存:</p><pre class=" language-php"><code class=" language-php"><span class="token variable">$user</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">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">$options</span> <span class="token operator">=</span> <span class="token variable">$user</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">options</span><span class="token punctuation">;</span> <span class="token variable">$options</span><span class="token punctuation">[</span><span class="token string">'key'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'value'</span><span class="token punctuation">;</span> <span class="token variable">$user</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">options</span> <span class="token operator">=</span> <span class="token variable">$options</span><span class="token punctuation">;</span> <span class="token variable">$user</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><h2>译者署名</h2><table><thead><tr><th>用户名</th><th>头像</th><th>职能</th><th>签名</th></tr></thead><tbody><tr><td><a href="https://laravel-china.org/users/79">@skyverd</a></td><td><img class="avatar-66 rm-style" src="https://dn-phphub.qbox.me/uploads/avatars/79_1427370664.jpeg?imageView2/1/w/100/h/100"></td><td>翻译</td><td>全桟工程师,<a href="https://skyverd.com">时光博客</a></td></tr></tbody></table></article>