Skip to main content

Laravel Package Core Showcase

Discover real-world examples and use cases of Laravel Package Core in action. See how this project uses the package as a foundation for provider bootstrapping, reusable CRUD services, runtime model extension, and response standardization.

Package Provider Foundation

Flow Service Provider Bootstrapping

Real implementation from packages/laravel-flow/src/FlowServiceProvider.php

Overview

FlowServiceProvider extends PackageCoreServiceProvider and uses the fluent PackageCore API to register package capabilities in one place. This includes config, migrations, routes, translations, dependency publishables, artisan commands, and service container aliases.

Key Features
  • Fluent package setup with configuration(PackageCore $package)
  • Container binding strategy via registerClass
  • Dependency publishable registration
  • Automatic command registration
  • Post-boot event registry integration
Use Cases
  • Building consistent package providers across a monorepo
  • Sharing registration conventions between teams
  • Reducing provider boilerplate in each package
  • Ensuring deterministic bootstrap behavior
  • Centralizing package lifecycle customization

Implementation Example

use JobMetric\PackageCore\PackageCore;
use JobMetric\PackageCore\PackageCoreServiceProvider;
use JobMetric\PackageCore\Enums\RegisterClassTypeEnum;
use JobMetric\Translation\TranslationServiceProvider;

class FlowServiceProvider extends PackageCoreServiceProvider
{
public function configuration(PackageCore $package): void
{
$package->name('laravel-workflow')
->hasConfig()
->hasMigration()
->hasRoute()
->hasTranslation()
->registerDependencyPublishable(TranslationServiceProvider::class)
->registerCommand(\JobMetric\Flow\Commands\MakeTask::class)
->registerClass('flow', \JobMetric\Flow\Services\Flow::class, RegisterClassTypeEnum::SINGLETON());
}
}

CRUD Service with Domain Logic

Flow Service Based on AbstractCrudService

Real implementation from packages/laravel-flow/src/Services/Flow.php

Overview

The Flow service inherits common CRUD behavior from AbstractCrudService and extends it with workflow-specific logic: START state initialization, default-flow switching with locking, rollout/window controls, consistency validation, and graph import/export.

Key Features
  • Model/resource binding with static class properties
  • Hook-based data shaping (changeFieldStore, afterStore)
  • Lifecycle event mapping for CRUD actions
  • Shared response contract via Response::make
  • Transactional safety for stateful operations
Use Cases
  • Package-level APIs that require consistent CRUD contracts
  • Complex services that need hooks + transactions
  • Entity-level event dispatching in reusable modules
  • Advanced workflows with duplication/import/export
  • Operations requiring deterministic cache invalidation

Implementation Example

use JobMetric\PackageCore\Services\AbstractCrudService;
use JobMetric\Flow\Models\Flow as FlowModel;
use JobMetric\Flow\Http\Resources\FlowResource;
use JobMetric\Flow\Events\Flow\FlowStoreEvent;

class Flow extends AbstractCrudService
{
protected bool $softDelete = true;
protected string $entityName = 'workflow::base.entity_names.flow';

protected static string $modelClass = FlowModel::class;
protected static string $resourceClass = FlowResource::class;
protected static ?string $storeEventClass = FlowStoreEvent::class;

protected function changeFieldStore(array &$data): void
{
$data = dto($data, \JobMetric\Flow\Http\Requests\Flow\StoreFlowRequest::class);
}
}

Dynamic Relation Extension in App Layer

Runtime Dynamic Relations

Real implementation from app/Models/Order.php

Overview

The Order model registers an orders relation on Member at boot time using addDynamicRelation. This makes cross-package model integration possible without hard-coding relation methods in upstream package models.

Key Features
  • Boot-time relation injection
  • Package-safe model extension pattern
  • Polymorphic many-to-many compatibility
  • No edits needed in dependency source code
  • Works in modular domain boundaries
Use Cases
  • Package integration in host application models
  • Custom relation mapping per project
  • Extensible membership/content/product modules
  • Plugin-like architecture for relations
  • Avoiding rigid compile-time coupling

Implementation Example

use JobMetric\Membership\Models\Member;

class Order extends Model
{
protected static function boot(): void
{
parent::boot();

Member::addDynamicRelation('orders', function ($model) {
return $model
? $model->morphedByMany(Order::class, 'memberable')
: (new Order)->morphedByMany(Member::class, 'memberable');
});
}
}

API Response Consistency with HasResponse

Controller Response Standardization

Real implementation from app/Http/Controllers/CategoryTestController.php

Overview

The controller uses HasResponse to keep single-item and collection responses consistent. This helps API endpoints return predictable structures while preserving custom message/status handling.

Key Features
  • response() helper for single payloads
  • responseCollection() helper for resources
  • Automatic message/status defaults
  • Additional metadata injection support
  • Reduced duplicate JSON boilerplate
Use Cases
  • Consistent API response contracts
  • Controller-level response abstraction
  • Mixed list/single endpoint patterns
  • Package facade result wrapping
  • Team-wide response style alignment

Implementation Example

use JobMetric\PackageCore\Controllers\HasResponse;

class CategoryTestController extends Controller
{
use HasResponse;

public function index(Request $request): JsonResponse
{
$category = Category::paginate(
$request->input('type'),
$request->input('filter', []),
$request->input('page_limit', 50),
$request->input('with', [])
);

return $this->responseCollection($category);
}
}

Get Started

Ready to implement these patterns in your package ecosystem?