信件样式与内容编辑

Markdown

先看看目前刚新建好的 Markdown 信件。

@component('mail::message')
# Introduction

The body of your message.

@component('mail::custom.blueButton', ['url' => ''])
Button Text
@endcomponent

Thanks,<br>
{{ config('app.name') }}
@endcomponent

Laravel 的 Markdown 信件结合了 Blade 的元件功能,尽可能用元件编排可以让主要的信件内容更聚焦。

举目前的架构来说,上面的 Markdown 信件首先用了 @component('mail::message') 引入 message 这个元件,而 message 又引入了 layout。

在 message 这个元件 (路径:resources/views/vendor/mail/html/message.blade.php) 中可以找到如下的程序码。

resources/views/vendor/mail/html/message.blade.php
{{ $slot }}

这个就像 React 里的 children 一样, @component 到 @endcomponent 间的内容会被置入这里。

而 message 本身又被置入 layout 元件中,不过这边不太一样

resources/views/vendor/mail/html/layout.blade.php

{{ Illuminate\Mail\Markdown::parse($slot) }}

$slot 被放在 Markdown::parse 中,所以主要的 Markdown 编译其实在这。

另外在 layout 中可以看到 {{ $header ?? '' }}{{ $subcopy ?? '' }}{{ $footer ?? '' }} ,这是 Blade 的功能,可以定义多个不同的 slot 。

对应 message 中的内容,用 @slot 指定要将内容放入哪个 $slot:

resources/views/vendor/mail/html/message.blade.php

@slot('header')
@component('mail::header', ['url' => config('app.url')])
{{ config('app.name') }}
@endcomponent
@endslot

自订元件

先看信件引入元件的语法

@component('mail::message')

在编译 Markdown 的时候,Laravel 会到 resources/views/vendor/mail
底下找对应 mail:: 後面字串的原件进行编译,不过可以看到 mail 目录底下其实没有元件,而是两个资料夹 html 跟 text 。

这是因为产生信件时会同时产生 html 信件内容与纯文字信件内容,所以两个目录下都需要要有对应的元件以供编译。

举例来说,如果想要新增一个 dangerButton 元件的话,在 html 跟 text 底下都要建一个

当然两者的内容不会相同,在 text 目录下的元件只需要纯文字。

建好後就可以用来建构信件啦,引入的方法跟其他元件一样

@component('mail::blueButton', ['url' => ''])
Button Text
@endcomponent

不过全部的元件塞在同一个资料夹迟早会乱成一团,所以希望可以分资料夹放置元件。

这时候只要在引用时用.区分目录就好。

@component('mail::custom.blueButton', ['url' => ''])
Button Text
@endcomponent

剩下就是编写元件内容啦,使用的是 blade 语法,除了可以穿插 Laravel 的变数跟功能外跟 html 差不多,关於穿插 Laravel 变数跟功能的部分後面的段落再说。

更改样式

目前信件尚在参照预设的 default 样式,还在 vendor 套件目录底下,如果要自行更改的话,要先将样式发布到专案目录底下。

sail artisan vendor:publish --tag=laravel-mail

这样就可以在 resources 目录中找到 default 的样式跟 layout ,可以从这里编辑。

当然我们可以直接改 default.css ,不过也可以建立复数个 css 再另外引入。

复制一份 default 并将其改名为 custom.css ,然後改信件内文的背景色为米色

resources/views/vendor/mail/html/themes/custom.css

.inner-body {
    -premailer-cellpadding: 0;
    -premailer-cellspacing: 0;
    -premailer-width: 570px;
    background-color: wheat;  /*改米色*/
    border-color: #e8e5ef;
    border-radius: 2px;
    border-width: 1px;
    box-shadow: 0 2px 0 rgba(0, 0, 150, 0.025), 2px 4px 0 rgba(0, 0, 150, 0.015);
    margin: 0 auto;
    padding: 0;
    width: 570px;
}

接着在产生信件前指定样式

app/Mail/CustomVerifyMail.php

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class CustomVerifyMail extends Mailable
{
    use Queueable, SerializesModels;

    public function __construct()
    {
        //
    }
    
    public function build()
    { 
+       $this->theme = 'custom';  
        return $this->markdown('mail.custom.verify');
    }
}

这边指定的样式必须放在 resources/views/vendor/mail/html/themes 目录下才能被参照到。

要在元件内引用 class 的话跟 html 相同,比较特别的是可以用 php 语法动态变更 class 。

<a href="{{ $url }}" class="button button-{{ $color ?? 'primary' }}" target="_blank" rel="noopener">{{ $slot }}</a>

更改内容

撰写信件内容

如果是最後会被 Illuminate\Mail\Markdown::parse() 编译的内容,就可以直接用 Markdown 语法书写。

# Introduction

也可以穿插 Blade 语法

Thanks,<br>

如果需要 php 或 Laravel 功能编译字串、引入环境变数或进行 i18n 翻译的话,要用 {{ }} 框起来。

{{ strtoupper('Hello') }}

{{ config('app.name') }}

{{ __('i18n.translation') }}

比较特别的是如果字串里有 \n 的话,一般的引入会被视为普通字元

{{ "Hello,\nWorld" }}

这时候需要换成一个特别的函式帮忙把 \n 通通换成<br/>

恩...,换是换好了....

换完的 <br/> 一样会被视为普通字元,这时候要换个框{!! !!}来告诉 Blade 这串字要原原本本本的带入模板,好让 <br/> 生效。

{!! nl2br("Hello,\nWorld") !!}

这样就会成功换行了


<<:  资料取得 - 多重来源

>>:  Day 27 - Vue 与 HTTP请求 (2)

理解 HTTP(二):Method、Status Code

昨天大致谈了网站内容是怎麽被下载到电脑里的,今天稍微深入一点聊聊关於 HTTP 这个协定的一些简单并...

9. STM32-PWM 呼吸灯(下)

设定.ioc档 这边选择TIM2来做,首先进到.ioc当中先确认系统时钟频率为多少,这边我的是16M...

设定档格式 YAML

YAML YAML的诞生不算太晚, 1.0在2004就出了, 虽然晚了JSON 5年(1999年),...

iOS APP 开发 OC 第六天, 面向过程&面向对象

tags: OC 30 day 什麽是面向对象? 实现需求之一: Ex:要如何将大象放入冰箱? 打开...

Day-05 Ruby 的世界里,万物都是物件?

什麽是物件? 物件(object) = 状态(state) + 行为(behavior) Ruby ...