Laravel Framework Basics
Laravel Framework Basics পর্ব-৩: Laravel Routes
Laravel Route কি?
সাধারণত ইংরেজি শব্দ route যাকে অনেক সময় আমরা বাংলায় বলি রুট যার অর্থ দাঁড়ায় গন্তব্যস্থলে পৌঁছানোর রাস্তা। আর Laravel Application এ route হচ্ছে URL থেকে request গ্রহণ করে এবং application কে resource এর জন্য নির্দেশনা প্রদান করে। আরো সহজ ভাবে বলা যায় route হল আপনার অ্যাপ্লিকেশনের একটি request এর বিপরীতে কোন URL টি hit হবে? বা কোথায় থেকে কি response করবে তা নির্ধারণের একটি উপায়। Laravel এ সব route গুলো routes ফোল্ডারে তৈরী করা থাকে। এর মধ্যে web application এর route সমূহ routes/web.php তে লিখা হয়। এবং API এর জন্য route সমূহ routes/api.php তে লিখা হয়। Laravel Framework এ route এর সবচেয়ে বড় সুবিধা হচ্ছে আপনি এক যায়গা থেকেই সমস্ত route কে নিয়ন্ত্রণ করতে পারবেন অর্থাৎ পরবর্তিতে route সম্পর্কিত যেকোনো ধরনের পরিবর্তন এখান থেকেই করতে পারবেন।
Laravel Route এর প্রাথমিক ধারণা
Laravel Route লিখার আগে আপনাকে PHP Anonymous Function, Closure এবং PHP Class এর Static Method সম্পর্কে ধারণা থাকা দরকার, আমরা ধরে নিলাম আপনি এই গুলো জানেন। তো আসা যাক কিভাবে route দিয়ে URL Request গুলো Manage করতে পারি। ধরুন আমাদের Web Application এ তিনটি পেজ আছে , সেগুলো যথাক্রমে Home, About এবং Contact. এখন Web Application ব্যবহারকারী এই তিনটি পেজ এর মধ্যে যাকে request করবে শুধু সংশ্লিষ্ট পেজটি response করবে। অনেকটা নিচের URL এর মত:
for Home page:
http://localhost:8000/
for About page:
http://localhost:8000/about
for Contact page:
http://localhost:8000/contact
এখন এই তিনটি URL Request এর জন্য আপনি Laravel এর routes/web.php ফাইল এ ঠিক নিচের মত করে লিখতে পারেন।
Route::get('/', function (){ echo "<h2>This is Home Page</h2>; }); Route::get('/about', function (){ echo "<h2> This is About Page</h2>"; }); Route::get('/contact', function (){ echo "<h2> This is Contact Page</h2>"; });
এখন আপনি আপনার ব্রাউজার এর Address bar এ http://localhost:8000 , http://localhost:8000/about এবং http://localhost:8000/contact লিখে hit করুন, তাহলে আপনার route ঠিক নিম্নের screenshot গুলোর মতো রেজাল্ট দেখাবে:
নোট: অবশ্যই ” php artisan serve ” command দিয়ে server run রাখতে ভুলবেননা।
ব্যাখ্যা: উপরোক্ত উদাহরণে আমরা Route class এর get() মেথডকে call করেছি। Route Class এর get() মেথডটি দুইটি Argument গ্রহণ করে। প্রথম Argument হিসেবে URL Path অর্থাৎ যেই URL এ hit করবে সেটি, এবং দ্বিতীয় Argument হিসেবে একটি Anonymous Function সাথে closure থাকতে পারে। যেমনঃ উপরোক্ত উদাহরণে আমাদের Home URL এর জন্য প্রথম আর্গুমেন্ট হিসেবে শুধু forward slash ( / ) ব্যবহার করি , যার দ্বারা Laravel route রুট ডোমেইনকে নির্দেশ করে। একই ভাবে About URL এর জন্য forward slash সাথে about (/about) এবং Contact URL এর জন্য forward slash সাথে contact(/contact) লিখি। আর তিনটি URL এর জন্যই দ্বিতীয় Argument হিসেবে একটি Anonymous Function ব্যবহার করি যার দ্বারা action কি হবে তা নির্ধারণ করি।
Available Router Methods
Laravel 9.0 এ মূলত ছয় ধরণের মেথড রয়েছে। যা দিয়ে আপনি বিভিন্ন ধরণের HTTP Request এবং Response এর কাজ গুলো করতে পারেন।
Route::get($uri, $callback); Route::post($uri, $callback); Route::put($uri, $callback); Route::patch($uri, $callback); Route::delete($uri, $callback); Route::options($uri, $callback); Route::match(['http_method_1','http_method_n'], $uri, $callback); Route::any($uri, $callback);
কখনো কখনো আপনাকে এমন একটি route তৈরি করতে হতে পারে যা একাধিক বা ভিন্ন ধরণের HTTP রিকোয়েস্ট কে গ্রহণ করে। এই কাজটি আপনি match method ব্যবহার করে করতে পারেন। অথবা, আপনি এমন একটি route তৈরি করতে পারেন যা যেকোনো পদ্ধতি ব্যবহার করে সমস্ত HTTP রিকোয়েস্ট কে গ্রহণ করে। নিচের উদাহরণটি দেখুন:
Route::match(['get', 'post'], '/', function () { // }); Route::any('/', function () { // });
Dependency Injection
আপনি চাইলে আপনার route এর callback ফাঙ্কশনের প্যারামিটারে আপনার route এর জন্য প্রয়োজনীয় লারাভেলের যেকোনো dependencies ক্লাস লাইব্রেরি এর type-hint সুবিধা ব্যবহার করতে পারেন। ঘোষিত dependencies ক্লাসটি স্বয়ংক্রিয়ভাবে লোড হবে এবং route এ ব্যবহারের সুযোগ হবে এবং Laravel service container দ্বারা কলব্যাক ফাঙ্কশনে ব্যবহার করা যাবে। উদাহরণস্বরূপ, আপনি আপনার route কলব্যাকে বর্তমান HTTP Request স্বয়ংক্রিয়ভাবে ব্যবহার করার জন্য Illuminate\Http\Request ক্লাসের type-hint করতে পারেন:
use Illuminate\Http\Request; Route::get('/users', function (Request $request) { // ... });
CSRF Protection
মনে রাখবেন, route ফাইলে সংজ্ঞায়িত POST, PUT, PATCH বা DELETE route এর দিকে পয়েন্ট করা যেকোন HTML ফর্মে অবশ্যই একটি CSRF টোকেন অন্তর্ভুক্ত করা উচিত। অন্যথায়, রিকোয়েস্ট রিজেক্ট করা হবে. আপনি CSRF ডকুমেন্টেশনে CSRF প্রটেকশন সম্পর্কে আরও পড়তে পারেন:
<form method="POST" action="/profile"> @csrf ... </form>
Redirect Routes
আপনি যদি একটি URL কে অন্য একটা URL এ redirect করতে চান , তাহলে আপনি লারাভেলের Route::redirect method টি ব্যবহার করতে পারেন। আর এর সিনটেক্স তা ঠিক নিচের মতো করে হবে:
Route::get('/here', function () { return "You're here!"; }); Route::get('/there', function () { return "You're there!"; }); Route::redirect('/here', '/there');
বাই ডিফল্ট Route::redirect মেথড টি ৩০২ স্টেটাস কোড রিটার্ন করে। তবে আপনি চাইলে এটিকে কাস্টমাইজ করতে পারেন।
Route::redirect('/here', '/there', 301);
View Routes
যদি আপনার route শুধু মাত্র একটা view রিটার্ন প্রয়োজন হয়, তাহলে আপনি Route::view এই method টি ব্যবহার করতে পারেন। অনেকটা redirect method এর মতো, অর্থাৎ আপনাকে একটা সম্পূর্ণ route বা controller ডিফাইন করতে হবেনা । view method এর মধ্যে প্রথম আর্গুমেন্ট টি হবে একটি URI এবং দ্বিতীয় আর্গুমেন্ট টি হবে একটি view file । এছাড়াও, আপনি অপশনাল হিসেবে তৃতীয় argument হিসেবে view তে একটা array পাস করতে পারেন:
Route::view('/welcome', 'welcome'); Route::view('/welcome', 'welcome', ['name' => 'Taylor']);
Laravel Route Parameter নিয়ে কাজ
অবশ্যই, কখনও কখনও আপনাকে আপনার route মধ্যে URI এর segment গুলিকে receive বা capture করতে হবে। এটি করার জন্য Laravel Route এ চারটি উপায় আছে যার মাধ্যমে আপনি URL- এর মাধ্যমে পাঠানো Parameter গুলিকে Capture করতে পারেন।
- Required Parameters
- Optional Parameters
- Regular Expression Constraints
- Global Constraints
Required Parameters
অর্থাৎ আপনার URL এ অবশ্যই Parameter থাকতে হবে। ধরুন আপনাকে URL থেকে ইউজারদের নাম capture করতে হতে পারে । আপনাকে route এ Parameter define করে তা করতে হবে । একটি উদাহরণ দিয়ে যাক ।
// get the parameter of name Route::get('students/{name}', function($name) { echo 'Students Name is ' . $name; });
এখন আপনার ব্রাউজারে, আপনি নিচের মতো করে student name এ access করতে পারেন।
http://localhost:8000/students/Masud
আর যদি URL এ কোনো Parameter না দেন বা খালি রাখেন, Laravel আপনাকে নিচের Message টি দিবে :
"Sorry, the page you are looking for could not be found."
একইভাবে আপনি একাধিক Required Parameter পাঠাতে পারেন, নিচের উদাহরণ লক্ষ্য করুন :
// get the parameter of name Route::get('students/{name}/{age}', function($name,$age) { echo "Students Name is $name and he is $age years old"; });
এখন আপনার ব্রাউজারে, আপনি নিচের মতো করে student name এবং তার age এ access করতে পারেন।
http://localhost:8000/students/Masud/30
এক্ষেত্রে আপনি চাইলে সরাসরি Request class এর Object দিয়েও data রিসিভ গ্রহণ পারেন। নিচের উদাহরণ লক্ষ্য করুন :
use Illuminate\Http\Request; Route::get('/user/{name}', function (Request $request) { return "User name: ".$request->name; });
Parameters & Dependency Injection
যদি আপনার route এ dependencies থাকে তখন আপনি যদি চান যে Laravel service container টি স্বয়ংক্রিয়ভাবে আপনার route এর callback এ চলে আসুক , তাহলে আপনার dependencies গুলোর পরে আপনার route এর parameter গুলি রাখা উচিত। নিচের উদাহরণ দেখুন :
use Illuminate\Http\Request; Route::get('/user/{id}/{name}', function (Request $request, $id, $name) { return "User Id : $id and Name: $name"; });
Optional Parameters
আপনি যদি আপনার URL এ এমন কিছু Parameter পাঠাতে চান , যা থাকতেও পারে আবার নাও থাকতে পারে। এই সব ক্ষেত্রে আপনাকে Laravel এর Optional Parameter System ব্যবহার করতে হবে। তখন URL এ এই প্যারামিটার গুলির থাকার আবশ্যকীয় নয়। আর এই Parameter গুলির নামের পরে “?” চিহ্ন দিতে হয়। নিম্নের কোডটি লক্ষ্য করুন :
Route::get('/user/{name?}', function ($name = null) { return $name; }); Route::get('/user/{name?}', function ($name = 'Masud Alam') { return $name; });
এখন আপনার URL এ যেই Parameter পাঠাবেন সেটা দেখাবে, অন্যথা default Parameter Masud Alam দেখাবে। নিম্নের ছবিতে লক্ষ্য করুন :
একইভাবে আপনি একাধিক Optional Parameter পাঠাতে পারেন, নিচের উদাহরণ লক্ষ্য করুন :
Route::get('users/{name?}/{age?}', function($name="Masud Alam",$age=30) { echo "User Name is $name and He is $age years Old"; });
এখন আপনার ব্রাউজারে, আপনি নিচের মতো করে user name এবং তার age এ access করতে পারেন।
http://localhost:8000/users
Regular Expression Constraints
এই পদ্ধতিতে route parameter গুলোকে where method ব্যবহার করে একটা নির্দিষ্ট ফরম্যাট এ ফিক্সড বা সীমাবদ্ধ করে দিতে পারেন। আর where method টি route এর জন্য শুধু মাত্র regular expression দিয়ে সঙ্গায়িত প্যারামিটার গুলো গ্রহণ করতে বাধ্য করবে।
Route::get('/user/{name}', function ($name) { return "Name: ".$name; })->where('name', '[A-Za-z]+'); //accept only alphabetical value Route::get('/user/{id}', function ($id) { return "Id: ".$id; })->where('id', '[0-9]+'); //accept only numerical value Route::get('/user/{id}/{name}', function ($id, $name) { return "Id: $id and Name: $name"; })->where(['id' => '[0-9]+', 'name' => '[a-z]+']); //Accept both Alphabetical and Numerical Value
তবে আপনি চাইলে Regex Pattern ব্যবহারের পরিবর্তে লারাভেলের বিদ্যমান ফাঙ্কশন গুলোও ব্যবহার করতে পারেন।
Route::get('/user/{id}/{name}', function ($id, $name) { return "Welcome $name, Your Id is: $id"; })->whereNumber('id')->whereAlpha('name'); Route::get('/user/{name}', function ($name) { return "Welcome $name"; })->whereAlphaNumeric('name'); Route::get('/user/{id}', function ($id) { return "Welcome , Your Id is: $id"; })->whereUuid('id');
Global Constraints
এই পদ্ধতিতে আপনি একটা নির্দিষ্ট route parameter কে সবসময় একটা নির্দিষ্ট ফরমেট এ রিটার্ন করতে পারেন। এর জন্যে আপনাকে App\Providers\RouteServiceProvider class: এর boot Method এ pattern মেথড ব্যবহার করতে পারেন।
/** * Define your route model bindings, pattern filters, etc. * * @return void */ public function boot() { Route::pattern('id', '[0-9]+'); }
প্যাটার্নটি যখন নির্দিষ্ট করে দিবেন, এটি স্বয়ংক্রিয়ভাবে সেই প্যারামিটার নাম ব্যবহার করে সব route এ প্রয়োগ হবে :
Route::get('/user/{id}', function ($id) { // Only executed if {id} is numeric... });
Encoded Forward Slashes
একটা বিষয় লক্ষ্য করে দেখবেন , Laravel routing component গুলো প্যারামিটার এ সব ধরণের ক্যারেক্টার একসেপ্ট করে , শুধু মাত্র forwarding slash (/) ছাড়া। কারণ এই ক্যারেক্টার (/) টি প্যারামিটার গুলো আলাদা করার জন্য ব্যবহৃত হয়। তবে আপনি চাইলে এটিকেও where condition এর মাধ্যমে এলাও করতে পারেন। তবে মনে রাখতে হবে এই কাজটি শুধু সর্বশেষ প্যারামিটার এর জন্য ব্যবহার করা যায়। নিচের উদাহরণ দেখুন।
Route::get('/search/{search}', function ($search) { return $search; })->where('search', '.*');
Named Routes
Laravel এর Named route ফীচার দিয়ে আপনি যেকোনো ছোট অথবা বড় URL কে একটা নির্দিষ নাম দিতে পারেন। এবং পরবর্তীতে route redirects সহ বহু কাজে ব্যবহার করতে পারেন। আপনি name method chaining করে একটি route এর জন্য একটি name নির্ধারণ করতে পারেন:
Route::get('/user/profile', function () { // })->name('profile');
আপনি চাইলে controller actions এর জন্য নিচের মতো করে route name গুলি নির্দিষ্ট করতে পারেন:
Route::get( '/user/profile', [UserProfileController::class, 'show'] )->name('profile');
Generating URLs To Named Routes
ধরুন আপনি একটি route লিখলেন , এবং সেটি পরবর্তীতে page redirect সহ অন্য অনেক কাজে ব্যবহার করতে চান , তাহলে আপনার জন্য সবচেয়ে সুবিধা হয় , যদি route টি কে আলাদা ভ্যারিয়েবল এ সংরক্ষণ না রেখে , এটিকে ডিক্লেয়ার এর সময় একটা Name দিয়ে দেওয়া। ব্যাপারটা অনেকটা এই রকম:
// Generating URLs... $url = route('profile'); // Generating Redirects... return redirect()->route('profile');
আর উপরোক্ত কাজটি করতে হলে , আপনাকে নিচের মতো করে route ডিক্লেয়ার করতে হবে:
Route::get('/profile/test', function () { return route("profile"); })->name('profile');
তবে আপনি চাইলে নিচের মতো করে অতিরিক্ত প্যারামিটার ও পাঠাতে পারেন।
Route::get('/profile/test', function () { return route("profile",['id' => 1, 'photos' => 'yes']); })->name('profile');
এমনকি আপনি চাইলে view file সহ সমগ্র লারাভেলের যেকোনো জায়গায় এই Named Route ব্যবহার করতে পারেন :
<!-- named.blade.php --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Laravel Named Route</title> </head> <body> Hello {{route('profile')}} </body> </html>
//Route Defination Route::get('/profile/test', function () { return view('named'); })->name('profile');
Route Groups
ধরুন আপনি একটা customer CRUD এর কাজ করবেন , সেক্ষেত্রে আপনি চাইলে create, read, update এবং delete এর কাজ গুলোকে পৃথক পৃথক route এ declare না করে একটা গ্রুপের মধ্যে কল করতে পারবেন। নিচের উদাহরণ টি দেখুন:
Route::group([], function(){ Route::get('/create',function(){ echo "First route for Create/Insert"; }); Route::get('/read',function(){ echo "Second route for Read"; }); Route::get('/update/{id}',function($id){ echo "Third route for Update"; }); Route::get('/delete/{id}',function($id){ echo "Fourth route for Delete"; }); });
আর এই কাজটি Controller দিয়ে করতে হলে আপনার কোড টি হবে নিম্নরুপঃ
use App\Http\Controllers\UserController; Route::group([], function(){ Route::get('/create',[UserController::class, 'create']); Route::get('/read',[UserController::class, 'read']); Route::get('/update/{id}',[UserController::class, 'update']); Route::get('/delete/{id}',[UserController::class, 'delete']); });
তবে আপনি চাইলে group এ prefex ও যুক্ত করতে পারেন। নিচের উদাহরণ টি দেখুন:
Route::group(["prefix"=>"/user"], function(){ Route::get('/create',function(){ echo "First route for Create/Insert"; }); Route::get('/read',function(){ echo "Second route for Read"; }); Route::get('/update/{id}',function($id){ echo "Third route for Update"; }); Route::get('/delete/{id}',function($id){ echo "Fourth route for Delete"; }); });
আর এই কাজটি Controller দিয়ে করতে হলে আপনার কোড টি হবে নিম্নরুপঃ
use App\Http\Controllers\UserController; Route::group(["prefix"=>"/user"], function(){ Route::get('/create',[UserController::class, 'create']); Route::get('/read',[UserController::class, 'read']); Route::get('/update/{id}',[UserController::class, 'update']); Route::get('/delete/{id}',[UserController::class, 'delete']); });
এখন আপনার url গুলো নিচের মতো হবে:
http://localhost:8000/user/create http://localhost:8000/user/read http://localhost:8000/user/update/2 http://localhost:8000/user/delete/2
Route Prefixes
উপরে আপনি নিশ্চয়ই লক্ষ্য করেছেন , আমরা প্রয়োজন হলে Route Group এর মধ্যে prefix যুক্ত করতে পারি , তবে আপনি চাইলে Route::prefix এই মেথডের মাধমেও prefix যুক্ত করতে পারেন। নিচের উদাহরণ লক্ষ্য করুন :
Route::prefix('user')->group(function () { Route::get('/create',function(){ echo "First route for Create/Insert!"; }); Route::get('/read',function(){ echo "Second route for Read"; }); Route::get('/update/{id}',function($id){ echo "Third route for Update"; }); Route::get('/delete/{id}',function($id){ echo "Fourth route for Delete"; }); });
আর এই কাজটি Controller দিয়ে করতে হলে আপনার কোড টি হবে নিম্নরুপঃ
Route::prefix('user')->group(function () { Route::get('/create',[UserController::class, 'create']); Route::get('/read',[UserController::class, 'read']); Route::get('/update/{id}',[UserController::class, 'update']); Route::get('/delete/{id}',[UserController::class, 'delete']); });
এখন আপনার url গুলো নিচের মতো হবে:
http://localhost:8000/user/create http://localhost:8000/user/read http://localhost:8000/user/update/2 http://localhost:8000/user/delete/2
Route Group Controller
আপনার যদি একই controller এর অধীনে একাধিক route url থাকে তাহলে আপনি প্রত্যেকটি route এর জন্য একই controller বার বার call করার পরিবর্তে Route Group Controller পদ্ধতি ব্যবহার করতে পারেন। তখন Route Group Controller টি হবে নিম্নরূপ :
use App\Http\Controllers\UserController; Route::prefix('user') ->name('user.') ->controller(UserController::class) ->group(function () { Route::get('/create','create')->name('create'); Route::get('/read','read')->name('read'); Route::get('/update/{id}','update')->name('update'); Route::get('/delete/{id}','delete')->name('delete'); });
এখন আপনার url গুলো নিচের মতো হবে:
http://localhost:8000/user/create http://localhost:8000/user/read http://localhost:8000/user/update/2 http://localhost:8000/user/delete/2
Note: তবে এই সুবিধাটি শুধু মাত্র লারাভেল ৮.৮০.০ ভার্সন থেকে কাজ করবে।
Route Name Prefixes
আপনি যদি group route এর মধ্যে প্রত্যেকটি route কে একটি করে নাম দিতে চান , তাহলে আপনি এই সুবিধা গ্রহণ করতে পারেন , তবে এই ক্ষেত্রে আপনাকে group route নামের পর একটা “.” দিতে হবে। নিচের উদাহরণ দেখুন :
Route::name('admin.')->group(function () { Route::get('/create',function(){ echo Route::currentRouteName(); })->name('create'); Route::get('/read',function(){ echo Route::currentRouteName(); })->name('read'); Route::get('/update/{id}',function($id){ echo Route::currentRouteName()."/".$id; })->name('update'); Route::get('/delete/{id}',function($id){ echo Route::currentRouteName()."/".$id; })->name('delete'); });
আর এই কাজটি Controller দিয়ে করতে হলে আপনার কোড টি হবে নিম্নরুপঃ
Route::name('user.')->group(function () { Route::get('/create',[UserController::class, 'create'])->name('create'); Route::get('/read',[UserController::class, 'read'])->name('read'); Route::get('/update/{id}',[UserController::class, 'update'])->name('update'); Route::get('/delete/{id}',[UserController::class, 'delete'])->name('delete'); });
এখন আপনার url গুলো নিচের মতো হবে:
http://localhost:8000/create http://localhost:8000/read http://localhost:8000/update/2 http://localhost:8000/delete/2
Multiple Middleware in Route Group
আপনি যদি একটি group route এর মধ্যে প্রত্যেকটি route কে ভিন্ন ভিন্ন middleware চেক করার পর রান করতে চান, তাহলে আপনাকে এই পদ্ধতি ব্যবহার করতে হবে। চলুন প্রথমে দেখা যাক এই পদ্ধতিতে , আপনার route দেখতে কেমন হবে :
Route::middleware(['first', 'second'])->group(function () { Route::get('/profile', function () { return "Checked By First Middleware"; }); Route::get('/user/profile', function () { return "Checked By Second Middleware"; }); });
এইবার নিম্নোক্ত দুটি কমান্ড ব্যবহার করে দুটি middleware তৈরী করে ফেলুন :
php artisan make:middleware first php artisan make:middleware second
এবার উক্ত middleware দুটিকে Kernel.php
তে রেজিস্টার করে আসুন।
protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'first' => \App\Http\Middleware\first::class, 'second' => \App\Http\Middleware\second::class, ];
এবার আপনার route ফাইলে সবার উপরে নিম্নোক্ত দুটি middleware যুক্ত করে দিন।
use App\Http\Middleware\first; use App\Http\Middleware\second;
এখন আপনি যথাক্রমে http://localhost:8000/profile এবং http://localhost:8000/user/profile এই দুটি url রান করেন , তাহলে নিচের মতো রেজাল্ট পাবেন।
এতক্ষন আমরা দেখলাম কিভাবে একটা route group এর মধ্যে একাধিক middleware রান করে হয়। এবার চলুন উক্ত first এবং second middleware থেকে আমাদের profile এবং user/profile route এর জন্য কিছু data যুক্ত করা যাক।
প্রথমে আমাদের তৈরি first Middleware কে নিচের মতো করে পরিবর্তন করে নিন।
public function handle(Request $request, Closure $next) { $request->request->add(["name"=>"Masud Alam"]); return $next($request); }
এবার আমাদের তৈরি second Middleware কে নিচের মতো করে পরিবর্তন করে নিন।
public function handle(Request $request, Closure $next) { $request->request->add(["user"=>"Sohel Alam"]); return $next($request); }
এবার আমাদের তৈরি route কে নিচের মতো করে পরিবর্তন করে নিন।
Route::middleware(['first', 'second'])->group(function () { Route::get('/profile', function (Request $request) { return "Welcome ".$request->name."!"; }); Route::get('/user/profile', function (Request $request) { return "Welcome ".$request->user."!"; }); });
এখন আপনি যথাক্রমে http://localhost:8000/profile এবং http://localhost:8000/user/profile এই দুটি url রান করেন , তাহলে নিচের মতো রেজাল্ট পাবেন।
Larave Route এর মাধ্যমে MySQL Database Table থেকে Data Fetch করা :
Laravel Database table থেকে Data fetch করতে হলে আপনাকে প্রথমে Database এর host এর সাথে connect এবং Database Select করতে হবে। আর এর জন্য আপনাকে আপনার project এর root ফোল্ডারের .env ফাইল এ Database এর host, username, password এবং Database name বলে দিতে হবে। নিচের ছবিটি লক্ষ্য করুন :
Note: .env file edit করার পর অবশ্যই php artisan সার্ভার টি রিস্টার্ট দিতে হবে। অথবা “php artisan config:clear” এই command টি run করতে হবে।
এবার নিম্নের কোডটি routes/web.php তে লিখুন :
Route::get('/getall', function() { $fetchData = DB::select('select * from students'); echo "<pre>"; print_r($fetchData); echo "</pre>"; });
এখন আপনি আপনার ব্রাউজার এর Address bar এ http://localhost:8000/getall লিখে hit করুন , তাহলে আপনার route ঠিক নিম্নের screenshot এর মতো রেজাল্ট দেখাবে:
Route Model Binding
যখন একটি model ID যেকোনো route বা controller এ ব্যবহার করা হয়, তখন প্রত্যেকবার আপনাকে সেই model ID সংশ্লিষ্ট model টি call করতে হয়। আর এই কাজটি একজন ডেভেলপারের জন্য অবশ্যই বিরক্তিকর বিষয়। আপনি যেই মডেলের আইডি ব্যবহার করবেন, যেন সেই মডেল টি অটোমেটিক্যালি route বা controller এ লোড হয়ে যায়, তা আপনি Laravel route model binding ফীচার এর মাধ্যমে খুব সহজেই করতে পারেন। আর এই কাজটি আপনি দুইভাবে করতে পারেন :
- Implicit Binding
- Explicit Binding
Implicit Binding
এই পদ্ধতিতে ,যখন কোনো route বা controller এ যেকোনো function এর মধ্যে অবস্থিত type-hinted variable এর নামের সাথে route বা controller এ ব্যবহার করা মডেলের নাম একই হয় , তখন লারাভেল স্বয়ংক্রিয় ভাবে উক্ত মডেলটি লোড করে নেয়। নিচের উদাহরণটি দেখুন :
use App\Models\User; Route::get('/users/{user}', function (User $user) { return $user->name."<br>".$user->email; });
উল্লেখ্য Implicit Binding এ route বা controller এ অবস্থিত function এ Typed Hint Parameter variable এর নাম এবং route এর URL variable এর নাম একই হতে হয়। তা না হলে আপনি কোনো রেজাল্ট পাবেন না।
আর এই কাজটি Controller দিয়ে করতে হলে আপনার কোড টি হবে নিম্নরুপঃ
// Route definition... use App\Http\Controllers\UserController; Route::get('/users/{user}', [UserController::class, 'show']);
// Controller method definition... public function show(User $user) { return $user->name."<br>".$user->email; }
Note:
controller এর প্রাকটিস টি করার পূর্বে , UserController Class শুরুর পূর্বে এই use App\Models\User; লাইনটি যুক্ত আছে কিনা তা নিশ্চিত হয়ে নিবেন।
এক্ষেত্রে আপনি যদি উক্ত মডেলের ডাটা কোনো view ফাইলে পাঠাতে চান , তাহলে আপনার কোডটি হবে নিম্নরুপঃ
শুধু route এর মাধ্যমে view তে পাঠাতে কোডঃ
// Route definition... use App\Models\User; Route::get('/users/{user}', function (User $user) { return view('user.profile', ['user' => $user]); });
আর এই কাজটি Controller দিয়ে করতে হলে আপনার কোড টি হবে নিম্নরুপঃ
// Route definition... use App\Http\Controllers\UserController; Route::get('/users/{user}', [UserController::class, 'show']);
// Controller method definition... public function show(User $user) { return view('user.profile', ['user' => $user]); }
এই ক্ষেত্রে আপনার resources/view/user/profile.blade.php ফাইলের কোড হবে নিম্নরূপ:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Route Model Implicit Binding</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> </head> <body> <div> <h4>Welcome {{$user['name']}}!</h4> <p>Your Email is: {{$user['email']}}!</p> </div> </body> </html>
Soft Deleted Models in Laravel Route
সাধারণতঃ implicit model binding পদ্ধতিতে আপনি লারাভেলের সফ্ট ডিলিট ডাটা কে সরাসরি retrieve করতে পারবেন না। তবে আপনি এই কাজটি withTrashed ফাঙ্কশন ব্যবহার করে করতে পারেন। তখন আপনার কোডটি হবে নিম্নরুপঃ
use App\Models\User; Route::get('/users/{user}', function (User $user) { return $user->email; })->withTrashed();
Customizing The Key in Laravel Route
আপনার অনেক সময় Eloquent model কে Id এর পরিবর্তে অন্য যেকোনো কলাম দিয়েও কল করতে ইচ্ছে বা দরকার হতে পারে। আর এই কাজটি করতে হলে আপনাকে route parameter definition এ Database table এর column কে নির্দিষ্ট করে দিতে হবে। কোডটি হবে নিম্নরুপঃ
use App\Models\User; Route::get('/users/{user:email}', function (User $user) { return $user->name."<br>".$user->email; });
এখন আপনার url টি হবে নিম্নরুপঃ
তবে আপনি চাইলে আপনার User Model ক্লাসে getRouteKeyName ফাঙ্কশন দিয়ে নতুন ডিফল্ট কলামের নাম বলে দিতে পারেন । কোডটি হবে নিম্নরুপঃ
/** * Get the route key for the model. * * @return string */ public function getRouteKeyName() { return 'email'; }
আর তখন আপনাকে আপনার route parameter definition এ Database table এর column কে আলাদাভাবে নির্দিষ্ট করে দিতে হবেনা।
use App\Models\User; Route::get('/users/{user}', function (User $user) { return $user->name."<br>".$user->email; });
Custom Keys & Scoping in Laravel Route
একটি route এ যখন একাধিক Eloquent model কে implicitly binding বা পরোক্ষভাবে আবদ্ধ করার সময়, আপনি দ্বিতীয় Eloquent model কে এমনভাবে স্কোপ করতে চাইতে পারেন যে এটি অবশ্যই তার পূর্ববর্তী Eloquent model এর একটি child হতে হবে। উদাহরণস্বরূপ, এই route definition টি লক্ষ্য করুন যা একটি নির্দিষ্ট ইউজারের জন্য id দ্বারা একটি ব্লগ পোস্ট খুঁজে বের করবে।
তবে এই কাজটি করার জন্য আপনাকে প্রথমে User Model এবং Post Model এর মধ্যে নিম্নোক্ত উপায়ে রিলেশন করে দিতে হবে।
User.php
public function posts() { return $this->hasMany(Post::class); }
Post.php
public function user(){ return $this->belongsTo(User::class); }
web.php
use App\Models\Post; use App\Models\User; Route::get('/users/{user}/posts/{post:id}', function (User $user, Post $post) { dd($post); });
একটি nested route এ প্যারামিটার হিসাবে যখন একটি custom keyed implicit binding ব্যবহার করার সময়, লারাভেল স্বয়ংক্রিয়ভাবে প্যারেন্টের সাথে relationship বের করার conventions গুলি ব্যবহার করে এবং তার প্যারেন্টস দ্বারা নেস্টেড মডেলটি খুঁজে বের করার জন্য ক্যোয়ারী স্কোপ করবে৷ এই ক্ষেত্রে, এটি ধরে নেওয়া হবে যে User মডেলের Post নামে একটি relationship রয়েছে ,যা Post মডেল খুঁজে বের করতে ব্যবহার করা যেতে পারে।
তবে আপনি যদি চান, আপনি লারাভেলকে নির্দেশ দিতে পারেন “child” বাইন্ডিং করার জন্য এমনকি যদি একটি custom key প্রদান করা না হয়। এটি করার জন্য, আপনি আপনার route সংজ্ঞায়িত করার সময় scopeBindings পদ্ধতি ব্যবহার করতে পারেন:
use App\Models\Post; use App\Models\User; Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) { dd($post); })->scopeBindings();
অথবা, আপনি চাইলে scoped bindings ব্যবহার করার জন্য route definition গুলো একটি সম্পূর্ণ Group এর মধ্যে লিখতে পারেন:
Route::scopeBindings()->group(function () { Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) { return $post; }); });
এক্ষেত্রে আপনার Model ক্লাসে getRouteKeyName ফাঙ্কশন দিয়ে নতুন ডিফল্ট কলামের নাম বলে দিতে ভুলবেন না ।
/** * Get the route key for the model. * * @return string */ public function getRouteKeyName() { return 'email'; }
Customizing Missing Model Behavior in Laravel Route
সাধারণত, যদি কোনো কারণে লারাভেলে কোনো implicitly bound model পাওয়া না যায়, লারাভেল তখন বাইডিফল্ট একটি 404 HTTP response তৈরি করে। তবে আপনি চাইলে, আপনার route কে ডিফাইন করার সময় লারাভেলের missing method কল করে এটি কাস্টমাইজ করতে পারেন। মূলতঃ যখনি কোনো কারণে implicitly bound model পাওয়া না যায়, তখন missing method টি প্রথমে একটি closure কে কল করবে। নিচের উদাহরণটি দেখুন :
use App\Models\User; use Illuminate\Support\Facades\Redirect; Route::get('/users/{user}', function (User $user) { return $user->name."<br>".$user->email; })->missing(fn()=>response()->view('404'));
আর যদি এই কাজটি আপনি কন্ট্রোলারের মাধ্যমে করতে চান , তখন আপনার route টি হবে নিম্নরুপঃ
use App\Models\User; use Illuminate\Support\Facades\Redirect; use App\Http\Controllers\UserController; Route::get('/users/{user}', [UserController::class, 'show']) ->name('user.view') ->missing(function (Request $request) { return response()->view('404'); });
আপনার কাস্টম resources/views/404.blade.php ফাইলের কোড হবে নিম্নরুপঃ
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>404</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> </head> <body> <div class="vh-100 d-flex justify-content-center align-items-center"> <h4>It seems we can’t find what you’re looking for.</h4> </div> </body> </html>
Implicit Route Bindings With Enums in Laravel Route
আপনি এখন আপনার লারাভেল route এ PHP 8.1 এর enum TypeHint সুবিধা যুক্ত করতে পারেন। Laravel তারপর শুধুমাত্র route টি ব্যবহার করবে যদি route এর URI তে একটি ভ্যালিড enum থাকে। আর যদি enum না পাওয়া যায় তাহলে একটি 404 ফেরত রিটার্ন করবে।
চলুন প্রথমে app/Enums ফোল্ডারে Category.php নামে একটা Enum তৈরি করা যাক।
<?php namespace App\Enums; enum Category: string{ case Fruits = 'fruits'; case People = 'people'; }
এবার আমরা route এ নিম্নোক্ত কোডটি লিখব:
use App\Enums\Category; Route::get('/categories/{category}', function (Category $category) { return $category->value; });
এখন আমরা যদি দুটি enum যথাক্রমে fruites এবং people এর মধ্যে যেকোনো একটি দেই , তুমি তাহলে লারাভেল রুট আপনাকে আউটপুট রিটার্ন করবে।
অন্যথায় 404 output রিটার্ন করবে।
Explicit Binding in Laravel Route
এটা অনেকটা Implicit Model Binding এর মতোই ,শুধু পার্থক্য হচ্ছে এই পদ্ধতিতে আপনি route বা controller function এ Model Class কে Typed Hint করা লাগবেনা। তবে Parameter Variable টির নাম অবশ্যই মডেলের নামের সাথে মিল থাকতে হবে। এবং app/Providers/ ফোল্ডারের মধ্যে অবস্থিত RouteServiceProvider ফাইলে boot মেথডে আপনার মডেল টিকে রেজিস্ট্রেশন করে রাখতে হবে।
তো চলুন প্রথমে RouteServiceProvider ফাইলে boot মেথডে আমাদের User Model টি রেজিস্টার করে রাখি।
use App\Models\User; use Illuminate\Support\Facades\Route; /** * Define your route model bindings, pattern filters, etc. * * @return void */ public function boot() { Route::model('user', User::class); // ... }
এখন আপনি আপনার route ফাইলে Model class Typed Hint ছাড়াই Route Model Binding করতে পারবেন।
Route::get('/users/{user}', function ($user) { return $user->name."<br>".$user->email; });
Customizing The Resolution Logic in Laravel Route
Explicit Binding এ ডাটাবেস টেবিল এর আপনার পছন্দ মতো কোনো নির্দিষ্ট কলাম এর বিপরীতে ডাটা fetch করতে চান। তাহলে আপনি আপনার নিজস্ব model binding resolution logic ব্যবহার করতে পারেন। এবং এর জন্য Route::bind method ব্যবহার করতে পারেন। এতে আপনি bind method এ যে ক্লোজারটি পাস করবেন সেটি URI সেগমেন্টের value পাবে এবং রুটে ইনজেকশন দেওয়া ক্লাসের instance ফেরত দেবে। আর , এই কাজটি আপনি আপনার অ্যাপ্লিকেশনের RouteServiceProvider-এর Boot Method এ লিখতে হবে:
use App\Models\Customers; use Illuminate\Support\Facades\Route; /** * Define your route model bindings, pattern filters, etc. * * @return void */ public function boot() { Route::bind('customers', function ($value) { return Customers::where('phone', $value)->firstOrFail(); }); // ... }
আপনার route টি হবে নিম্নরূপ :
Route::get('/getinfo/{customers}',function($customers){ dd($customers); });
এখন আপনি আপনার কাস্টমারের তথ্য তার Id এর পরিবর্তে phone নম্বর দিয়ে fetch করতে পারবেন।
2 thoughts on “Laravel Framework Basics পর্ব-৩: Laravel Routes”
Leave a Reply
You must be logged in to post a comment.
Route::get(‘/’, function (){
echo “This is Home Page”; //here ” was missing above
});
Route::get(‘/about’, function (){
echo ” This is About Page”;
});
Route::get(‘/contact’, function (){
echo ” This is Contact Page”;
});
why array index name such as [0]=>stdClass Object