Description
Description
The current implementation of read-only status for fields in the LaravelJsonApi\Eloquent\Fields\Concerns\IsReadOnly
trait makes it challenging to determine which specific read-only method (readOnly()
, readOnlyOnCreate()
, or readOnlyOnUpdate()
) has been called on a field. This lack of clarity can lead to difficulties in debugging and maintaining code, especially in complex schemas. This also makes it hard to create your own custom endpoints, that makes use of the attribute rules defined within the Schema.
Current Behavior
Currently, the read-only status is stored in a private property $readOnly
as either a boolean or a Closure. The isReadOnly()
method then evaluates this property to determine if a field is read-only. While functional, this approach doesn't provide an easy way to identify which specific read-only method was used.
/**
* Whether the field is read-only.
*
* @var Closure|bool
*/
private $readOnly = false;
/**
* Mark the field as read-only.
*
* @param Closure|bool $callback
* @return $this
*/
public function readOnly($callback = true): self
{
if (!is_bool($callback) && !$callback instanceof Closure) {
throw new InvalidArgumentException('Expecting a boolean or closure.');
}
$this->readOnly = $callback;
return $this;
}
/**
* Mark the field as read only when the resource is being created.
*
* @return $this
*/
public function readOnlyOnCreate(): self
{
$this->readOnly(static fn($request) => $request && $request->isMethod('POST'));
return $this;
}
/**
* Mark the field as read only when the resource is being updated.
*
* @return $this
*/
public function readOnlyOnUpdate(): self
{
$this->readOnly(static fn($request) => $request && $request->isMethod('PATCH'));
return $this;
}
Proposed Solution
To improve this, we could introduce a new property that explicitly tracks which read-only method was called. Here's a suggested implementation:
private $readOnlyType = null;
public function readOnly($callback = true): self
{
// ... existing implementation ...
$this->readOnlyType = 'always';
return $this;
}
public function readOnlyOnCreate(): self
{
// ... existing implementation ...
$this->readOnlyType = 'onCreate';
return $this;
}
public function readOnlyOnUpdate(): self
{
// ... existing implementation ...
$this->readOnlyType = 'onUpdate';
return $this;
}
public function getReadOnlyType(): ?string
{
return $this->readOnlyType;
}
This approach would allow developers to easily check which read-only method was called on a field:
$field = Number::make('target_value')->readOnlyOnUpdate();
echo $field->getReadOnlyType(); // Outputs: 'onUpdate'
Benefits
- Improved debugging: Developers can quickly identify which read-only method was applied to a field.
- Better introspection: Schemas become more self-documenting, as the read-only behavior of each field is explicitly tracked.
- Easier maintenance: Changes to read-only behavior become more transparent and easier to manage.
Potential Impact
This change would be backwards-compatible, as it doesn't alter the existing behavior of the isReadOnly() method. It only adds new functionality to improve developer experience.
(Claude 3.5 Sonnet, has been used to help formulate this)