Server Requirements สำหรับ Laravel 9 นั้น มีความต้องการดังนี้
ในเครื่องจะต้องติดตั้ง node js ไว้แล้ว จากนั้นติดตั้ง laravel ได้เลยครับ
composer create-project laravel/laravel blog
แก้ไข config ไฟล์ .env
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=blog
DB_USERNAME=root
DB_PASSWORD=
ระบบ Authentication System ของ Laravel Breeze นั้นเป็นเป็นชุด Start Kit
ที่นำมาใช้กับพวกระบบพื้นฐานเช่น Register,Login,Forget Password ซึ่งสามารถใช้ coposer ติดตั้งได้ตามคำสั่งนี้
composer require laravel/breeze --dev
ติดตั้ง react js
php artisan breeze:install react
ติดตั้ง nod_module ด้วย node js เพื่อเรียกใช้ package
npm install
เมื่อก่อนใน laravel นั้นจะ laramix webpack.js มาให้ใช้ตั้งแต่ติดตั้ง เพื่อมาช่วยในการจัดการพวก css,js ต่าง แต่ปัจจุบันนั้นมี vite.js แทน
npm run dev
จากนั้นใช้คำสั่ง migrate เพื่อสร้าง database table
php artisan migrate
เปิด Terminal ใช้คำสั่ง migration เพื่อสร้าง blog table
php artisan make:migration create_blogs_table
เปิดไฟล์แก้ไฟล์ Migration ตามคำสั่งนี้
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('blogs', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('details');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('blogs');
}
};
เปิด Terminal จากนั้น run คำสั่ง migrate
php artisan migrate
เปิด Terminal จากนั้น run คำสั่งเพื่อสร้างไฟล์ Model
php artisan make:model Blog
เปิดไฟล์ App/Models/Blog.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Blog extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'title', 'details'
];
}
เปิดไฟล์ routes/web.php แก้ไขฟล์ตามนี้
<?php
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
use App\Http\Controllers\BlogController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::resource('blog', BlogController::class);
Route::get('/', function () {
return Inertia::render('Welcome', [
'canLogin' => Route::has('login'),
'canRegister' => Route::has('register'),
'laravelVersion' => Application::VERSION,
'phpVersion' => PHP_VERSION,
]);
});
Route::get('/dashboard', function () {
return Inertia::render('Dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
require __DIR__.'/auth.php';
เปิด Terminal แล้วพิมพ์คำสั่ง Artisan CLI ตามด้านล่างดังนี้
php artisan make:controller BlogController
เปิดไฟล์ app/Http/Controllers/BlogController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Inertia\Inertia;
use App\Models\Blog;
use Illuminate\Support\Facades\Validator;
class BlogController extends Controller
{
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function index()
{
$blog = Blog::all();
return Inertia::render('Blog/Index', ['blog' => $blog]);
}
/**
* Write code on Method
*
* @return response()
*/
public function create()
{
return Inertia::render('Blog/Create');
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function store(Request $request)
{
Validator::make($request->all(), [
'title' => ['required'],
'details' => ['required'],
])->validate();
Blog::create($request->all());
return redirect()->route('blog.index');
}
/**
* Write code on Method
*
* @return response()
*/
public function edit(Blog $blog)
{
return Inertia::render('Blog/Edit', [
'blogs' => $blog
]);
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function update($id, Request $request)
{
Validator::make($request->all(), [
'title' => ['required'],
'details' => ['required'],
])->validate();
Blog::find($id)->update($request->all());
return redirect()->route('blog.index');
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function destroy($id)
{
Blog::find($id)->delete();
return redirect()->route('blog.index');
}
}
ในขั้นตอนนี้ เราจะสร้างไฟล์ react js สำหรับ Index.jsx, Create.jsx และ Edit.jsx
สร้างไฟล Index.jsx ไว้ที่ resources/js/Pages/Blog/Index.jsx
import React from 'react';
import Authenticated from '@/Layouts/Authenticated';
import { Inertia } from "@inertiajs/inertia";
import { Head, usePage, Link } from '@inertiajs/inertia-react';
export default function Dashboard(props) {
const { blog } = usePage().props
function destroy(e) {
if (confirm("Are you sure you want to delete this user?")) {
Inertia.delete(route("blog.destroy", e.currentTarget.id));
}
}
return (
<Authenticated
auth={props.auth}
errors={props.errors}
header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">Blog</h2>}
>
<Head title="Blog" />
<div className="py-12">
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div className="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div className="p-6 bg-white border-b border-gray-200">
<div className="flex items-center justify-between mb-6">
<Link
className="px-6 py-2 text-white bg-green-500 rounded-md focus:outline-none"
href={ route("blog.create") }
>
Create Blog
</Link>
</div>
<table className="table-fixed w-full">
<thead>
<tr className="bg-gray-100">
<th className="px-4 py-2 w-20">No.</th>
<th className="px-4 py-2">Title</th>
<th className="px-4 py-2">Details</th>
<th className="px-4 py-2">Action</th>
</tr>
</thead>
<tbody>
{blog.map(({ id, title, details }) => (
<tr>
<td className="border px-4 py-2">{ id }</td>
<td className="border px-4 py-2">{ title }</td>
<td className="border px-4 py-2">{ details }</td>
<td className="border px-4 py-2">
<Link
tabIndex="1"
className="px-4 py-2 text-sm text-white bg-blue-500 rounded"
href={route("blog.edit", id)}
>
Edit
</Link>
<button
onClick={destroy}
id={id}
tabIndex="-1"
type="button"
className="mx-1 px-4 py-2 text-sm text-white bg-red-500 rounded">
Delete
</button>
</td>
</tr>
))}
{blog.length === 0 && (
<tr>
<td
className="px-6 py-4 border-t"
colSpan="4"
>
No contacts found.
</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
</div>
</div>
</Authenticated>
);
}
สร้างไฟล Create.jsx ไว้ที่ resources/js/Pages/Blog/Create.jsx
import React from 'react';
import Authenticated from '@/Layouts/Authenticated';
import { Head, useForm, Link } from '@inertiajs/inertia-react';
export default function Dashboard(props) {
const { data, setData, errors, post } = useForm({
title: "",
description: "",
});
function handleSubmit(e) {
e.preventDefault();
post(route("blog.store"));
}
return (
<Authenticated
auth={props.auth}
errors={props.errors}
header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">Create Blog</h2>}
>
<Head title="Blog" />
<div className="py-12">
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div className="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div className="p-6 bg-white border-b border-gray-200">
<div className="flex items-center justify-between mb-6">
<Link
className="px-6 py-2 text-white bg-blue-500 rounded-md focus:outline-none"
href={ route("blog.index") }
>
Back
</Link>
</div>
<form name="createForm" onSubmit={handleSubmit}>
<div className="flex flex-col">
<div className="mb-4">
<label className="">Title</label>
<input
type="text"
className="w-full px-4 py-2"
label="Title"
name="title"
value={data.title}
onChange={(e) =>
setData("title", e.target.value)
}
/>
<span className="text-red-600">
{errors.title}
</span>
</div>
<div className="mb-0">
<label className="">Details</label>
<textarea
type="text"
className="w-full rounded"
label="details"
name="details"
errors={errors.details}
value={data.details}
onChange={(e) =>
setData("details", e.target.value)
}
/>
<span className="text-red-600">
{errors.details}
</span>
</div>
</div>
<div className="mt-4">
<button
type="submit"
className="px-6 py-2 font-bold text-white bg-green-500 rounded"
>
Save
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</Authenticated>
);
}
สร้างไฟล Edit.jsx ไว้ที่ resources/js/Pages/Blog/Edit.jsx
import React from 'react';
import Authenticated from '@/Layouts/Authenticated';
import { Head, useForm, usePage, Link } from '@inertiajs/inertia-react';
export default function Dashboard(props) {
const { blog } = usePage().props;
const { data, setData, put, errors } = useForm({
title: blog.title || "",
details: blog.body || "",
});
function handleSubmit(e) {
e.preventDefault();
put(route("blog.update", blog.id));
}
return (
<Authenticated
auth={props.auth}
errors={props.errors}
header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">Edit Blog</h2>}
>
<Head title="Blog" />
<div className="py-12">
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div className="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div className="p-6 bg-white border-b border-gray-200">
<div className="flex items-center justify-between mb-6">
<Link
className="px-6 py-2 text-white bg-blue-500 rounded-md focus:outline-none"
href={ route("blog.index") }
>
Back
</Link>
</div>
<form name="createForm" onSubmit={handleSubmit}>
<div className="flex flex-col">
<div className="mb-4">
<label className="">Title</label>
<input
type="text"
className="w-full px-4 py-2"
label="Title"
name="title"
value={data.title}
onChange={(e) =>
setData("title", e.target.value)
}
/>
<span className="text-red-600">
{errors.title}
</span>
</div>
<div className="mb-0">
<label className="">Details</label>
<textarea
type="text"
className="w-full rounded"
label="details"
name="details"
errors={errors.details}
value={data.details}
onChange={(e) =>
setData("details", e.target.value)
}
/>
<span className="text-red-600">
{errors.details}
</span>
</div>
</div>
<div className="mt-4">
<button
type="submit"
className="px-6 py-2 font-bold text-white bg-green-500 rounded"
>
Update
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</Authenticated>
);
}
เข้าไปที่ไฟล์ Authenticated.jsx เพิ่ม link นี้ในส่วน Header
...
<NavLink href={route('blog.index')} active={route().current('blog.index')}>
Blog
</NavLink>
...
ขั้นตอนที่จำเป็นทั้งหมดเสร็จสิ้นแล้ว จากนั้นเปิด Terminal และพิมพ์คำสั่งด้านล่างแล้วกด Enter เพื่อเรียกใช้ app Laravel
php artisan serve
หากต้องการเปลี่ยน port เพียงก็ใช้คำสั่งนี้
php artisan serve --port=8081
จากนั้น run คำสั่ง สำหรับ vite.js
npm run dev
หากจะ build โปรเจคเอาไปใช้ในระดับ production ก็ใช้คำสั่งด้านล่างนี้
npm run build
เปิด Browser
http://localhost:8081