Laravel Architecture Concepts
বাংলায় Laravel Framework Laravel Architecture Concepts পর্ব-২: Laravel Service Container
Service Container ব্যাখ্যা শুরু করার পূর্বে আমি DI মানে Dependency Injection কি সেটি ব্যাখ্যা করব।
In software engineering, dependency injection is a technique in which an object receives other objects that it depends on. These other objects are called dependencies. In the typical “using” relationship the receiving object is called a client and the passed object is called a service.
By Wikipedia
সহজ কথায়, Dependency Injection হল অন্য object বা class এর উপর নির্ভরশীল হওয়া। Dependency Injection সাধারণত constructor বা setter ফাঙ্কশন দিয়ে সম্পন্ন করা হয়। বেশিরভাগ ক্ষেত্রে আমরা constructor মাধ্যমে এটি ব্যবহার করি। আমরা সাধারণত নিম্নোক্ত তিন উপায়ে Dependency গুলোকে Inject করে থাকি।
- Constructor Injection
- Setter Injection
- Interface Injection
চলুন উপরোক্ত তিন উপায়ের প্রত্যেকটির একটি করে উদাহরণ দেওয়া যাক :
Constructor Injection
Class Client { public $service; public function __construct(CarService $service){ $this->service = $service; } }
Setter Injection
Class Client { public $service; public function setService(CarService $service){ $this->service = $service; } }
Interface Injection
interface Services{ public function setService(CarService $service); } Class Client implements Services { private $service; public function setService(CarService $service){ $this->service = $service; } }
আশাকরি আপনারা বুঝতে পেরেছেন। তাই service containers নিয়ে কথা বলা যাক.
Laravel Service Container কি?
The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection. Dependency injection is a fancy phrase that essentially means this: class dependencies are “injected” into the class via the constructor or, in some cases, “setter” methods.
By Laravel
আরো সহজভাবে বলা যায়, Laravel service container এমন একটি Powerful Tool যা আপনাকে লারাভেলের class dependency গুলো পরিচালনা এবং এদের ব্যবহারের অনুমতি প্রদান করে। আর এই সব কিছুই Laravel এ Dependency injection সিস্টেম ব্যবহার করে করা হয়। এটি এমন একটি সুবিধা , যা দিয়ে আপনি class dependency গুলোকে constructor বা কিছু ক্ষেত্রে “setter” method এর মাধ্যমে ক্লাসে “injected” করা হয়। আরো সহজ ভাবে বলা যায়, এটি এমন একটি কন্টেইনার যা ক্লাস গুলো কে তার কাছে hold করতে পারে এবং পরবর্তিতে ক্লাসের অবজেক্ট তৈরিতে আমরা আমাদের প্রয়োজন মতো এদেরকে ব্যবহার করতে পারি।
লারাভেলে Service Container কেন ব্যবহার করবেন?
সবার আগে আমাদের জানা দরকার, কেন service container দরকার। উপরের আলোচনা অনুযায়ী আমরা যদি কোর পিএইচপি-তে Dependency Injection ব্যবহার করি তাহলে আমাদেরকে আমাদের সার্ভিসের জন্য একটা Instance প্রোভাইড করতে হয়। কিন্তু লারাভেলে আমাদের Service এর জন্য কোনো Instance তৈরি করার দরকার নেই। আমরা কেবল আমাদের Service তৈরি করব এবং type hint ব্যবহার করে Inject করব বা লারাভেলের Service Container ব্যবহার করে এটি করব ।
লারাভেলে Service Container কখন ব্যবহার করবেন?
তাহলে এতক্ষনে আমরা জানলাম যে কেন লারাভেল service container ব্যবহার করে , আর এখন আমরা জানব আমাদের কেন service container ব্যবহার করতে হবে। মূলতঃ আপনি যদি কখনও লারাভেল দিয়ে কোনো প্রজেক্ট তৈরি করেন তবে আমি নিশ্চিত যে আপনি ইতিমধ্যে service container ফীচার টি ব্যবহার করেছেন। উদাহরণস্বরূপ, যদি আপনি আপনার কোনো Method এ type-hint Illuminate\Http\Request এবং $request ব্যবহার করেন। তাহলে লক্ষ্য করবেন, আপনি Request ক্লাসের কোনো Instance প্রোভাইড করেন নাই , তাহলে আপনি আপনার Method এ কিভাবে $request object ব্যবহার করতে পারেন? কারণ এখানে লারাভেলের স্বয়ংক্রিয় dependency injection কাজ করতেছে।
এখন আমাদের জানা দরকার , কখন আমাদের service container ব্যবহার করা উচিৎ? মূলতঃ দুটি পরিস্থিতিতে আপনাকে সত্যিকারে service container ব্যবহার করা উচিৎ।
- আপনি যখন class constructor বা route একটি ইন্টারফেস type-hint করতে চান
- একটি লারাভেল package develop করার সময়
লারাভেলে Service Container কীভাবে ব্যবহার করবেন?
লারাভেল Service Container ব্যবহার করা খুবই সহজ। নিম্নে আমরা কয়েকটি পদ্ধতিতে Laravel Service Container ব্যবহার শিখব।
1.Binding
কন্টেইনারে আপনার service যোগ করতে আপনি Binding পদ্ধতি ব্যবহার করতে পারেন। উদাহরণস্বরূপ আপনার কাছে PaymentService একটা Interface আছে এবং আপনি এটি service container এ আবদ্ধ করতে চান। তাহলে আপনি নিচের উদাহরণকে অনুসরণ করতে পারেন।
<?php namespace App\Providers; use App\Billings\PaypalAPI; use Illuminate\Support\ServiceProvider; class PaymentServiceProvider extends ServiceProvider { /** * Register services. * * @return void */ public function register() { $this->app->bind(PaypalAPI::class, function () { return new PaypalAPI(125); }); } /** * Bootstrap services. * * @return void */ public function boot() { // } }
এছাড়াও আমরা container এ যেকোনো service আবদ্ধ করতে Facades ব্যবহার করতে পারি।
<?php namespace App\Providers; use App\Billings\PaypalAPI; use Illuminate\Support\Facades\App; use Illuminate\Support\ServiceProvider; class PaymentServiceProvider extends ServiceProvider { /** * Register services. * * @return void */ public function register() { App::bind(PaypalAPI::class, function () { return new PaypalAPI(125); }); } /** * Bootstrap services. * * @return void */ public function boot() { // } }
2. Singleton Binding
একে বলা হয় simple binding এবং যখনই আমরা কোনো Object এ একাধিকবার access করার চেষ্টা করি তখন এটি একই কাজ একাধিকবার সমাধান করে তাই আমরা একটি singleton method ব্যবহার করতে পারি বা অতিরিক্ত Argument পাস করতে পারি যা bind() এ একটা shared parameter.
<?php namespace App\Providers; use App\Billings\PaypalAPI; use Illuminate\Support\Facades\App; use Illuminate\Support\ServiceProvider; class PaymentServiceProvider extends ServiceProvider { /** * Register services. * * @return void */ public function register() { $this->app->singleton(PaypalAPI::class, function () { return new PaypalAPI(125); }); } /** * Bootstrap services. * * @return void */ public function boot() { // } }
অথবা নিচের মতো করেও করতে পারেন।
<?php namespace App\Providers; use App\Billings\PaypalAPI; use Illuminate\Support\ServiceProvider; class PaymentServiceProvider extends ServiceProvider { /** * Register services. * * @return void */ public function register() { $this->app->bind(PaypalAPI::class, function () { return new PaypalAPI(125); }, true); } /** * Bootstrap services. * * @return void */ public function boot() { // } }
3. Binding a Instance
কখনো এমন একটি পরিস্থিতি হতে পারে যেখানে আমাদের কাছে কোনও নির্দিষ্ট service এর instance রয়েছে এবং আমরা সেটিকে service container এ bind করতে চাই। তখন নিচের উদাহরণের মতো অনুসরণ করতে পারেন।
<?php namespace App\Providers; use App\Billings\PaypalAPI; use Illuminate\Support\ServiceProvider; class PaymentServiceProvider extends ServiceProvider { /** * Register services. * * @return void */ public function register() { $service = new PaypalAPI(125); $this->app->instance(PaypalAPI::class, $service); } /** * Bootstrap services. * * @return void */ public function boot() { // } }
4. Interface Binding
Laravel Service Container বেশিরভাগই interface এর সাথে ব্যবহৃত হয় তাই যখনই আমরা কিছু Code এবং Service পরিবর্তন করতে চাই যা একটি interface কে Implement করে তখন আমাদের controller side এ আমাদের কোড পরিবর্তন করতে কোন সমস্যা নেই। আসুন নীচের কোডটি দেখুন –
<?php namespace App\Billings; use Illuminate\Http\Request; interface PaymentGatewayInterface { public function process(Request $request); public function checkout($res); }
আমাদের কাছে একটা simple interface সাথে দুটি Method রয়েছে , একটি হচ্ছে payment Method আর অন্যটি হচ্ছে checkout method.
এখন আমরা আমাদের মেইন service তৈরি করার জন্য এই ইন্টারফেসটি ব্যবহার করব । আমাদের Payment Process করার জন্য আমরা PaypalGateway এবং StripeGateway তৈরি করেছি। এখন আমরা শুধু srmklive/paypal payment package দিয়ে কিছু random code তৈরি করব।
<?php namespace App\Billings\Gateways; use App\Billings\PaymentGatewayInterface; use Illuminate\Http\Request; use Srmklive\PayPal\Services\ExpressCheckout; class PaypalGateway implements PaymentGatewayInterface { public function process(Request $request) { $products = []; $products['items'] = [ ['name' => 'Laravel Book', 'price' => 1200, 'des' => "Laravel Book for Advance Learning", 'qty' => 1 ] ]; $products['invoice_id'] = uniqid(); $products['invoice_description'] = "Order #{$products['invoice_id']} Billing"; $products['return_url'] = route('success.pay'); $products['cancel_url'] = route('success.pay'); $products['total'] = 1200; $paypal = new ExpressCheckout(); return $paypal->setExpressCheckout($products); } public function checkout($res) { return redirect($res['paypal_link']); } }
<?php namespace App\Billings\Gateways; use App\Billings\PaymentGatewayInterface; use Illuminate\Http\Request; class StripeGateway implements PaymentGatewayInterface { public function process(Request $request) { // TODO: Implement process() method. } public function checkout($res) { // TODO: Implement checkout() method. } }
এখন আমাদের কাছে দুটি service রয়েছে। আর এখানে যেকোনো customer চাইলে Paypal বা Stripe এর মাধ্যমে তার ইচ্ছামত অর্থ প্রদান করতে পারে। এখন আমাদের বাইন্ডিং বিভাগ দেখব। আমরা সরাসরি আমাদের AppServiceProvider এরমাধ্যমে এটি করেছি। আপনি চাইলে আপনার custom Service Provider ব্যবহার করতে পারেন।
<?php namespace App\Providers; use App\Billings\Gateways\PaypalGateway; use App\Billings\Gateways\StripeGateway; use App\Billings\PaymentGatewayInterface; use Illuminate\Support\ServiceProvider; use Softon\Indipay\Indipay; class AppServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { $this->app->bind(PaymentGatewayInterface::class, function(){ $gateway = request()->gateway; if ($gateway === "paypal"){ return new PaypalGateway(); }elseif ($gateway === "stripe"){ return new StripeGateway(); } }); } /** * Bootstrap any application services. * * @return void */ public function boot() { // } }
এবার আমরা আমাদের paymentController এ এটি ব্যবহার করব।
<?php namespace App\Http\Controllers; use App\Billings\PaymentGatewayInterface; use Illuminate\Http\Request; class PaymentController extends Controller { public function pay(Request $request, PaymentGatewayInterface $module) { $res = $module->process($request); return $module->checkout($res); } }
লক্ষ্য করুন, আমরা কিভাবে paypal অথবা stripe এর মাধ্যমে অর্থপ্রদানের প্রক্রিয়াটি সমাধান করব সেটি controller দিয়ে না করে PaymentGatewayInterface এর মাধ্যমে করেছি।
5.Contextual Binding
কখনো কখনো আপনার দুই বা ততোধিক class থাকতে পারে যারা একই Interface ব্যবহার করে এবং আপনি আপনার পরিস্থিতির উপর নির্ভর করে ভিন্ন ভিন্ন ইমপ্লিমেন্ট ইনজেকশন করতে চান। উদাহরণস্বরূপ আপনি যদি Filesystem ব্যবহার করেন এবং আপনার স্থানীয় সার্ভারে ফটো আপলোড করতে চান এবং আপনার S3 bucket এ ভিডিও আপলোড করতে চান তবে আপনি এই সমস্যাটি সমাধান করতে contextual binding ব্যবহার করতে পারেন।
<?php namespace App\Providers; use App\Http\Controllers\PhotoController; use App\Http\Controllers\UploadController; use App\Http\Controllers\VideoController; use Illuminate\Contracts\Filesystem\Filesystem; use Illuminate\Support\Facades\Storage; use Illuminate\Support\ServiceProvider; class PaymentServiceProvider extends ServiceProvider { /** * Register services. * * @return void */ public function register() { $this->app->when(PhotoController::class) ->needs(Filesystem::class) ->give(function () { return Storage::disk('local'); }); $this->app->when(VideoController::class) ->needs(Filesystem::class) ->give(function () { return Storage::disk('s3'); }); } /** * Bootstrap services. * * @return void */ public function boot() { // } }
কখনও কখনও আমাদের কিছু primitive value যেমন integer, string value গুলো inject করতে হয়, তখন আমাদেরকে এই ধরনের সমস্যা সমাধানের জন্য Contextual Binding ব্যবহার করা উচিৎ।
ধরুন – আমাদের কাছে একটি controller রয়েছে যা index method এ value ব্যবহার করতে constructor ব্যবহার করে এবং সেই value টিকে আউটপুটে return করে। নিচের উদাহরণ লক্ষ্য করুন:
<?php use Illuminate\Support\Facades\Route; Route::get('/', [\App\Http\Controllers\TestController::class, 'index']);
এখন আপনি একটি route তৈরি করতে পারেন যেটি TestController এর index Method কে কল করবে। নিম্নে TestController ক্লাসটি দেখুন:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class TestController extends Controller { private $value; public function __construct(string $value) { $this->value = $value; } public function index(): string { return $this->value; } }
<?php namespace App\Providers; use App\Http\Controllers\TestController; use Illuminate\Support\ServiceProvider; class TestServiceProvider extends ServiceProvider { /** * Register services. * * @return void */ public function register() { $value = "Dump Coder"; $this->app->when(TestController::class) ->needs('$value') ->give($value); } /** * Bootstrap services. * * @return void */ public function boot() { // } }
এখন আপনি যখন ব্রাউজারে এই প্রোজেক্ট ওপেন করবেন তখন এটি service container দ্বারা automatic resolved হয়ে যাবে।
6.Tagging
এখন আমরা tagging নিয়ে আলোচনা করবেন। tagging হচ্ছে একাধিক বিষয়ের ট্যাগের মতই। উদাহরণ স্বরূপ আমাদের কিছু class আছে যেগুলি একই নির্দিষ্ট বা অভিন্ন কাজের সাথে সম্পর্কিত আমরা তাদের একটি ট্যাগ দিতে পারি এবং আমরা সমস্ত ক্লাস পেতে একই ট্যাগ ব্যবহার করতে পারি। নিচের কোড চেক করা যাক-
<?php namespace App\Providers; use App\Reports\Report; use App\Reports\IncomeReport; use App\Reports\ExpanceReport; use App\Http\Controllers\ReportController; use Illuminate\Support\ServiceProvider; class ReportServiceProvider extends ServiceProvider { /** * Register services. * * @return void */ public function register() { $this->app->tag([IncomeReport::class, ExpanceReport::class], 'reports'); $this->app->when(ReportController::class) ->needs(Report::class) ->giveTagged('reports'); } /** * Bootstrap services. * * @return void */ public function boot() { // } }
7.Extending Bindings
কখনও কখনও আমাদের resolved service কে modify করতে হয় এবং extend করে ব্যবহার করতে হয় ৷ আমরা যখন extend করা Method ব্যবহার করি তখন তার একমাত্র argument হিসাবে একটি extended বা modified service প্রদান করে।
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; class TestServiceProvider extends ServiceProvider { /** * Register services. * * @return void */ public function register() { $this->app->extend(TestService::class, function ($service) { return new NewExtendedService($service); }); } /** * Bootstrap services. * * @return void */ public function boot() { // } }
8.Resolving
কখনও কখনও এমন হয় যে service container টি এক বা একাধিক dependency কে এনাবল করে। তখন আমাদের এমন কিছু method ব্যবহার করতে হবে যা আমাদের এই সমস্যাটি কাটিয়ে উঠতে সহায়তা করে।
আমরা নিচের মেথড গুলো দিয়ে সমাধান করতে পারি এবং এগুলো সবই একই কাজ করে।
// Using the App Facade App::make(TestService::class, ['value'=> $value]); // Using the app helper function app(TestService::class, ['value'=> $value]); // Using the resolve helper function resolve(TestService::class, ['value'=> $value]); // makeWith() $this->app->makeWith(TestService::class, ['value'=> $value]);
Service Container Feature ব্যবহার করে CRUD
তো চলুন Service Container Feature ব্যবহার করে একটি সম্পূর্ণ dynamic crud application তৈরি করে ফেলা যাক :
Step 1: Create Model and Migration
যেহেতু আমরা User model ব্যবহার করতে যাচ্ছি তাই Model তৈরি করার দরকার নেই। শুধু Database Connectivity ঠিক আছে কিনা সেটা যাচাই করুন এবং Database Schema তৈরির জন্য Migration আর্টিসান কম্যান্ড রান করুন।
আপনি যদি লারাভেল 9X ব্যবহারকারী হয়ে থাকেন , তাহলে আপনার App\Model\User Model টি ঠিক নিচের কোডগুলোর মতো হবে।
<?php namespace App\Models; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable { use HasApiTokens, HasFactory, Notifiable; /** * The attributes that are mass assignable. * * @var array<int, string> */ protected $fillable = [ 'name', 'email', 'password', ]; /** * The attributes that should be hidden for serialization. * * @var array<int, string> */ protected $hidden = [ 'password', 'remember_token', ]; /** * The attributes that should be cast. * * @var array<string, string> */ protected $casts = [ 'email_verified_at' => 'datetime', ]; }
Step 2: Create Repository Interface
App\Repositories\RepositoryInterface.php
যেহেতু আমরা repository pattern ব্যবহার করে একটি dynamic complete crud অ্যাপ্লিকেশন তৈরি করতে যাচ্ছি তাই আমরা নীচের মতো একটি interface তৈরি করব, যেখানে আমাদের repository এর মূল টেম্পলেট থাকবে।
<?php namespace App\Repositories; interface RepositoryInterface { public function getAllUsers(); public function getUserById($id); public function createOrUpdate( $id = null, $collection = [] ); public function deleteUser($id); }
Step 3: Create Repository Class
App\Repositories\UserRepository.php
এখন আমাদের UserRepository class তৈরি করতে হবে যেখানে আমরা ফাংশনটিকে override করব এবং এই override Method টি inplement করব। চলুন নিচের মত করে তৈরি করা যাক।
<?php namespace App\Repositories; use App\Models\User; use App\Repositories\RepositoryInterface; use Illuminate\Support\Facades\Hash; class UserRepository implements RepositoryInterface { protected $user = null; public function getAllUsers() { return User::all(); } public function getUserById($id) { return User::find($id); } public function createOrUpdate( $id = null, $collection = [] ) { if(is_null($id)) { $user = new User; $user->name = $collection['name']; $user->email = $collection['email']; $user->password = Hash::make('password'); return $user->save(); } $user = User::find($id); $user->name = $collection['name']; $user->email = $collection['email']; return $user->save(); } public function deleteUser($id) { return User::find($id)->delete(); } }
Step 4: Bind Repository in ServiceProvider
এখন আমাদের service provider এর মধ্যে এই repository টি bind করতে হবে। এবার নিচের মত করে bind করুন।
App\Providers\AppServiceProvider
<?php namespace App\Providers; use App\Repositories\RepositoryInterface; use App\Repositories\UserRepository; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { $this->app->bind(RepositoryInterface::class, UserRepository::class); } /** * Bootstrap any application services. * * @return void */ public function boot() { // } }
Step 5: Create Route
আমরা যেহেতু repository pattern দিয়ে crud তৈরি করতে যাচ্ছি, তাই আমাদেরকে এর জন্য route তৈরি করতে হবে। চলুন নিচের মত route তৈরি করে ফেলা যাক ।
routes\web.php
use App\Http\Controllers\UserController; Route::get('/users', [UserController::class,'showUsers'])->name('user.list'); Route::get('/user/create', [UserController::class,'createUser'])->name('user.create'); Route::post('/user/create', [UserController::class,'saveUser']); Route::get('/user/edit/{id}', [UserController::class,'getUser'])->name('user.edit'); Route::put('/user/edit/{id}', [UserController::class,'saveUser'])->name('user.update'); Route::get('/user/delete/{id}', [UserController::class,'deleteUser'])->name('user.delete');
Step 6: Create Controller
এখন এই ধাপে, রিপোজিটরি ডিজাইন প্যাটার্ন ব্যবহার করে একটি সম্পূর্ণ ল্যারাভেল পিএইচপি CRUD অ্যাপ্লিকেশন তৈরি করার জন্য এবং আমাদের তৈরি রিপোজিটরি ডিজাইন প্যাটার্নে তৈরি সব Method কে implement করার জন্য এখন আমাদেরকে UserController তৈরি করতে হবে।
App\Http\Controllers\UserController.php
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Repositories\RepositoryInterface; use Illuminate\Support\Facades\View; class UserController extends Controller { public $user; public function __construct(RepositoryInterface $user) { $this->user = $user; } public function showUsers() { $users = $this->user->getAllUsers(); return View::make('user.index', compact('users'))->with('i');; } public function createUser() { return View::make('user.edit'); } public function getUser($id) { $user = $this->user->getUserById($id); return View::make('user.edit', compact('user')); } public function saveUser(Request $request, $id = null) { $collection = $request->except(['_token','_method']); if( ! is_null( $id ) ) { $this->user->createOrUpdate($id, $collection); } else { $this->user->createOrUpdate($id = null, $collection); } return redirect()->route('user.list'); } public function deleteUser($id) { $this->user->deleteUser($id); return redirect()->route('user.list'); } }
Step 7: Create Blade File
Core Functionality এর সব কিছু মোটামোটি সেট করা হয়েছে। এখন আমরা শুধু আমাদের view file গুলো তৈরি করব। তারপর আমরা আমাদের প্রথম repository pattern application কে CRUD দিয়ে পরীক্ষা করব। এখন আমরা সবগুলো user লিস্ট দেখানোর জন্য index.blade.php এবং edit.blade.php ফাইলকে নিচের মতো করে তৈরি করব।
resources/views/user/index.blade.php
@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">User List</div> <div> <a href="{{ route('user.create') }}" style="float:right; margin-right:10px;">Create User</a> </div> <div class="card-body"> <table class="table table-striped table-inverse"> <thead class="thead-inverse"> <tr> <th>No</th> <th>Name</th> <th>Email</th> <th>Action</th> </tr> </thead> <tbody> @forelse ($users as $item) <tr> <td>{{ ++$i }}</td> <td>{{ $item->name }}</td> <td>{{ $item->email }}</td> <td>{{ $item->country->name ?? '' }}</td> <td> <a href="{{ route('user.edit',$item->id) }}">Edit</a> | <a href="{{ route('user.delete',$item->id) }}">Delete</a> </td> </tr> @empty @endforelse </tbody> </table> </div> </div> </div> </div> </div> @endsection
resources/views/user/edit.blade.php
@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">{{ isset($user) ? "Edit User" : "Create User" }}</div> <div class="card-body"> <form id="itemFrom" role="form" method="POST" action="{{ isset($user) ? route('user.update',$user->id) : route('user.create') }}"> @csrf @isset($user) @method('PUT') @endisset <div class="card-body"> <div class="form-group"> <label for="type">Name</label> <input type="text" name="name" value="{{ $user->name ?? '' }}"> </div> <div class="form-group"> <label for="type">Email</label> <input type="text" name="email" value="{{ $user->email ?? '' }}"> </div> <button type="submit" class="btn btn-primary"> @isset($user) <i class="fas fa-arrow-circle-up"></i> <span>Update</span> @else <i class="fas fa-plus-circle"></i> <span>Create</span> @endisset </button> </div> </form> </div> </div> </div> </div> </div> @endsection
এখন সব কিছু প্রস্তুত. এখন আপনি নীচের এই url দিয়ে পরীক্ষা করতে পারেন