Магазин на Yii2, часть 22. Оформление заказа, часть третья

17.08.2019

Теги: Web-разработкаYii2ЗаказИнтернетМагазинКаталогТоваровКорзинаПрактикаФреймворк

Осталось только отправить письмо покупателю о заказе. Для отправки почты Yii2 предлагает расширение swiftmailer, которое нужно просто настроить. Настраивается оно в файле config/web.php. Обратите внимание на настройку useFileTransport: когда она имеет значение true — письмо не отправляется реально, что нам и нужно.

$config = [
    /*...*/
    'components' => [
        /*...*/
        'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => true,
            'htmlLayout' => 'layouts/html',
        ],
        /*...*/
    ],
    /*...*/
];

Давайте подготовим шаблон письма, для этого создадим файл order.php в директории mail:

<?php
use yii\helpers\Html;
$this->title = 'Заказ в магазине № ' . $order->id;
?>

<h1><?= Html::encode($this->title); ?></h1>

<ul>
    <li>Покупатель: <?= Html::encode($order->name); ?></li>
    <li>E-mail: <?= Html::encode($order->email); ?></li>
    <li>Телефон: <?= Html::encode($order->phone); ?></li>
</ul>

<table border="1" cellpadding="3" cellspacing="0">
    <tr>
        <th align="left">Наименование</th>
        <th align="left">Кол-во, шт</th>
        <th align="left">Цена, руб.</th>
        <th align="left">Сумма, руб.</th>
    </tr>
    <?php foreach ($order->items as $product): ?>
        <tr>
            <td align="left"><?= Html::encode($product['name']); ?></td>
            <td align="right"><?= $product['quantity']; ?></td>
            <td align="right"><?= $product['price']; ?></td>
            <td align="right"><?= $product['cost']; ?></td>
        </tr>
    <?php endforeach; ?>
    <tr>
        <td colspan="3" align="right">Итого</td>
        <td align="right"><?= $order['amount']; ?></td>
    </tr>
</table>

<p>Адрес доставки: <?= Html::encode($order->address); ?></p>

<p>Комментарий: <?= Html::encode($order->comment); ?></p>

Теперь добавим в контроллер код отправки письма:

<?php
namespace app\controllers;

use Yii;
use app\models\Basket;
use app\models\Order;

class OrderController extends AppController {
    public $defaultAction = 'checkout';

    public function actionCheckout() {
        // если в корзине нет товаров, здесь делать нечего
        if (empty((new Basket())->getBasket())) {
            return $this->redirect(['basket/index']);
        }
        $this->setMetaTags('Оформление заказа');
        $order = new Order();
        /*
         * Если пришли post-данные, загружаем их в модель...
         */
        if ($order->load(Yii::$app->request->post())) {
            // ...и проверяем эти данные
            if ( ! $order->validate()) {
                // данные не прошли валидацию, отмечаем этот факт
                Yii::$app->session->setFlash(
                    'checkout-success',
                    false
                );
                // сохраняем в сессии введенные пользователем данные
                Yii::$app->session->setFlash(
                    'checkout-data',
                    [
                        'name' => $order->name,
                        'email' => $order->email,
                        'phone' => $order->phone,
                        'address' => $order->address,
                        'comment' => $order->comment
                    ]
                );
                /*
                 * Сохраняем в сессии массив сообщений об ошибках. Массив имеет вид
                 * [
                 *     'name' => [
                 *         'Поле «Ваше имя» обязательно для заполнения',
                 *     ],
                 *     'email' => [
                 *         'Поле «Ваш email» обязательно для заполнения',
                 *         'Поле «Ваш email» должно быть адресом почты'
                 *     ]
                 * ]
                 */
                Yii::$app->session->setFlash(
                    'checkout-errors',
                    $order->getErrors()
                );
            } else {
                /*
                 * Заполняем остальные поля модели — те которые приходят
                 * не из формы, а которые надо получить из корзины. Кроме
                 * того, поля created и updated будут заполнены с помощью
                 * метода Order::behaviors().
                 */
                $basket = new Basket();
                $content = $basket->getBasket();
                $order->amount = $content['amount'];
                // сохраняем заказ в базу данных
                $order->insert();
                $order->addItems($content);
                // отправляем письмо покупателю
                $mail = Yii::$app->mailer->compose(
                    'order',
                    ['order' => $order]
                );
                $mail->setFrom(Yii::$app->params['senderEmail'])
                    ->setTo($order->email)
                    ->setSubject('Заказ в магазине № ' . $order->id)
                    ->send();
                // очищаем содержимое корзины
                $basket->clearBasket();
                // данные прошли валидацию, заказ успешно сохранен
                Yii::$app->session->setFlash(
                    'checkout-success',
                    true
                );
            }
            // выполняем редирект, чтобы избежать повторной отправки формы
            return $this->refresh();
        }
        return $this->render('checkout', ['order' => $order]);
    }
}

Само письмо будет таким, его можно найти в директории runtime/mail:

Message-ID: <c0bdfc0f1823d566ec47f3b237295bb7@www.example.com>
Date: Sat, 17 Aug 2019 10:28:47 +0300
Subject: =?utf-8?Q?=D0=97=D0=B0=D0=BA=D0=B0=D0=B7_=D0=B2_?=
 =?utf-8?Q?=D0=BC=D0=B0=D0=B3=D0=B0=D0=B7=D0=B8=D0=BD=D0=B5_=E2=84=96?= 7
From: noreply@example.com
To: ivanov@mail.ru
MIME-Version: 1.0
Content-Type: multipart/alternative;
 boundary="_=_swift_1566026927_e97faf701339ec540abb7bfef2e0f908_=_"


--_=_swift_1566026927_e97faf701339ec540abb7bfef2e0f908_=_
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

=D0=97=D0=B0=D0=BA=D0=B0=D0=B7 =D0=B2 =D0=BC=D0=B0=D0=B3=D0=B0=D0=B7=D0=
=B8=D0=BD=D0=B5 =E2=84=96 7

=D0=9F=D0=BE=D0=BA=D1=83=D0=BF=D0=B0=D1=
=82=D0=B5=D0=BB=D1=8C: =D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9 =D0=98=D0=B2=
=D0=B0=D0=BD=D0=BE=D0=B2
E-mail: ivanov@mail.ru
=D0=A2=D0=B5=D0=BB=D0=B5=D1=84=D0=BE=D0=BD: +7 (926) 765-43-21

=D0=
=9D=D0=B0=D0=B8=D0=BC=D0=B5=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5
=D0=9A=D0=BE=D0=BB-=D0=B2=D0=BE, =D1=88=D1=82
=D0=A6=D0=B5=D0=BD=D0=B0, =D1=80=D1=83=D0=B1.
=D0=A1=D1=83=D0=BC=D0=BC=D0=B0, =D1=80=D1=83=D0=B1.

=D0=9C=D1=83=D0=
=B6=D1=81=D0=BA=D0=B0=D1=8F =D0=BB=D0=B5=D1=82=D0=BD=D1=8F=D1=8F =D0=BE=
=D0=B4=D0=B5=D0=B6=D0=B4=D0=B0 1
2
1000.23
2000.46

=D0=9C=D1=83=D0=B6=D1=81=D0=BA=D0=B0=D1=8F =D0=BB=D0=B5=D1=
=82=D0=BD=D1=8F=D1=8F =D0=BE=D0=B4=D0=B5=D0=B6=D0=B4=D0=B0 2
3
56.00
168.00

=D0=98=D1=82=D0=BE=D0=B3=D0=BE
2168.46

=D0=90=D0=B4=D1=80=D0=B5=D1=81 =D0=B4=D0=BE=D1=81=D1=82=D0=
=B0=D0=B2=D0=BA=D0=B8: =D0=9C=D0=BE=D1=81=D0=BA=D0=B2=D0=B0, =D0=A4=D0=
=BB=D0=BE=D1=82=D1=81=D0=BA=D0=B0=D1=8F =D1=83=D0=BB=D0=B8=D1=86=D0=B0, =
=D0=B4=D0=BE=D0=BC 12, =D0=BA=D0=B2.72

=D0=9A=D0=BE=D0=BC=D0=BC=D0=
=B5=D0=BD=D1=82=D0=B0=D1=80=D0=B8=D0=B9: 2-=D0=BE=D0=B9 =D0=BF=D0=BE=D0=
=B4=D1=8A=D0=B5=D0=B7=D0=B4, 4-=D1=8B=D0=B9 =D1=8D=D1=82=D0=B0=D0=B6

--_=_swift_1566026927_e97faf701339ec540abb7bfef2e0f908_=_
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org=
/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns=3D"http://www.w3.org/1999/=
xhtml">
<head>
    <meta http-equiv=3D"Content-Type" content=3D"text/ht=
ml; charset=3DUTF-8" />
    <title>=D0=97=D0=B0=D0=BA=D0=B0=D0=B7 =D0=
=B2 =D0=BC=D0=B0=D0=B3=D0=B0=D0=B7=D0=B8=D0=BD=D0=B5 =E2=84=96 7</title>
=
    </head>
<body>
       =20
<h1>=D0=97=D0=B0=D0=BA=D0=B0=D0=B7 =D0=B2 =D0=BC=D0=B0=D0=B3=D0=B0=D0=B7=
=D0=B8=D0=BD=D0=B5 =E2=84=96 7</h1>

<ul>
    <li>=D0=9F=D0=BE=D0=BA=D1=83=D0=BF=D0=B0=D1=82=D0=B5=D0=BB=D1=8C: =
=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9 =D0=98=D0=B2=D0=B0=D0=BD=D0=BE=D0=
=B2</li>
    <li>E-mail: ivanov@mail.ru</li>
    <li>=D0=A2=D0=B5=D0=BB=D0=B5=D1=84=D0=BE=D0=BD: +7 (926) 765-43-21</li>
</ul>

<table border=3D"1" cellpadding=3D"3" cellspacing=3D"0">
    <tr>
        <th align=3D"left">=D0=9D=D0=B0=D0=B8=D0=BC=D0=B5=D0=BD=D0=BE=D0=
=B2=D0=B0=D0=BD=D0=B8=D0=B5</th>
        <th align=3D"left">=D0=9A=D0=BE=D0=BB-=D0=B2=D0=BE, =D1=88=D1=82</t=
h>
        <th align=3D"left">=D0=A6=D0=B5=D0=BD=D0=B0, =D1=80=D1=83=D0=B1.</t=
h>
        <th align=3D"left">=D0=A1=D1=83=D0=BC=D0=BC=D0=B0, =D1=80=D1=83=
=D0=B1.</th>
    </tr>
            <tr>
            <td align=3D"left">=D0=9C=D1=83=D0=B6=D1=81=D0=BA=D0=B0=D1=
=8F =D0=BB=D0=B5=D1=82=D0=BD=D1=8F=D1=8F =D0=BE=D0=B4=D0=B5=D0=B6=D0=B4=
=D0=B0 1</td>
            <td align=3D"right">2</td>
            <td align=3D"right">1000.23</td>
            <td align=3D"right">2000.46</td>
        </tr>
            <tr>
            <td align=3D"left">=D0=9C=D1=83=D0=B6=D1=81=D0=BA=D0=B0=D1=
=8F =D0=BB=D0=B5=D1=82=D0=BD=D1=8F=D1=8F =D0=BE=D0=B4=D0=B5=D0=B6=D0=B4=
=D0=B0 2</td>
            <td align=3D"right">3</td>
            <td align=3D"right">56.00</td>
            <td align=3D"right">168.00</td>
        </tr>
        <tr>
        <td colspan=3D"3" align=3D"right">=D0=98=D1=82=D0=BE=D0=B3=D0=BE</t=
d>
        <td align=3D"right">2168.46</td>
    </tr>
</table>

<p>=D0=90=D0=B4=D1=80=D0=B5=D1=81 =D0=B4=D0=BE=D1=81=D1=82=D0=B0=D0=B2=
=D0=BA=D0=B8: =D0=9C=D0=BE=D1=81=D0=BA=D0=B2=D0=B0, =D0=A4=D0=BB=D0=BE=
=D1=82=D1=81=D0=BA=D0=B0=D1=8F =D1=83=D0=BB=D0=B8=D1=86=D0=B0, =D0=B4=D0=
=BE=D0=BC 12, =D0=BA=D0=B2.72</p>

<p>=D0=9A=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=80=D0=B8=D0=B9: 2-=
=D0=BE=D0=B9 =D0=BF=D0=BE=D0=B4=D1=8A=D0=B5=D0=B7=D0=B4, 4-=D1=8B=D0=B9 =
=D1=8D=D1=82=D0=B0=D0=B6</p>

    </body>
</html>
--_=_swift_1566026927_e97faf701339ec540abb7bfef2e0f908_=_--

На этом с оформлением заказа мы закончили. А про отправку почты можно почитать здесь.

Поиск: Web-разработка • Yii2 • Интернет магазин • Каталог товаров • Фреймворк • Заказ • Корзина • Order • Basket

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.