ساخت فرم تماس با ما ساده در لاراول

میتونم بگم تقریبا هر مشتری میاد چنین قابلیتی رو از سایتش انتظار داره(حتی با اینکه اکثرا هیچوقت کاربری ازش استفاده نمیکنه :) ) ولی خب چه کنیم مشتریه دیگه میگه بزنیم ما هم میزنیم.
اما من میخام اینجا بنویسم روتین من برای ساخت فرم تماس با ما چیه.

هدف: ساخت یه فرم تماس با ما که نام و شماره تماس و متن از کاربر میگیره و ذخیره میکنه و برای صاحب وبسایت ایمیل میفرسته.

برای شروع یه مدل میسازم.

php artisan make:model Message -m

در میگریشن ایجاد شده سه تا ستون اضافه میکنم برای نام, شماره تماس و متن پیام.

Schema::create('messages', function (Blueprint $table) {
     $table->increments('id');
     $table->string('name');
     $table->string('phone');
     $table->text('message');
     $table->timestamps();
 });

و متغیر $fillable رو برای مدل مینویسم.

protected $fillable = [
     'name',
     'phone',
     'message'
 ];

کنترلر لازم رو هم ایجاد میکنم

php artisan make:controller ContactController

داخلش دو تا متد به نام
show و send
میسازم و تابع show رو به این شکل مینویسم.

public function show()
 {
     return view("index");
 }

و روت هاش رو هم تعریف میکنم.

Route::get('/', '[email protected]')->name("contact.show");
Route::post('/send', '[email protected]')->name("contact.send");

یه view جدید به نام index حاضر میکنم که داخلش یه فرم قرار داره.

https://gist.github.com/amir9480/3d44b19cff050971a7d2f835fc2698e3
سشن
success
رو برای ارسال
flash message
از کنترلر استفاده میکنم.

برای نوشتن متد ارسال اول یه
Request
میسازم.

php artisan make:request ContactRequest

و rules رو به این شکل مینویسم.

return [
    'name' => 'required|string|max:60',
    'phone' => 'required|string|max:20',
    'message' => 'required|string'
];

همچنین attributes رو هم برای دو phone و message داخل کلاس تعریف میکنم.

public function attributes()
 {
     return [
         'phone' => 'شماره تماس',
         'message' => 'پیام',
     ];
 }

و در نهایت داخل کنترلر send رو به این شکل تعریف میکنم.

public function send(ContactRequest $request)
 {
     Message::create($request->all());
     return redirect()->back()->with(['success' => 'پیام شما با موفقیت ارسال شد.']);
 }

تا این جای قسمت ذخیره کردن پیام ها رو زدیم که شما میتونین سمت ادمین سایت لیست پیام ها رو به صاحب وبسایت نشون بدین.
ولی خب ما میخاهیم برای صاحب وبسایت ایمیل ارسال بشه که آقا برات پیام اومده.
برای شروع اول یه پکیج به پروژه م اضافه میکنم که بتونم ایمیل هایی که ارسال میشه رو مشاهده کنم.

https://github.com/themsaid/laravel-mail-preview/

حتما بخونین چجوری کار میکنه.

composer require themsaid/laravel-mail-preview

بعد نصب این دستور رو وارد میکنم که کانفیگ درست بشه.

php artisan vendor:publish --provider="Themsaid\MailPreview\MailPreviewServiceProvider"

و داخل فایل .env مقدار MAIL_DRIVER رو تغییر میدم.

MAIL_DRIVER=preview

برای شروع ایمیل زدن یه
mail
جدید میسازم.

php artisan make:mail Contact --markdown=emails.contact

و کلاس رو به این شکل تغییر میدم.

https://gist.github.com/amir9480/2c306785978bf85e02dbc878999a6e38

و ویو emails/contact رو به این شکل تغییر میدم.

@component('mail::message')
# پیام فرم تماس با ما
این ایمیل به صورت خودکار ارسال شده است.

## مشخصات فرستنده
### نام : {{ $name }}
### شماره تماس : {{ $phone }}

@component('mail::panel')
 {{ $message }}
@endcomponent

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

برای ادامه داخل فولدر
config
یه فایل جدید به نام
contact.php
میسازم و به این شکل مینویسمش
شما میتونین از همون app.php استفاده کنین فرقی نداره.

<?php
return [
    'email' => env('CONTACT_EMAIL')
];

و داخل فایل .env این رو اضافه میکنم.

[email protected]

به جای این ایمیل بعدا ایمیل مشتریتون رو بنویسین.
و در نهایت متد ارسال کنترلرم رو به این شکل اصلاح میکنم.

public function send(ContactRequest $request)
 {
     Mail::to(config("contact.email"))
         ->send(new Contact(Message::create($request->all())));
     return redirect()->back()->with(['success' => 'پیام شما با موفقیت ارسال شد.']);
 }

حالا بعد اینکه فرم رو ارسال کنید پکیجی که اضافه کردیم یه لینک بهتون نمایش داده میشه.

در پایان من از اسپمر ها خوشم نمیاد.
مشتری هم از اسپمر ها خوشش نمیاد.
شما چطور؟
با کمک Recaptcha سعی میکنم تا جای ممکن اسپم واسه مشتری فرستاده نشه.
اول پکیج Recaptcha گوگل رو اضافه میکنم.

https://github.com/google/recaptcha
composer require google/recaptcha

فایل کانفیگم رو به این شکل تغییر میدم.

<?php

return [
    'email' => env('CONTACT_EMAIL'),
    'recaptcha' => [
        'site' => env('RECAPTCHA_SITE'),
        'secret' => env('RECAPTCHA_SECRET'),
    ]
];

و این ها رو به فایل .env اضافه میکنم.

RECAPTCHA_SITE=
RECAPTCHA_SECRET=

باید توی سایت https://www.google.com/recaptcha سایت خودتون رو ثبت کنید.
و مقادیر
Site Key و Secret Key
جلوی اینا قرار بدین.
بعد داخل
app/Providers/AppServiceProvider
این خطوط رو اضافه میکنم تا ولیدیتور برای
Recaptcha
ساخته شه.

use ReCaptcha\ReCaptcha;
use Illuminate\Support\Facades\Validator;
.
.
public function boot()
 {
 Validator::extendImplicit('recaptcha', function ($attribute, $value, $parameters, $validator) {
 $recaptcha = new ReCaptcha(config("contact.recaptcha.secret"));
 $response = $recaptcha->verify($value, request()->ip());
 if ($response->isSuccess()) {
 return true;
 }
 return false;
 });
 }

و داخل فایل translations validation.php این خط رو اضافه میکنم.

'recaptcha' => 'لطفا بر روی گزینه من یک ربات نیستم کلیک کنید.',

این خط کد رو به
rules
داخل کلاس
Request
که نوشته بودم اضافه میکنم.

'g-recaptcha-response' => 'recaptcha'

و در نهایت داخل
view
این خط کد رو به انتهای فرمم اضافه میکنم.

<div data-sitekey="{{ config('contact.recaptcha.site') }}"></div>

و این فایل جاوا اسکریپت رو هم اضافه میکنم.

<script src="https://www.google.com/recaptcha/api.js?hl=fa"></script>

و نتیجه کار بعد اینکه کاربر گزینه من یک ربات نیستم رو کلیک نکرد ولی پیام فرستاد.

سورس کد هم اینجا در دسترس هست.

https://github.com/amir9480/laravel-contact-form-sample

سایر نوشته هام.

https://virgool.io/@amiralizadeh9480/%D8%B3%D8%A7%D8%AE%D8%AA-%DA%A9%D9%88%D8%AA%D8%A7%D9%87-%DA%A9%D9%86%D9%86%D8%AF%D9%87-%D9%84%DB%8C%D9%86%DA%A9-%D8%A8%D8%A7-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84-vcrlsheusa5f
https://virgool.io/Software/%D8%B3%D8%A7%D8%AE%D8%AA-crud-%D8%A8%D8%A7-%D9%84%D8%A7%D8%B1%D9%88%D8%A7%D9%84-%D9%88-vue-oa3s5ageyafv
https://virgool.io/JavaScript8/%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-%D9%81%D8%A7%DB%8C%D9%84-%D9%87%D8%A7%DB%8C-%D8%AA%D8%B1%D8%AC%D9%85%D9%87-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84-%D8%AF%D8%B1-%D8%AC%D8%A7%D9%88%D8%A7-%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA-mxxpowoydz0z