Package Development in Bagisto Overview A package is a self-contained module that encapsulates specific features or functionality in Bagisto. This comprehensive skill covers all aspects of package development from structure to advanced features. When to Apply Activate this skill when: Creating new packages for Bagisto Setting up package directory structure Creating database migrations Building Eloquent models with contracts and proxies Implementing repositories for data access Creating routes for admin/shop sections Building controllers with dependency injection Creating Blade views with Bagisto layouts Adding multi-language support Creating admin DataGrid tables Setting up admin navigation menus Implementing permission-based access control Creating configurable settings for admin @core: Package Development - Core Package Structure Standard Directory Structure packages/Webkul/{PackageName}/ ├── src/ │ ├── Config/ │ │ ├── admin-menu.php │ │ ├── acl.php │ │ └── system.php │ ├── Database/ │ │ ├── Migrations/ │ │ ├── Seeders/ │ │ └── Factories/ │ ├── Http/ │ │ ├── Controllers/ │ │ │ ├── Admin/ │ │ │ └── Shop/ │ │ ├── Middleware/ │ │ └── Requests/ │ ├── Models/ │ │ └── {Package}Proxy.php │ ├── Repositories/ │ │ └── {Package}Repository.php │ ├── Resources/ │ │ ├── views/ │ │ └── lang/ │ ├── Providers/ │ │ ├── {Package}ServiceProvider.php │ │ └── ModuleServiceProvider.php │ ├── DataGrids/ │ │ └── Admin/ │ └── manifest.php └── composer.json Using Package Generator Installation composer require bagisto/bagisto-package-generator Creating a Package
If package directory doesn't exist
php artisan package:make Webkul/RMA
If package directory already exists
php artisan package:make Webkul/RMA --force Making Models php artisan package:make-model ReturnRequest Webkul/RMA Making Repositories php artisan package:make-repository ReturnRequestRepository Webkul/RMA Making Migrations php artisan package:make-migration CreateRmaRequestsTable Webkul/RMA Manual Setup Create Package Directory mkdir -p packages/Webkul/RMA/src/Providers Create Service Provider File: packages/Webkul/RMA/src/Providers/RMAServiceProvider.php
loadMigrationsFrom ( __DIR__ . '/../Database/Migrations' ) ; } Loading Routes public function boot ( ) : void { $this -> loadRoutesFrom ( __DIR__ . '/../Routes/admin-routes.php' ) ; $this -> loadRoutesFrom ( __DIR__ . '/../Routes/shop-routes.php' ) ; } Loading Views public function boot ( ) : void { $this -> loadViewsFrom ( __DIR__ . '/../Resources/views' , 'rma' ) ; } Loading Translations public function boot ( ) : void { $this -> loadTranslationsFrom ( __DIR__ . '/../Resources/lang' , 'rma' ) ; } Merging Config public function register ( ) : void { $this -> mergeConfigFrom ( dirname ( __DIR__ ) . '/Config/admin-menu.php' , 'menu.admin' ) ; $this -> mergeConfigFrom ( dirname ( __DIR__ ) . '/Config/acl.php' , 'acl' ) ; $this -> mergeConfigFrom ( dirname ( __DIR__ ) . '/Config/system.php' , 'core' ) ; } Concord Model Registration Create ModuleServiceProvider File: packages/Webkul/RMA/src/Providers/ModuleServiceProvider.php [ // Other service providers... \ Webkul \ RMA \ Providers \ ModuleServiceProvider :: class , ] , ] ; @data: Package Development - Data Layer Migrations Creating Migrations # Using Bagisto generator php artisan package:make-migration CreateRmaRequestsTable Webkul/RMA # Using Laravel artisan php artisan make:migration CreateRmaRequestsTable --path = packages/Webkul/RMA/src/Database/Migrations Basic Migration Structure id ( ) ; $table -> unsignedInteger ( 'customer_id' ) ; $table -> unsignedInteger ( 'order_id' ) ; $table -> string ( 'product_sku' ) ; $table -> string ( 'product_name' ) ; $table -> integer ( 'product_quantity' ) ; $table -> string ( 'status' ) -> default ( 'pending' ) ; $table -> string ( 'reason' ) -> nullable ( ) ; $table -> text ( 'admin_notes' ) -> nullable ( ) ; $table -> timestamps ( ) ; } ) ; } public function down ( ) : void { Schema :: dropIfExists ( 'rma_requests' ) ; } } ; Running Migrations # Run all migrations php artisan migrate # Run specific package migrations php artisan migrate --path = packages/Webkul/RMA/src/Database/Migrations # Check migration status php artisan migrate:status Models Bagisto Model Architecture Bagisto uses a three-component model system: Contract - Interface defining the public API Model - Eloquent model implementation Proxy - Runtime model resolution via Concord Creating Model Components # Using Bagisto generator (creates all three) php artisan package:make-model ReturnRequest Webkul/RMA Contract File: packages/Webkul/RMA/src/Contracts/ReturnRequest.php create ( [ 'customer_id' => 1 , 'order_id' => 123 , 'product_sku' => 'SAMPLE-001' , 'status' => 'pending' , ] ) ; // Read $all = $repository -> all ( ) ; $find = $repository -> find ( $id ) ; $findOrFail = $repository -> findOrFail ( $id ) ; $first = $repository -> findWhere ( [ 'status' => 'pending' ] ) -> first ( ) ; // Update $repository -> update ( [ 'status' => 'approved' ] , $id ) ; // Delete $repository -> delete ( $id ) ; Advanced Queries // Where conditions $results = $repository -> findWhere ( [ 'status' => 'pending' , 'customer_id' => 456 , ] ) ; // Where in $results = $repository -> findWhereIn ( 'id' , [ 1 , 2 , 3 ] ) ; // Where between $results = $repository -> findWhereBetween ( 'created_at' , [ '2024-01-01' , '2024-12-31' ] ) ; // Pagination $paginator = $repository -> paginate ( 15 ) ; // Eager loading $withRelations = $repository -> with ( [ 'customer' , 'order' ] ) -> find ( $id ) ; Custom Repository Methods findWhere ( [ 'customer_id' => $customerId , 'status' => 'pending' ] ) ; } public function getStats ( ) : array { return [ 'total' => $this -> count ( ) , 'pending' => $this -> findWhere ( [ 'status' => 'pending' ] ) -> count ( ) , 'approved' => $this -> findWhere ( [ 'status' => 'approved' ] ) -> count ( ) , ] ; } public function getRecent ( int $limit = 10 ) { return $this -> orderBy ( 'created_at' , 'desc' ) -> limit ( $limit ) -> get ( ) ; } } @ui: Package Development - UI Layer Routes Admin Routes File: packages/Webkul/RMA/src/Routes/admin-routes.php [ 'web' , 'admin' ] , 'prefix' => config ( 'app.admin_url' ) ] , function ( ) { Route :: prefix ( 'rma/return-requests' ) -> group ( function ( ) { Route :: get ( '' , [ ReturnRequestController :: class , 'index' ] ) -> name ( 'admin.rma.return-requests.index' ) ; Route :: get ( '{id}' , [ ReturnRequestController :: class , 'show' ] ) -> name ( 'admin.rma.return-requests.show' ) ; Route :: post ( '' , [ ReturnRequestController :: class , 'store' ] ) -> name ( 'admin.rma.return-requests.store' ) ; Route :: put ( '{id}' , [ ReturnRequestController :: class , 'update' ] ) -> name ( 'admin.rma.return-requests.update' ) ; Route :: delete ( '{id}' , [ ReturnRequestController :: class , 'destroy' ] ) -> name ( 'admin.rma.return-requests.destroy' ) ; Route :: post ( 'mass-delete' , [ ReturnRequestController :: class , 'massDestroy' ] ) -> name ( 'admin.rma.return-requests.mass-delete' ) ; } ) ; } ) ; Shop Routes File: packages/Webkul/RMA/src/Routes/shop-routes.php [ 'web' , 'locale' , 'theme' , 'currency' ] ] , function ( ) { Route :: prefix ( 'rma/return-requests' ) -> group ( function ( ) { Route :: get ( '' , [ ReturnRequestController :: class , 'index' ] ) -> name ( 'shop.rma.return-requests.index' ) ; Route :: post ( '' , [ ReturnRequestController :: class , 'store' ] ) -> name ( 'shop.rma.return-requests.store' ) ; } ) ; } ) ; Route Middleware Middleware Purpose web Session handling, CSRF protection admin Admin authentication locale Language handling theme Theme resolution currency Currency handling Controllers Base Controller File: packages/Webkul/RMA/src/Http/Controllers/Controller.php ajax ( ) ) { return datagrid ( ReturnRequestDataGrid :: class ) -> process ( ) ; } return view ( 'rma::admin.return-requests.index' ) ; } public function show ( int $id ) { $returnRequest = $this -> returnRequestRepository -> findOrFail ( $id ) ; return view ( 'rma::admin.return-requests.show' , compact ( 'returnRequest' ) ) ; } public function store ( Request $request ) { $data = $request -> validate ( [ 'customer_id' => 'required|integer' , 'order_id' => 'required|integer' , 'product_sku' => 'required|string' , 'product_name' => 'required|string' , 'product_quantity' => 'required|integer|min:1' , 'reason' => 'nullable|string' , ] ) ; $this -> returnRequestRepository -> create ( $data ) ; return redirect ( ) -> route ( 'admin.rma.return-requests.index' ) -> with ( 'success' , 'Return request created successfully.' ) ; } public function update ( Request $request , int $id ) { $data = $request -> validate ( [ 'status' => 'required|string|in:pending,approved,rejected' , 'admin_notes' => 'nullable|string' , ] ) ; $this -> returnRequestRepository -> update ( $data , $id ) ; return redirect ( ) -> back ( ) -> with ( 'success' , 'Return request updated.' ) ; } public function destroy ( int $id ) { $this -> returnRequestRepository -> delete ( $id ) ; return redirect ( ) -> back ( ) -> with ( 'success' , 'Return request deleted.' ) ; } public function massDestroy ( ) { $indices = request ( ) -> input ( 'indices' ) ; foreach ( $indices as $index ) { $this -> returnRequestRepository -> delete ( $index ) ; } return response ( ) -> json ( [ 'message' => 'Selected records deleted.' ] ) ; } } Shop Controller File: packages/Webkul/RMA/src/Http/Controllers/Shop/ReturnRequestController.php returnRequestRepository -> findWhere ( [ 'customer_id' => auth ( ) -> id ( ) ] ) ; return view ( 'rma::shop.return-requests.index' , compact ( 'returnRequests' ) ) ; } public function store ( Request $request ) { $data = $request -> validate ( [ 'order_id' => 'required|integer' , 'product_sku' => 'required|string' , 'product_name' => 'required|string' , 'product_quantity' => 'required|integer|min:1' , 'reason' => 'required|string' , ] ) ; $data [ 'customer_id' ] = auth ( ) -> id ( ) ; $data [ 'status' ] = 'pending' ; $this -> returnRequestRepository -> create ( $data ) ; return redirect ( ) -> back ( ) -> with ( 'success' , 'Return request submitted.' ) ; } } Views Admin Layout@lang('rma::app.admin.return-requests.title')
@lang('rma::app.admin.return-requests.show.title') #{{ $returnRequest->id }}
@lang('rma::app.admin.return-requests.show.general-info')
@lang('rma::app.admin.return-requests.show.product-name'):
{{ $returnRequest->product_name }}
@lang('rma::app.admin.return-requests.show.status'):
{{ ucfirst($returnRequest->status) }}