127 lines
4.1 KiB
Markdown
127 lines
4.1 KiB
Markdown
# Field Writability
|
|
|
|
By default, fields are read-only. You can allow a field to be written to in `PATCH` and `POST` requests using the `writable` and `readonly` methods.
|
|
|
|
You can optionally supply a closure to these methods which will receive the model instance, and should return a boolean value.
|
|
|
|
For example, the following schema will make an email attribute that is only writable by the self:
|
|
|
|
```php
|
|
$type->attribute('email')
|
|
->writable(function ($model, Context $context) {
|
|
return $model->id === $context->getRequest()->getAttribute('userId');
|
|
});
|
|
```
|
|
|
|
## Writable Once
|
|
|
|
You may want a field to only be writable when creating a new resource, but not when an existing resource is being updated. This can be achieved by calling the `once` method:
|
|
|
|
```php
|
|
$type->hasOne('author')
|
|
->writable()->once();
|
|
```
|
|
|
|
## Default Values
|
|
|
|
You can provide a default value to be used when creating a new resource if there is no value provided by the consumer. Pass a value or a closure to the `default` method:
|
|
|
|
```php
|
|
$type->attribute('joinedAt')
|
|
->default(new DateTime);
|
|
|
|
$type->attribute('ipAddress')
|
|
->default(function (Context $context) {
|
|
return $context->getRequest()->getServerParams()['REMOTE_ADDR'] ?? null;
|
|
});
|
|
```
|
|
|
|
::: tip
|
|
If you're using Eloquent, you could also define [default attribute values](https://laravel.com/docs/8.x/eloquent#default-attribute-values) to achieve a similar thing. However, the Request instance will not be available in this context.
|
|
:::
|
|
|
|
## Validation
|
|
|
|
You can ensure that data provided for a field is valid before the resource is saved. Provide a closure to the `validate` method, and call the first argument if validation fails:
|
|
|
|
```php
|
|
$type->attribute('email')
|
|
->validate(function (callable $fail, $value, $model, Context $context) {
|
|
if (! filter_var($value, FILTER_VALIDATE_EMAIL)) {
|
|
$fail('Invalid email');
|
|
}
|
|
});
|
|
```
|
|
|
|
::: tip
|
|
You can easily use Laravel's [Validation](https://laravel.com/docs/8.x/validation) component for field validation with the [`rules` helper function](laravel.md#validation).
|
|
:::
|
|
|
|
This works for relationships, too. The related models will be retrieved via your adapter and passed into your validation function.
|
|
|
|
```php
|
|
$type->hasMany('groups')
|
|
->validate(function (callable $fail, array $groups, $model, Context $context) {
|
|
foreach ($groups as $group) {
|
|
if ($group->id === 1) {
|
|
$fail('You cannot assign this group');
|
|
}
|
|
}
|
|
});
|
|
```
|
|
|
|
## Transformers
|
|
|
|
Use the `transform` method on an attribute to mutate any incoming value before it is saved to the model.
|
|
|
|
```php
|
|
$type->attribute('firstName')
|
|
->transform(function ($value, Context $context) {
|
|
return ucfirst($value);
|
|
});
|
|
```
|
|
|
|
::: tip
|
|
If you're using Eloquent, you could also define attribute [casts](https://laravel.com/docs/8.x/eloquent-mutators#attribute-casting) or [mutators](https://laravel.com/docs/8.x/eloquent-mutators#defining-a-mutator) on your model to achieve a similar thing.
|
|
:::
|
|
|
|
## Setters
|
|
|
|
Use the `set` method to define custom mutation logic for your field, instead of just setting the value straight on the model property.
|
|
|
|
```php
|
|
$type->attribute('firstName')
|
|
->set(function ($value, $model, Context $context) {
|
|
$model->first_name = ucfirst($value);
|
|
if ($model->first_name === 'Toby') {
|
|
$model->last_name = 'Zerner';
|
|
}
|
|
});
|
|
```
|
|
|
|
## Savers
|
|
|
|
If your field corresponds to some other form of data storage rather than a simple property on your model, you can use the `save` method to provide a closure that will be run _after_ your model has been successfully saved. If specified, the adapter will NOT be used to set the field on the model.
|
|
|
|
```php
|
|
$type->attribute('locale')
|
|
->save(function ($value, $model, Context $context) {
|
|
$model->preferences()
|
|
->where('key', 'locale')
|
|
->update(['value' => $value]);
|
|
});
|
|
```
|
|
|
|
## Events
|
|
|
|
### `saved`
|
|
|
|
Run after a field has been successfully saved.
|
|
|
|
```php
|
|
$type->attribute('email')
|
|
->saved(function ($value, $model, Context $context) {
|
|
event(new EmailWasChanged($model));
|
|
});
|
|
```
|