お問い合わせフォームの作成
Netteでお問い合わせフォームを作成し、メールで送信する方法を見ていきましょう。さあ、始めましょう!
まず、新しいプロジェクトを作成する必要があります。その方法は はじめに ページで説明されています。その後、フォームの作成を開始できます。
最も簡単な方法は、Presenter内で直接フォームを作成する
ことです。事前に準備された HomePresenter
を使用できます。そこにフォームを表す
contactForm
コンポーネントを追加します。これを行うには、コードにコンポーネントを作成するファクトリメソッド
createComponentContactForm()
を記述します。
use Nette\Application\UI\Form;
use Nette\Application\UI\Presenter;
class HomePresenter extends Presenter
{
protected function createComponentContactForm(): Form
{
$form = new Form;
$form->addText('name', 'お名前:')
->setRequired('名前を入力してください');
$form->addEmail('email', 'メールアドレス:')
->setRequired('メールアドレスを入力してください');
$form->addTextarea('message', 'メッセージ:')
->setRequired('メッセージを入力してください');
$form->addSubmit('send', '送信');
$form->onSuccess[] = [$this, 'contactFormSucceeded'];
return $form;
}
public function contactFormSucceeded(Form $form, $data): void
{
// メールの送信
}
}
ご覧のとおり、2つのメソッドを作成しました。最初のメソッド createComponentContactForm()
は新しいフォームを作成します。このフォームには、名前、メール、メッセージのフィールドがあり、これらは
addText()
、addEmail()
、addTextArea()
メソッドで追加します。フォームを送信するためのボタンも追加しました。
しかし、ユーザーがフィールドを空欄にした場合はどうでしょうか?その場合、それが必須フィールドであることを知らせるべきです。これは
setRequired()
メソッドで実現しました。
最後に、フォームが正常に送信された場合にトリガーされる イベント onSuccess
も追加しました。私たちの場合、送信されたフォームの処理を担当する contactFormSucceeded
メソッドを呼び出します。これはすぐにコードに追加します。
contantForm
コンポーネントを Home/default.latte
テンプレートでレンダリングさせます。
{block content}
<h1>お問い合わせフォーム</h1>
{control contactForm}
メールの送信自体については、ContactFacade
という名前の新しいクラスを作成し、それを app/Model/ContactFacade.php
ファイルに配置します。
<?php
declare(strict_types=1);
namespace App\Model;
use Nette\Mail\Mailer;
use Nette\Mail\Message;
class ContactFacade
{
public function __construct(
private Mailer $mailer,
) {
}
public function sendMessage(string $email, string $name, string $message): void
{
$mail = new Message;
$mail->addTo('admin@example.com') // あなたのメールアドレス
->setFrom($email, $name)
->setSubject('お問い合わせフォームからのメッセージ')
->setBody($message);
$this->mailer->send($mail);
}
}
sendMessage()
メソッドはメールを作成して送信します。これには、コンストラクタを介して依存関係として渡される、いわゆるメーラーを使用します。メールの送信 について詳しく読んでください。
次に、Presenterに戻り、contactFormSucceeded()
メソッドを完成させます。これは
ContactFacade
クラスの sendMessage()
メソッドを呼び出し、フォームからのデータを渡します。そして、ContactFacade
オブジェクトをどのように取得しますか?コンストラクタを介して渡してもらいます。
use App\Model\ContactFacade;
use Nette\Application\UI\Form;
use Nette\Application\UI\Presenter;
class HomePresenter extends Presenter
{
public function __construct(
private ContactFacade $facade,
) {
}
protected function createComponentContactForm(): Form
{
// ...
}
public function contactFormSucceeded(stdClass $data): void
{
$this->facade->sendMessage($data->email, $data->name, $data->message);
$this->flashMessage('メッセージは送信されました');
$this->redirect('this');
}
}
メールが送信された後、ユーザーにメッセージが送信されたことを確認する、いわゆる フラッシュメッセージ を表示し、その後、ブラウザの リフレッシュ でフォームが繰り返し送信されるのを防ぐために次のページにリダイレクトします。
さて、すべてが機能していれば、お問い合わせフォームからメールを送信できるはずです。おめでとうございます!
HTMLメールテンプレート
今のところ、フォームから送信されたメッセージのみを含むプレーンテキストのメールが送信されます。しかし、メールでHTMLを使用して、その外観をより魅力的にすることができます。そのためにLatteでテンプレートを作成し、それを
app/Model/contactEmail.latte
に記述します。
<html>
<title>お問い合わせフォームからのメッセージ</title>
<body>
<p><strong>お名前:</strong> {$name}</p>
<p><strong>メールアドレス:</strong> {$email}</p>
<p><strong>メッセージ:</strong> {$message}</p>
</body>
</html>
残りは、このテンプレートを使用するように ContactFacade
を変更することです。コンストラクタで、Latte\Engine
オブジェクト、つまり Latteテンプレートレンダラー を作成できる
LatteFactory
クラスを要求します。renderToString()
メソッドを使用して、テンプレートをファイルにレンダリングします。最初のパラメータはテンプレートへのパス、2番目は変数です。
namespace App\Model;
use Nette\Bridges\ApplicationLatte\LatteFactory;
use Nette\Mail\Mailer;
use Nette\Mail\Message;
class ContactFacade
{
public function __construct(
private Mailer $mailer,
private LatteFactory $latteFactory,
) {
}
public function sendMessage(string $email, string $name, string $message): void
{
$latte = $this->latteFactory->create();
$body = $latte->renderToString(__DIR__ . '/contactEmail.latte', [
'email' => $email,
'name' => $name,
'message' => $message,
]);
$mail = new Message;
$mail->addTo('admin@example.com') // あなたのメールアドレス
->setFrom($email, $name)
->setHtmlBody($body);
$this->mailer->send($mail);
}
}
生成されたHTMLメールを、元の setBody()
の代わりに setHtmlBody()
メソッドに渡します。また、ライブラリがテンプレートの <title>
要素から件名を取得するため、setSubject()
でメールの件名を指定する必要もありません。
設定
ContactFacade
クラスのコードには、まだ管理者メール admin@example.com
がハードコーディングされています。これを設定ファイルに移動する方が良いでしょう。どうすればよいでしょうか?
まず、ContactFacade
クラスを変更し、メールを含む文字列をコンストラクタで渡される変数に置き換えます。
class ContactFacade
{
public function __construct(
private Mailer $mailer,
private LatteFactory $latteFactory,
private string $adminEmail,
) {
}
public function sendMessage(string $email, string $name, string $message): void
{
// ...
$mail = new Message;
$mail->addTo($this->adminEmail)
->setFrom($email, $name)
->setHtmlBody($body);
// ...
}
}
そして2番目のステップは、設定でこの変数の値を指定することです。app/config/services.neon
ファイルに次のように記述します。
services:
- App\Model\ContactFacade(adminEmail: admin@example.com)
これで完了です。services
セクションの項目が多く、メールがその中で見失われていると感じる場合は、それを変数にすることができます。記述を次のように変更します。
services:
- App\Model\ContactFacade(adminEmail: %adminEmail%)
そして、app/config/common.neon
ファイルでこの変数を定義します。
parameters:
adminEmail: admin@example.com
これで完了です!