Models
Overview
Pyle ships its core domain as Eloquent models under CBOX\Framework\Models. Applications can extend those models when they need app-specific relationships, scopes, casts, or behavior.
The framework resolves models through a model manifest. Use the framework model classes directly in new code. When an application overrides a model, calls such as Order::query() and Order::factory() resolve to the active application model.
WARNING
Model overrides should extend their framework counterpart. Prefer adding application behavior on top of the Pyle model instead of replacing the core table or persistence contract.
Creating an Override
Create an application model that extends the matching framework model:
<?php
namespace App\Models;
class Order extends \CBOX\Framework\Models\Order
{
public function ticket()
{
return $this->belongsTo(Ticket::class);
}
}When App\Models\Order exists and extends CBOX\Framework\Models\Order, Pyle will use it by convention.
Explicit Registration
You may also register overrides explicitly in config/pyle.php:
use App\Models\Order as AppOrder;
use CBOX\Framework\Models\Contracts\Order as OrderContract;
use CBOX\Framework\Models\Order;
return [
'overrides' => [
'models' => [
OrderContract::class => AppOrder::class,
// The framework model class is also accepted as a key.
Order::class => AppOrder::class,
],
],
];Or register an override at runtime:
use App\Models\Order as AppOrder;
use CBOX\Framework\Facades\ModelManifest;
use CBOX\Framework\Models\Contracts\Order as OrderContract;
ModelManifest::replace(OrderContract::class, AppOrder::class);To register a directory of overrides:
use CBOX\Framework\Facades\ModelManifest;
ModelManifest::addDirectory(app_path('Models'));Each discovered model must extend its framework counterpart.
Resolving Models
Use framework model classes for normal Eloquent work:
use CBOX\Framework\Models\Order;
$order = Order::make();
$orders = Order::query()->latest()->get();
$order = Order::findOrFail($id);Use modelClass() when Laravel expects a class string:
use CBOX\Framework\Models\Customer;
return $this->belongsTo(Customer::modelClass());Use morphName() when you need the stable polymorphic alias:
use CBOX\Framework\Models\Order;
$type = Order::morphName();Factories also resolve through the manifest, so Order::factory()->create() returns an instance of the active override when one is registered.
CBOX::model() and CBOX::modelClass() resolve runtime model-name strings through the model manifest. Only names registered in the manifest are accepted; a name absent from the manifest throws an InvalidArgumentException. Entries in config/bindings.php under bindings.models no longer affect model resolution.
New framework and application code should prefer direct framework model classes, or the framework model's ::modelClass() method when Laravel needs a typed class string.
Route Bindings, Morph Maps, and Observers
The model manifest keeps framework names stable even when the concrete class is overridden.
Route bindings continue to use framework route keys such as {order} and resolve the active model class. Polymorphic records keep the canonical morph key, such as OrderModel, instead of storing App\Models\Order.
Observers discovered by model name, such as App\Observers\OrderObserver or CBOX\Framework\Observers\OrderObserver, are attached to the resolved model class. Calling Order::observe(...) also forwards to the active override.
Framework model events are forwarded under the canonical event name:
eloquent.created: CBOX\Framework\Models\OrderThis lets existing listeners continue to work when an app overrides Order.
Search Indexes
Scout index settings should be configured with the framework model name, such as Product, in scout.meilisearch.model-index-settings. During boot, the manifest copies those settings to the active model class used at runtime.
When you need the concrete index name, call the framework model directly:
use CBOX\Framework\Models\Product;
$indexName = Product::make()->searchableAs();This keeps search configuration stable while still allowing an application to replace the underlying model class.
Dynamic Relationships
If you only need to add a relationship, Laravel's dynamic relationship API is still supported:
use App\Models\Ticket;
use CBOX\Framework\Models\Order;
Order::resolveRelationUsing('ticket', function ($order) {
return $order->belongsTo(Ticket::class);
});Dynamic relationships are useful for small app-only additions. Use a model override when the behavior belongs directly on the application model.