Laravel PHP framework එකේ නවතම version එක වන Laravel 12 සමඟ modern web applications සාදන්නේ කොහොමද? අද අපි ඉගෙන ගන්නේ Laravel 12 හි Blade templating engine එක භාවිතා කරමින් සම්පූර්ණ CRUD (Create, Read, Update, Delete) system එකක් සාදන ආකාරයයි.
CRUD Operations කියන්නේ මොකක්ද?
CRUD(Create, Read, Update, Delete) යනු වෙබ් application එකක මූලික operations හතරයි:
- Create - නව data records එකතු කිරීම
- Read - database එකේ ඇති data පෙන්වීම
- Update - පවතින data වෙනස් කිරීම
- Delete - අනවශ්ය data ඉවත් කිරීම
Laravel 12 හි විශේෂ ගුණාංග සහ ප්රධාන වෙනස්කම් මොනවාද?
- Performance - කලින් versions වලට වඩා 30% පමණ වේගවත්
- Enhanced Security - වැඩි දියුණු කළ ආරක්ෂක පද්ධති
- Modern PHP Support - PHP 8.3+ සහාය
- Improved Blade Engine - වැඩිදියුණු කළ template engine එක
👉 How to install Laravel (Laravel install කරන ආකාරය) : https://blogs.teknyo.lk/all-the-new-features-and-updates-you-need-to-know-about-laravel-12
අපි සරල Blog Application එකක් සාදන ආකාරය බලමු .
Create Laravel Project
අපි මුලින්ම අලුත් Laravel project එකක් create කරගමු.
composer create-project laravel/laravel:^12.0 blog-app
cd blog-app
ඉන්පසු ඔබ කැමති code editor එකකින් project එක open කරගන්න. xampp හී phpmyadmin වෙත ගොස් අලුත් database එකක් create කර එයට අදාල database connection details ටික පහත ආකාරයට .env file එකෙහි දමන්න.
Database Configuration
.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog_app
DB_USERNAME=your_username
DB_PASSWORD=your_password

අපි මුලින්ම Post එකට අදාල Migration, Model සහ Controller ටික හදාගමු.
php artisan make:model Post :- අවශය Model එක පමණක් සාදාගත හැක.
php artisan make:model Post -m :- අවශය Model එක සමග එයට අදාල Migration file එකද සාදාගත හැක.
php artisan make:model Post -mc :- අවශය Model එක, Migration file එක සහ Controller එක සාදාගත හැක.
php artisan make:model Post -mcr :- අවශය Model එක, Migration file එක සහ CRUD එකට අදාලව functions structure එකත් සමග Controller එක සාදාගත හැක.
-m :- Migration
-c :- Controller
-r :- Resources
👉 වැඩිදුර විස්තර සදහා :- https://laravel.com/docs/12.x
Model සහ Migration
මේ සදහා පහත command එක භාවිතා කරන්න
php artisan make:model Post -m
දැන් අපි post table එකට අදාල fields ටික migration file එකට add කරගමු
database/migrations/create_posts_table.php
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->string('author');
$table->timestamps();
});
}
app/Models/Post.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = [
'title',
'content',
'author'
];
}
කලින් අපි සාදාගත් migration එක භාවිතයෙන් database table එක සාදා ගනිමු.
php artisan migrate
Controllers
ඊලගට අපි post controller එක සාදා ගනිමු. ඒ සදහා පහත command එක භාවිතා කල හැක.
php artisan make:controller PostController -r
app/Http/Controllers/PostController.php
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index()
{
$posts = Post::latest()->paginate(10);
return view('posts.index', compact('posts'));
}
public function create()
{
return view('posts.create');
}
public function store(Request $request)
{
$request->validate([
'title' => 'required|max:255',
'content' => 'required',
'author' => 'required|max:100'
]);
Post::create($request->all());
return redirect()->route('posts.index')
->with('success', 'Post Created Successful');
}
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
public function edit(Post $post)
{
return view('posts.edit', compact('post'));
}
public function update(Request $request, Post $post)
{
$request->validate([
'title' => 'required|max:255',
'content' => 'required',
'author' => 'required|max:100'
]);
$post->update($request->all());
return redirect()->route('posts.index')
->with('success', 'Post Updated Successful');
}
public function destroy(Post $post)
{
$post->delete();
return redirect()->route('posts.index')
->with('success', 'Post Deleted Successful');
}
}
Routes
Post CRUD එකට අදාල routes ටික සකස් කරගමු
routes/web.php
<?php
use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return redirect()->route('posts.index');
});
Route::resource('posts', PostController::class);
Blade View Files
ඊලගට අපි data insert, update කරන්න අවශය UI ටික හදාගමු. මේ සදහා Bootstrap framework එක භාවිතා කරමු.
👉 https://getbootstrap.com/docs/5.0/getting-started/introduction/
resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title', 'Blog Application')</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="{{ route('posts.index') }}">
Blog App
</a>
</div>
</nav>
<div class="container mt-4">
@if(session('success'))
<div class="alert alert-success alert-dismissible fade show">
{{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
@endif
@yield('content')
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Posts List View
resources/views/posts/index.blade.php
@extends('layouts.app')
@section('title', 'All Posts')
@section('content')
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>All Blog Posts</h2>
<a href="{{ route('posts.create') }}" class="btn btn-success">
Add New Post
</a>
</div>
@if($posts->count() > 0)
<div class="row">
@foreach($posts as $post)
<div class="col-md-6 mb-4">
<div class="card h-100">
<div class="card-body">
<h5 class="card-title">{{ $post->title }}</h5>
<p class="card-text">
{{ Str::limit($post->content, 100) }}
</p>
<p class="text-muted">
<small> {{ $post->author }} | {{ $post->created_at->format('Y-m-d') }}</small>
</p>
</div>
<div class="card-footer">
<div class="btn-group w-100">
<a href="{{ route('posts.show', $post) }}" class="btn btn-info btn-sm">
View
</a>
<a href="{{ route('posts.edit', $post) }}" class="btn btn-warning btn-sm">
Edit
</a>
<form action="{{ route('posts.destroy', $post) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm"
onclick="return confirm('Are you sure you want to delete this post?')">
Delete
</button>
</form>
</div>
</div>
</div>
</div>
@endforeach
</div>
<div class="d-flex justify-content-center">
{{ $posts->links() }}
</div>
@else
<div class="text-center py-5">
<p class="fs-4">No Posts Available</p>
<a href="{{ route('posts.create') }}" class="btn btn-primary">
Create Your First Post
</a>
</div>
@endif
@endsection

Create Post Form
resources/views/posts/create.blade.php
@extends('layouts.app')
@section('title', 'Create New Post')
@section('content')
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h4>Create New Blog Post</h4>
</div>
<div class="card-body">
<form action="{{ route('posts.store') }}" method="POST">
@csrf
<div class="mb-3">
<label for="title" class="form-label">Post Title</label>
<input type="text" class="form-control @error('title') is-invalid @enderror"
id="title" name="title" value="{{ old('title') }}" required>
@error('title')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="author" class="form-label">Author Name</label>
<input type="text" class="form-control @error('author') is-invalid @enderror"
id="author" name="author" value="{{ old('author') }}" required>
@error('author')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="content" class="form-label">Post Content</label>
<textarea class="form-control @error('content') is-invalid @enderror"
id="content" name="content" rows="8" required>{{ old('content') }}</textarea>
@error('content')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="d-flex justify-content-between">
<a href="{{ route('posts.index') }}" class="btn btn-secondary">
Go Back
</a>
<button type="submit" class="btn btn-success">
Save
</button>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection

Edit Post Form
resources/views/posts/edit.blade.php
@extends('layouts.app')
@section('title', 'Edit Post')
@section('content')
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h4>Edit Post</h4>
</div>
<div class="card-body">
<form action="{{ route('posts.update', $post) }}" method="POST">
@csrf
@method('PUT')
<div class="mb-3">
<label for="title" class="form-label">Post Title</label>
<input type="text" class="form-control @error('title') is-invalid @enderror"
id="title" name="title" value="{{ old('title', $post->title) }}" required>
@error('title')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="author" class="form-label">Author Name</label>
<input type="text" class="form-control @error('author') is-invalid @enderror"
id="author" name="author" value="{{ old('author', $post->author) }}" required>
@error('author')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="content" class="form-label">Post Content</label>
<textarea class="form-control @error('content') is-invalid @enderror"
id="content" name="content" rows="8" required>{{ old('content', $post->content) }}</textarea>
@error('content')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="d-flex justify-content-between">
<a href="{{ route('posts.index') }}" class="btn btn-secondary">
Go Back
</a>
<button type="submit" class="btn btn-warning">
Update
</button>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection

Single Post View
resources/views/posts/show.blade.php
@extends('layouts.app')
@section('title', $post->title)
@section('content')
<div class="row justify-content-center">
<div class="col-md-10">
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h2>{{ $post->title }}</h2>
<div class="btn-group">
<a href="{{ route('posts.edit', $post) }}" class="btn btn-warning btn-sm">
Edit
</a>
<form action="{{ route('posts.destroy', $post) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm"
onclick="return confirm('Are you sure you want to delete this post?')">
Delete
</button>
</form>
</div>
</div>
<div class="card-body">
<div class="mb-3">
<strong>Author:</strong> {{ $post->author }}
<span class="text-muted mx-2">|</span>
<strong>Published:</strong> {{ $post->created_at->format('F d, Y') }}
@if($post->updated_at != $post->created_at)
<span class="text-muted mx-2">|</span>
<strong>Updated:</strong> {{ $post->updated_at->format('F d, Y') }}
@endif
</div>
<hr>
<div class="content">
{!! nl2br(e($post->content)) !!}
</div>
</div>
<div class="card-footer">
<a href="{{ route('posts.index') }}" class="btn btn-primary">
All Posts
</a>
</div>
</div>
</div>
</div>
@endsection

දැන් අපි CRUD එකට අදාල සියලුම දේවල් කරල ඉවරයි. අපේ application එක run කරල බලමු. ඒ සදහා පහත command එක run කරල
php artisan serve
Browser එකේ http://localhost:8000
වලට ගිහින් application එක open කරල බලන්න.
We're done. 🎉 Happy Coding! 🧑💻
👉 https://github.com/hushanthaK/laravel-12-blog-app
Laravel development ගැන වැඩි විස්තර සඳහා Laravel official documentation එක refer කරන්න. තවත් මේ වගේ tutorials සහ tips සඳහා අපේ blog එකත් එක්ක එකතු වෙලා ඉන්න.