use Modules\Blog\Models\Post;
$post = model(Post::class)
->create()
->fill([
'title' => 'Quantum 3.0',
'slug' => 'quantum-3',
'body' => 'Package notes',
'author_id' => 7,
]);
$post->save();What happens here:
create()starts a new record context and clears current attributes.fill()applies only allowed fields.save()copies attributes into the ORM.- If the adapter generated a primary key, the model receives it back after save.
- If
HasTimestampsis used,updated_atis refreshed on every save, whilecreated_atis filled on the first save unless you already set it.
$posts = model(Post::class)
->criteria('status', '=', 'published')
->orderBy('created_at', 'desc')
->limit(10)
->get();This returns a ModelCollection, not a plain array.
Useful collection methods:
all()count()first()last()isEmpty()
Use a fresh model instance for unrelated queries to avoid carrying accidental query state.
DbModel query methods mutate the current model instance.
That means this pattern is safer:
$published = model(Post::class)
->criteria('status', '=', 'published')
->get();
$drafts = model(Post::class)
->criteria('status', '=', 'draft')
->get();Instead of continuing to reuse one already-filtered model instance across unrelated queries.
use Quantum\Database\Enums\Relation;
class Post extends DbModel
{
public function relations(): array
{
return [
User::class => [
'type' => Relation::BELONGS_TO,
'foreign_key' => 'author_id',
'local_key' => 'id',
],
];
}
}Then query with:
$posts = model(Post::class)
->joinTo(model(User::class))
->select('posts.*')
->get();Keep relation definitions explicit. Include type, foreign_key, and local_key for each joined model.
$paginator = model(Post::class)
->criteria('status', '=', 'published')
->paginate(15, 2);
$items = $paginator->data();
$total = $paginator->total();The paginator clones the model and ORM for the total-count query so total calculation does not mutate the live query before page data is fetched.
$post = model(Post::class)->findOne(10);
$post?->delete();
$active = model(Post::class)->get();
$all = model(Post::class)->withTrashed()->get();
$trashed = model(Post::class)->onlyTrashed()->get();Behavior to remember:
delete()becomes a soft delete when the trait is usedforceDelete()performs the real deleterestore()clears the deleted-at valuewithTrashed()changes later reads on that same model instance- Reusing one soft-delete builder across several reads keeps the accumulated scope on that builder, so a fresh model instance is the cleanest start for each query
use Quantum\Model\Model;
class PublishPayload extends Model
{
protected array $fillable = ['title', 'slug'];
public array $hidden = ['slug'];
}
$payload = (new PublishPayload())->fill([
'title' => 'Hello',
'slug' => 'hello',
]);
$data = $payload->asArray();Here asArray() returns only visible fields, while slug is still stored on the object.
new Post()does not attach an ORM instance by itself.fill()rejects unknown fields instead of ignoring them.- Direct assignment bypasses
fillablerules. create()clears existing attributes.- Soft-delete inclusion flags stay on the current model instance until you discard it.
- A fresh builder is the simplest way to avoid carrying earlier soft-delete scope into later reads.