@orieljs/framework 0.1.0-alpha.6 → 0.1.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +4 -0
- package/README.md +10 -1
- package/TRADEMARKS.md +33 -0
- package/dist/{chunk-ZOEPKBVF.js → chunk-4MWG3B7G.js} +1347 -428
- package/dist/chunk-4MWG3B7G.js.map +1 -0
- package/dist/{chunk-POEP4B2M.js → chunk-7ZQZYDOC.js} +745 -105
- package/dist/chunk-7ZQZYDOC.js.map +1 -0
- package/dist/{chunk-I63ZFMX6.js → chunk-GVNLZZTN.js} +1 -1
- package/dist/chunk-GVNLZZTN.js.map +1 -0
- package/dist/{chunk-MFTZQMZM.js → chunk-VOYW3R5J.js} +4 -4
- package/dist/chunk-VOYW3R5J.js.map +1 -0
- package/dist/contracts.d.ts +515 -17
- package/dist/contracts.js +1 -1
- package/dist/index.d-WQpfdIbG.d.ts +630 -0
- package/dist/index.d.ts +964 -152
- package/dist/index.js +4279 -866
- package/dist/index.js.map +1 -1
- package/dist/{jsx-runtime-CBZQYYDS.d.ts → jsx-runtime-6um4Mwfb.d.ts} +96 -5
- package/dist/jsx-runtime.d.ts +2 -2
- package/dist/jsx-runtime.js +3 -3
- package/dist/{testing-BM481Hdz.d.ts → testing-CKwfWJGn.d.ts} +180 -15
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +3 -3
- package/docs/authentication.md +487 -0
- package/docs/authorization.md +435 -0
- package/docs/cache.md +647 -0
- package/docs/collections.md +2270 -0
- package/docs/configuration.md +334 -0
- package/docs/console.md +651 -0
- package/docs/container.md +430 -0
- package/docs/controllers.md +406 -0
- package/docs/csrf.md +126 -0
- package/docs/database-testing.md +144 -0
- package/docs/database.md +236 -0
- package/docs/deployment.md +276 -0
- package/docs/eloquent-collections.md +218 -0
- package/docs/eloquent-factories.md +255 -0
- package/docs/eloquent-mutators.md +254 -0
- package/docs/eloquent-observers.md +145 -0
- package/docs/eloquent-relationships.md +557 -0
- package/docs/eloquent.md +494 -0
- package/docs/encryption.md +104 -0
- package/docs/errors.md +318 -0
- package/docs/events.md +336 -0
- package/docs/facades.md +278 -0
- package/docs/hashing.md +118 -0
- package/docs/helpers.md +1281 -0
- package/docs/http-tests.md +386 -0
- package/docs/inertia.md +485 -0
- package/docs/installation.md +209 -0
- package/docs/lifecycle.md +234 -0
- package/docs/live-tests.md +226 -0
- package/docs/live.md +910 -0
- package/docs/logging.md +255 -0
- package/docs/mail.md +619 -0
- package/docs/middleware.md +384 -0
- package/docs/migrations.md +416 -0
- package/docs/mocking.md +264 -0
- package/docs/navigation.json +273 -0
- package/docs/notifications.md +225 -0
- package/docs/pagination.md +247 -0
- package/docs/passwords.md +207 -0
- package/docs/providers.md +187 -0
- package/docs/queries.md +600 -0
- package/docs/queues.md +330 -0
- package/docs/requests.md +533 -0
- package/docs/responses.md +444 -0
- package/docs/routing.md +738 -0
- package/docs/scheduling.md +277 -0
- package/docs/seeding.md +122 -0
- package/docs/session.md +409 -0
- package/docs/starter-kits.md +396 -0
- package/docs/storage.md +192 -0
- package/docs/structure.md +264 -0
- package/docs/testing.md +165 -0
- package/docs/time-travel.md +138 -0
- package/docs/validation.md +1792 -0
- package/docs/verification.md +152 -0
- package/docs/views.md +566 -0
- package/docs/vite.md +322 -0
- package/package.json +34 -32
- package/dist/chunk-I63ZFMX6.js.map +0 -1
- package/dist/chunk-MFTZQMZM.js.map +0 -1
- package/dist/chunk-POEP4B2M.js.map +0 -1
- package/dist/chunk-ZOEPKBVF.js.map +0 -1
- package/dist/index.d-BJyJx6U1.d.ts +0 -319
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# Eloquent: mutators and casting
|
|
2
|
+
|
|
3
|
+
Accessors, mutators and casts change attribute values as your models read and write them: a JSON column comes back as
|
|
4
|
+
an object, a date as a `Date`, and a name in the case you chose.
|
|
5
|
+
|
|
6
|
+
## Introduction
|
|
7
|
+
|
|
8
|
+
A cast turns a column's stored value into the type your code works with, and back when the model is saved. An accessor
|
|
9
|
+
is a method that computes an attribute when you read it, and a mutator one that sets it when you write it.
|
|
10
|
+
|
|
11
|
+
## Accessors and mutators
|
|
12
|
+
|
|
13
|
+
### Defining an accessor
|
|
14
|
+
|
|
15
|
+
An accessor is a method named `get`, the attribute's name in StudlyCase, and `Attribute`. It receives the stored value,
|
|
16
|
+
and returns what reading the attribute gives:
|
|
17
|
+
|
|
18
|
+
```ts title="app/Models/User.ts"
|
|
19
|
+
import { Model } from '@orieljs/framework'
|
|
20
|
+
|
|
21
|
+
export class User extends Model {
|
|
22
|
+
/** Get the user's first name. */
|
|
23
|
+
getFirstNameAttribute(value: unknown): string {
|
|
24
|
+
const name = String(value ?? '')
|
|
25
|
+
|
|
26
|
+
return name.charAt(0).toUpperCase() + name.slice(1)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`user.getAttribute('first_name')` then calls it, and so does reading `user.first_name`. `model:types` keeps the column's
|
|
32
|
+
type for it; an accessor with no column, below, is typed from its return type.
|
|
33
|
+
|
|
34
|
+
An accessor can also make an attribute that has no column, computed from others:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
export class User extends Model {
|
|
38
|
+
getFullNameAttribute(): string {
|
|
39
|
+
return `${String(this.getAttribute('first_name'))} ${String(this.getAttribute('last_name'))}`
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
To have it in the model's `toArray()` and JSON, add it to `appends` (see
|
|
45
|
+
[Appending values to JSON](#appending-values-to-json)).
|
|
46
|
+
|
|
47
|
+
### Defining a mutator
|
|
48
|
+
|
|
49
|
+
A mutator is a method named `set`, the attribute's name in StudlyCase, and `Attribute`. It receives the value being
|
|
50
|
+
set, and stores what it decides in `this.attributes`:
|
|
51
|
+
|
|
52
|
+
```ts title="app/Models/User.ts"
|
|
53
|
+
import { Model } from '@orieljs/framework'
|
|
54
|
+
|
|
55
|
+
export class User extends Model {
|
|
56
|
+
/** Interact with the user's first name. */
|
|
57
|
+
setFirstNameAttribute(value: string): void {
|
|
58
|
+
this.attributes.first_name = value.toLowerCase()
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Every write goes through it: `user.first_name = 'Sally'`, `fill()`, `create()` and `update()`.
|
|
64
|
+
|
|
65
|
+
> [!NOTE]
|
|
66
|
+
> Laravel's accessors and mutators are methods returning an `Attribute` (`Attribute::make(get: …, set: …)`), or the
|
|
67
|
+
> older `getXAttribute()` and `setXAttribute()` methods. Oriel has the older form.
|
|
68
|
+
|
|
69
|
+
## Attribute casting
|
|
70
|
+
|
|
71
|
+
`casts` maps attributes to the type they are read as:
|
|
72
|
+
|
|
73
|
+
```ts title="app/Models/User.ts"
|
|
74
|
+
import { Model, type CastDefinition } from '@orieljs/framework'
|
|
75
|
+
|
|
76
|
+
export class User extends Model {
|
|
77
|
+
protected override casts: Readonly<Record<string, CastDefinition>> = {
|
|
78
|
+
is_admin: 'boolean',
|
|
79
|
+
options: 'json',
|
|
80
|
+
email_verified_at: 'datetime',
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
A model with `model:types` types each attribute from its cast: `is_admin` as a `boolean`, `email_verified_at` as a
|
|
86
|
+
`Date | null`.
|
|
87
|
+
|
|
88
|
+
| Cast | Read as | Stored as |
|
|
89
|
+
| --- | --- | --- |
|
|
90
|
+
| `int`, `integer` | A number | The number |
|
|
91
|
+
| `float`, `double`, `real` | A number | The number |
|
|
92
|
+
| `string` | A string | The string |
|
|
93
|
+
| `bool`, `boolean` | `true` or `false` | `1` or `0`, or a boolean on PostgreSQL |
|
|
94
|
+
| `array`, `json`, `object` | The parsed JSON | JSON text |
|
|
95
|
+
| `collection` | A [collection](collections.md) of the parsed JSON list | JSON text |
|
|
96
|
+
| `date` | A `Date` at midnight UTC | `'2026-03-04'` |
|
|
97
|
+
| `datetime` | A `Date` | `'2026-01-02 03:04:05'`, in UTC |
|
|
98
|
+
| `immutable_date`, `immutable_datetime` | A `Date`, as `date` and `datetime` | The same |
|
|
99
|
+
| `timestamp` | A Unix time in seconds | The date and time |
|
|
100
|
+
| `decimal:2` | A string with that many decimals, `'9.50'` | The number |
|
|
101
|
+
| `hashed` | The hash | A hash of the value, made when the model is saved |
|
|
102
|
+
|
|
103
|
+
A built-in cast of `null` stays `null`; a custom cast's `get()` receives it. The incrementing key is always cast as an
|
|
104
|
+
integer, and `created_at` and `updated_at` (and `deleted_at` with soft deletes) as datetimes.
|
|
105
|
+
|
|
106
|
+
A cast string Oriel doesn't know, such as Laravel's `datetime:Y-m-d` with a format, throws an `InvalidCastError` when
|
|
107
|
+
the attribute is read or written: "Call to undefined cast [datetime:Y-m-d] on column [launched_at] in model
|
|
108
|
+
[Product].".
|
|
109
|
+
|
|
110
|
+
### Array and JSON casting
|
|
111
|
+
|
|
112
|
+
A `json` attribute is read as the parsed value. Changing it in place counts as a change, so `save()` writes it:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
declare const user: User & { options: { theme: string } }
|
|
116
|
+
// ---cut---
|
|
117
|
+
user.options.theme = 'dark'
|
|
118
|
+
|
|
119
|
+
await user.save()
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Date casting
|
|
123
|
+
|
|
124
|
+
A date is stored in UTC, as `'2026-01-02 03:04:05'`, and read as a `Date`. In `toArray()` and JSON, dates are written
|
|
125
|
+
as Laravel writes them: `'2026-01-02T03:04:05.000000Z'`.
|
|
126
|
+
|
|
127
|
+
### Enum casting
|
|
128
|
+
|
|
129
|
+
A TypeScript enum casts an attribute to its values:
|
|
130
|
+
|
|
131
|
+
```ts title="app/Models/Server.ts"
|
|
132
|
+
import { Model, type CastDefinition } from '@orieljs/framework'
|
|
133
|
+
|
|
134
|
+
export enum ServerStatus {
|
|
135
|
+
Provisioned = 'provisioned',
|
|
136
|
+
Ready = 'ready',
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export class Server extends Model {
|
|
140
|
+
protected override casts: Readonly<Record<string, CastDefinition>> = { status: ServerStatus }
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Setting a value that isn't one of the enum's throws: "\"nope\" is not a valid backing value for the cast of [status]
|
|
145
|
+
on [Server].".
|
|
146
|
+
|
|
147
|
+
### Hashed casting
|
|
148
|
+
|
|
149
|
+
The `hashed` cast hashes a value when the model is saved, with your [hashing](hashing.md) driver, so you can set a
|
|
150
|
+
plain password:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
export class User extends Model {
|
|
154
|
+
protected override casts: Readonly<Record<string, CastDefinition>> = { password: 'hashed' }
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Until `save()`, reading the attribute gives what you set. A value that is already a hash made with your current
|
|
159
|
+
settings is kept as it is; one made with other settings is refused.
|
|
160
|
+
|
|
161
|
+
> [!NOTE]
|
|
162
|
+
> Laravel hashes as soon as you set the attribute. Hashing is asynchronous in Oriel, so it happens in `save()`, before
|
|
163
|
+
> the model's `saving` event, which sees the hash.
|
|
164
|
+
|
|
165
|
+
### Query time casting
|
|
166
|
+
|
|
167
|
+
`withCasts()` adds casts for one query, such as for a column a raw select adds:
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
const users = await User.query()
|
|
171
|
+
.select('users.*')
|
|
172
|
+
.selectRaw('(select max(created_at) from posts where posts.author_id = users.id) as last_posted_at')
|
|
173
|
+
.withCasts({ last_posted_at: 'datetime' })
|
|
174
|
+
.get()
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
> [!NOTE]
|
|
178
|
+
> Laravel's encrypted casts, `AsArrayObject`, `AsCollection`, `AsStringable`, `AsEnumCollection` and castable value
|
|
179
|
+
> objects aren't in Oriel; write a custom cast for them.
|
|
180
|
+
|
|
181
|
+
## Custom casts
|
|
182
|
+
|
|
183
|
+
A custom cast is a class with a `get()` method, which turns the stored value into what the model gives, and a `set()`
|
|
184
|
+
method, which turns a value back into what is stored. `make:cast` writes one in `app/Casts`:
|
|
185
|
+
|
|
186
|
+
```sh
|
|
187
|
+
node oriel make:cast Money
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
```ts title="app/Casts/Money.ts"
|
|
191
|
+
import type { CastsAttributes } from '@orieljs/framework'
|
|
192
|
+
|
|
193
|
+
/** A price kept in cents, read in units: 1234 is 12.34. */
|
|
194
|
+
export class Money implements CastsAttributes<number, number> {
|
|
195
|
+
get(_model: object, _key: string, value: unknown): number {
|
|
196
|
+
return Number(value) / 100
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
set(_model: object, _key: string, value: number): unknown {
|
|
200
|
+
return Math.round(value * 100)
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Name the class in `casts`, or give an instance:
|
|
206
|
+
|
|
207
|
+
```ts title="app/Models/Product.ts"
|
|
208
|
+
// @filename: app/Casts/Money.ts
|
|
209
|
+
import type { CastsAttributes } from '@orieljs/framework'
|
|
210
|
+
export declare class Money implements CastsAttributes<number, number> {
|
|
211
|
+
get(model: object, key: string, value: unknown): number
|
|
212
|
+
set(model: object, key: string, value: number): unknown
|
|
213
|
+
}
|
|
214
|
+
// ---cut---
|
|
215
|
+
import { Model, type CastDefinition } from '@orieljs/framework'
|
|
216
|
+
import { Money } from '../Casts/Money'
|
|
217
|
+
|
|
218
|
+
export class Product extends Model {
|
|
219
|
+
protected override casts: Readonly<Record<string, CastDefinition>> = { price: Money }
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Both methods also receive the model, the attribute's name and all its stored attributes.
|
|
224
|
+
|
|
225
|
+
## Serialization
|
|
226
|
+
|
|
227
|
+
### Hiding attributes from JSON
|
|
228
|
+
|
|
229
|
+
`hidden` lists the attributes left out of the model's `toArray()` and JSON, such as a password, and `visible` lists
|
|
230
|
+
the only ones left in:
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
export class User extends Model {
|
|
234
|
+
protected override hidden = ['password', 'remember_token']
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`makeVisible()` and `makeHidden()` change the lists for one model: `user.makeVisible('password').toArray()`.
|
|
239
|
+
|
|
240
|
+
### Appending values to JSON
|
|
241
|
+
|
|
242
|
+
An accessor with no column isn't in `toArray()` and JSON unless you add it to `appends`:
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
export class User extends Model {
|
|
246
|
+
protected override appends = ['is_admin']
|
|
247
|
+
|
|
248
|
+
getIsAdminAttribute(): boolean {
|
|
249
|
+
return this.getAttribute('role') === 'admin'
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
`append()` adds one for one model: `user.append('is_admin').toArray()`.
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Eloquent: observers
|
|
2
|
+
|
|
3
|
+
Models dispatch events as they are created, updated, deleted and restored. Listen for them with a closure, or group
|
|
4
|
+
the listeners for one model in an observer class.
|
|
5
|
+
|
|
6
|
+
## Introduction
|
|
7
|
+
|
|
8
|
+
A model dispatches these events, each with the model:
|
|
9
|
+
|
|
10
|
+
| Event | When |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| `retrieved` | A model was read from the database |
|
|
13
|
+
| `creating`, `created` | A new model is about to be saved for the first time, and was |
|
|
14
|
+
| `updating`, `updated` | A model that exists is about to be saved with changes, and was |
|
|
15
|
+
| `saving`, `saved` | A model is about to be saved, new or not, changed or not, and was |
|
|
16
|
+
| `deleting`, `deleted` | A model is about to be deleted, or soft-deleted, and was |
|
|
17
|
+
| `restoring`, `restored` | A soft-deleted model is about to be restored, and was |
|
|
18
|
+
| `forceDeleting`, `forceDeleted` | A soft-deleted model is about to be deleted for good, and was |
|
|
19
|
+
|
|
20
|
+
Creating a model dispatches `saving`, `creating`, `created`, then `saved`; updating one dispatches `saving`,
|
|
21
|
+
`updating`, `updated`, then `saved`. Saving a model with no changes dispatches only `saving` and `saved`.
|
|
22
|
+
|
|
23
|
+
A listener of a `-ing` event that returns `false` stops the operation: the model isn't saved, deleted or restored.
|
|
24
|
+
|
|
25
|
+
> [!WARNING]
|
|
26
|
+
> A query's `update()` and `delete()`, such as `Post.where('active', 0).delete()`, write the rows directly: no model
|
|
27
|
+
> is read, and no event is dispatched.
|
|
28
|
+
|
|
29
|
+
## Using closures
|
|
30
|
+
|
|
31
|
+
Register a closure for an event in the model's static `booted()`, with the method named after the event:
|
|
32
|
+
|
|
33
|
+
```ts title="app/Models/User.ts"
|
|
34
|
+
import { Model } from '@orieljs/framework'
|
|
35
|
+
|
|
36
|
+
export class User extends Model {
|
|
37
|
+
/** The "booted" method of the model. */
|
|
38
|
+
static override booted(): void {
|
|
39
|
+
this.created((user) => {
|
|
40
|
+
// ...
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`booted()` runs once, the first time the model is used in your app.
|
|
47
|
+
|
|
48
|
+
## Observers
|
|
49
|
+
|
|
50
|
+
### Defining observers
|
|
51
|
+
|
|
52
|
+
An observer is a class whose methods are named after the events they handle. `make:observer` writes one in
|
|
53
|
+
`app/Observers`, with `created()`, `updated()` and `deleted()` methods; give their parameter your model's type:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
node oriel make:observer UserObserver
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```ts title="app/Observers/UserObserver.ts"
|
|
60
|
+
import type { User } from '../Models/User'
|
|
61
|
+
|
|
62
|
+
export class UserObserver {
|
|
63
|
+
/** Handle the User "created" event. */
|
|
64
|
+
created(user: User): void {
|
|
65
|
+
// ...
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Handle the User "updated" event. */
|
|
69
|
+
updated(user: User): void {
|
|
70
|
+
// ...
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Handle the User "deleted" event. */
|
|
74
|
+
deleted(user: User): void {
|
|
75
|
+
// ...
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Register it with the model's `observe()`, in a service provider's `boot()`:
|
|
81
|
+
|
|
82
|
+
```ts title="app/Providers/AppServiceProvider.ts"
|
|
83
|
+
// @filename: app/Observers/UserObserver.ts
|
|
84
|
+
export declare class UserObserver {}
|
|
85
|
+
// ---cut---
|
|
86
|
+
import { ServiceProvider } from '@orieljs/framework'
|
|
87
|
+
import { User } from '../Models/User'
|
|
88
|
+
import { UserObserver } from '../Observers/UserObserver'
|
|
89
|
+
|
|
90
|
+
export class AppServiceProvider extends ServiceProvider {
|
|
91
|
+
override boot(): void {
|
|
92
|
+
User.observe(UserObserver)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Every method named after an event is registered. Oriel makes the observer through your app's container, so it can take
|
|
98
|
+
a service with `inject()`; an instance works too: `User.observe(new UserObserver())`.
|
|
99
|
+
|
|
100
|
+
A `-ing` method that returns `false` cancels the operation, as a closure does:
|
|
101
|
+
|
|
102
|
+
```ts title="app/Observers/PostObserver.ts"
|
|
103
|
+
import { Str } from '@orieljs/framework'
|
|
104
|
+
import type { Post } from '../Models/Post'
|
|
105
|
+
|
|
106
|
+
export class PostObserver {
|
|
107
|
+
/** Give a new post its slug. */
|
|
108
|
+
creating(post: Post): void {
|
|
109
|
+
post.slug = Str.slug(post.title)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** A published post can't be deleted. */
|
|
113
|
+
deleting(post: Post): boolean {
|
|
114
|
+
return post.published_at === null
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
> [!NOTE]
|
|
120
|
+
> Laravel registers an observer with an attribute on the model (`#[ObservedBy]`), and can run its methods after the
|
|
121
|
+
> transaction commits (`ShouldHandleEventsAfterCommit`). Oriel registers observers with `observe()`, and runs them as
|
|
122
|
+
> the events happen. Laravel's `trashed` and `replicating` events aren't in Oriel.
|
|
123
|
+
|
|
124
|
+
### Event names
|
|
125
|
+
|
|
126
|
+
A model event is dispatched as `eloquent.<event>: <Model>`, such as `eloquent.created: User`, so you can also listen
|
|
127
|
+
for it with `Event.listen()`. Laravel uses the model's full class name; Oriel uses the class's name.
|
|
128
|
+
|
|
129
|
+
## Muting events
|
|
130
|
+
|
|
131
|
+
`Model.withoutEvents()` runs a function with model events off, for the code it runs:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
const user = await Model.withoutEvents(() => User.findOrFail(1))
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`saveQuietly()` and `deleteQuietly()` save or delete one model without events:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
const user = await User.findOrFail(1)
|
|
141
|
+
|
|
142
|
+
user.name = 'Victoria Faith'
|
|
143
|
+
|
|
144
|
+
await user.saveQuietly()
|
|
145
|
+
```
|