আমরা একটা সিম্পল গ্যালারি অ্যাপ তৈরি করব। যেখানে রেজিস্টার্ড ইউজার লগিন করে ইমেজ আপলোড করতে পারবে। এরপর ইমেজ গুলো গ্যালারি আকারে দেখাবে। ইমেজের সিঙ্গেল পেইজে গেলে ইমেজের ক্যাপশন দেখতে পাবে। এবং চাইলে ইমেজটি ডিলেট করতে পারবে। দুইটা পেইজ লাগবে শুধু মাত্র।
মেইন পেইজঃ
সিঙ্গেল পেইজঃ
স্টেপ ১ – প্রজেক্ট তৈরি
একটা ল্যারাভেল প্রজেক্ট তৈরি করে নিব। আমি নাম দিয়েছি Gallery। ল্যারাভেল ব্রিজ যদি না এড করে থাকেন, তাহলে ব্রিজ যুক্ত করে নিতে হবেঃ
composer require laravel/breeze --dev
php artisan breeze:install
স্টেপ ২ – মডেল ও প্রয়োজনীয় ফাইল তৈরি
ছবি গুলো আপলোড করার জন্য Image নামে একটা মডেল তৈরি করে নিব। পাশাপাশি মাইগ্রেশন এবং কন্ট্রোলার তৈরি করে নিবঃ
php artisan make:model Image -mcr
স্টেপ ৩ – ডেটাবেজ
আমরা ডেটাবেজে ইউজার আইডি, ইমেজ টাইটেল এবং ইমেজের পাথ স্টোর করব। তাই ডেটাবেজ স্কিমা এভাবে লিখবঃ
Schema::create('images', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->string('title')->nullable();
$table->string('path');
$table->timestamps();
});
এরপর ডেটাবেজ মাইগ্রেট করে নিবঃ
php artisan migrate
স্টেপ ৪ – রুট
যেহেতু আমরা রিসোর্স কন্ট্রোলার তৈরি করেছি, তাই রুট হিসেবে রিসোর্স কন্ট্রোলার ব্যবহার করতে পারব। আর যেহেতু শুধু মাত্র লগিন ইউজার ইমেজ আপলোড করতে পারবে, তাই auth মিডেলওয়ার যোগ করে দিবঃ
Route::resource('images', ImageController::class)->middleware(['auth']);
এছাড়া কেউ যদি হোম পেইজ ভিজিট করে, তাকে image.index রুটে রিডারেক্ট করে দিবঃ
Route::get('/', function () {
return redirect()->route('images.index');
});
স্টেপ ৫ – লেআউট এবং ফরম
resources/views/components ফোল্ডারের ভেতর layout.blade.php নামে একটা ফাইল তৈরি করবঃ
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com/"></script>
</head>
<body>
<nav class="bg-gray-800">
<div class="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
<div class="relative flex h-16 items-center justify-between">
<div class="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
<div class="flex flex-shrink-0 items-center">
<img class="h-8 w-auto" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=500"
alt="Your Company">
</div>
<div class="hidden sm:ml-6 sm:block">
<div class="flex space-x-4">
<a href="/"
class="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700 hover:text-white">Home</a>
<a href="/dashboard"
class="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700 hover:text-white">Dashboard</a>
</div>
</div>
</div>
</div>
</nav>
<main class="mx-auto max-w-7xl px-4 py-6 sm:px-6 lg:px-8">
{{ $slot }}
</main>
</body>
</html>
ইমেজ আপলোড এবং আপলোড করা ইমেজ গুলো আমরা হোমপেইজেই দেখাবো। welcome.blade.php নামে ডিফল্ট ভাবে একটা ফাইল তৈরি থাকে। আমরা ঐটাকেই ব্যবহার করব। resources/views/welcome.blade.php ফাইলের কোড রিপ্লেস করে এভাবে লিখবঃ
<x-layout>
@if (session('success'))
<div class="p-4 mb-4 text-sm text-blue-800 rounded-lg bg-blue-50 ">
{{ session('success') }}
</div>
@endif
<h1 class="text-center text-3xl font-semibold my-5">Upload Image</h1>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('images.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="grid grid-cols-1 md:grid-cols-3 gap-10">
<div class="mb-5">
<input type="text" name="title" id="title"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
placeholder="Image Title (optional)" />
</div>
<div class="mb-5">
<input id="image" name="image" type="file"
class="block w-full text-xl text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50">
<p class="mt-1 text-sm text-gray-500 dark:text-gray-300" id="file_input_help"> JPEG, PNG, JPG or GIF
(MAX. 2048byte).</p>
</div>
<div class="mb-5">
<button type="submit"
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-10 py-2.5 me-2 mb-2 ">Upload</button>
</div>
</div>
</form>
<h1 class="text-center text-3xl font-semibold my-5">My Gallery</h1>
@if ($images->isEmpty())
<p>No images found.</p>
@else
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
@foreach ($images as $image)
<div>
<a href="{{ route('images.show', $image) }}">
<img src="{{ asset('storage/' . $image->path) }}"
class="object-cover object-center w-full h-40 max-w-full rounded-lg hover:opacity-70"
alt="{{ $image->title }}">
</a>
</div>
@endforeach
</div>
@endif
</x-layout>
সিঙ্গেল ইমেজ দেখানোর জন্য resources/views ফোল্ডারের ভেতর single.blade.php তৈরি করে এভাবে লিখবঃ
<x-layout>
<div class=" p-5 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
<img class="rounded-t-lg object-center mx-auto hover:opacity-80" src="{{ asset('storage/' . $image->path) }}"
alt="{{ $image->title }}" />
<div class="flex justify-between items-center p-4">
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Image Caption:
{{ $image->title }}</h5>
<form action="{{ route('images.destroy', $image) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit"
class="focus:outline-none text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2">Delete</button>
</form>
</div>
</div>
</x-layout>
স্টেপ ৬ – ইমেজ আপলোড করা এবং আপলোডকৃত ইমেজ গুলো দেখানো
App/Http/Controllers/ImageController.php ফাইল ওপেন করব। index
মেথডে সব গুলো ইমেজ রিটার্ণ করবঃ
public function index()
{
$images = Image::all();
return view('welcome', compact('images'));
}
ইমেজ আপলোড করার জন্য store মেথডের কোড এভাবে লিখবঃ
public function store(Request $request)
{
$request->validate([
'title' => 'nullable|string|max:255',
'image' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048',
]);
$path = $request->file('image')->store('images', 'public');
Auth::user()->images()->create([
'title' => $request->input('title'),
'path' => $path,
]);
return redirect()->route('images.index')->with('success', 'Image uploaded successfully!');
}
ইমেজ গুলো স্টোর হবে storage > app > public > images ফোল্ডারে। ডেটাবেজে image/image_name অংশটা স্টোর করে রাখব।
এখন আমরা চাইলে ইমেজ সিলেক্ট করে আপলোড করতে পারব। হোমপেইজে ইমেজ গুলো দেখাবে। যে কোন ইমেজে ক্লিক করে ওপেন করলে সিঙ্গেল পেইজে ইমেজ দেখাবে। যেখানে আমরা একটা ডিলেট বাটন যোগ করেছি।
ImageController.php ফাইলে destroy মেথড এভাবে লিখবঃ
public function destroy(Image $image)
{
Storage::disk('public')->delete($image->path);
$image->delete();
return redirect()->route('images.index')->with('success', 'Image deleted successfully!');
}
হয়ে গেলো সুন্দর একটা ইমেজ গ্যালারি অ্যাপ! প্রজেক্ট কোড গিটহাবে পাওয়া যাবে। ল্যারাভেল নিয়ে অন্যান্য লেখা গুলো পাওয়া যাবে বাংলায় ল্যারাভেল টিউটোরিয়াল পেইজে।
একটা ওপেন সোর্স ল্যারাভেল প্রজেক্ট কিভাবে কাজ করা যায়, তা নিয়ে বিস্তারিতঃ ওপেন সোর্স ল্যারাভেল প্রজেক্ট ব্যবহার করা