Closed nathan-io closed 2 years ago
Looks like a duplicate of #17.
Thanks Matthew. I took a look at #17 and #172. I'm not understanding the relevance of #172 to this issue.
The purpose of #172 seems to be to support instantiation of enums from null
, which is not what I'm talking about here.
We're (myself and the author of #17) just talking about supporting the option to pass no value for the enum field when submitting the form, so we can keep a nullable/optional enum attribute null
if the user didn't wish to provide a value.
What would you want to store in the database in that instance?
If the enum attribute's column is nullable in the table (the only scenario I'm aware of where we'd use nullable()
in the Nova resource) I'm not understanding why we have to pass a value to store at all.
It would be just like any other nullable field. They didn't provide a value, so we don't set it on store or update. It just stays null
The problem with that approach is that when it's then read from the database (as null
), it would throw an error (BenSampo/laravel-enum#172).
I think the better approach would be to create an explicit "null" or "none" value:
final class ReasonType extends Enum
{
const None = 0;
const ReasonOne = 1;
const ReasonTwo = 2;
}
I think the better approach would be to create an explicit "null" or "none" value:
I respectfully disagree. If this is the solution, then why not just get rid of null
in every RDMS and use this "0 is the new null
" pattern on every column and data type we previously had as nullable?
Of course not. Clearly null
is incredibly useful, and I'd certainly like to be able to leverage it here.
The problem with that approach is that when it's then read from the database (as null), it would throw an error (BenSampo/laravel-enum#172).
In Tinker at least, I'm not getting an exception when accessing a null
enum attribute or saving a model with a null
enum attribute - and that's without any safety checks!
Psy Shell v0.10.8 (PHP 8.0.9 — cli) by Justin Hileman
>>> $ps = App\Models\PassStatus::first();
=> App\Models\PassStatus {#4674
id: 1,
pass_id: 1,
status: 1,
reason: null,
setter_type: "App\Models\User",
setter_id: 1,
created_at: "2021-09-25 21:06:00",
updated_at: "2021-09-25 21:06:00",
}
>>> $ps->reason
=> null
>>> $ps->reason->value
<warning>PHP Warning: Attempt to read property "value" on null in Psy Shell code on line 1</warning>
=> null
>>> $ps->save()
=> true
So the worst I got a warning. If this were production code, I'd have implemented safety checks. in whatever view, controller, etc.
Now I go into TablePlus and change the reason
value for that record to 1
. Then continue in the same Tinker session:
>>> $ps->refresh()
=> App\Models\PassStatus {#4674
id: 1,
pass_id: 1,
status: 1,
reason: 1,
setter_type: "App\Models\User",
setter_id: 1,
note: null,
created_at: "2021-09-25 21:06:00",
updated_at: "2021-09-25 21:06:00",
}
>>> $ps->reason
=> App\Enums\PassStatus\ReasonType {#4741
+value: 1,
+key: "Chargeback",
+description: "Chargeback",
}
>>>
And to confirm, I do have the cast in the model:
use App\Enums\PassStatus\StatusType;
use App\Enums\PassStatus\ReasonType;
// ...
protected $casts = [
'status' => StatusType::class,
'reason' => ReasonType::class,
];
IMO, if any attribute's corresponding table column - regardless of type - is nullable()
in the migration, the responsibility lies on the developer to handle safety checks and validation elsewhere throughout the application.
And at least looking at the CLI example above, there's nothing preventing saving a null
value to an enum attribute, or accessing a null
enum-casted value.
In one of my current projects, we're using enums in probably a dozen models. Some are nullable, and we've had no issues. Then again, we have safety checks on any nullable model attribute, which I think is just to be expected as a best practice.
By the way, I do want to say I'm very grateful for this package, it's been incredibly useful for me lately, and saved time in multiple projects. I appreciate it!
That's interesting actually. It looks like support was added for casting null
values (BenSampo/laravel-enum#152) - I missed that!
Feel free to PR a nullable()
method with tests, otherwise I should have time to do it myself in the coming days.
I totally missed #152! It's been a busy week, but I could try to give it a shot if you're not able to carve out time in the next few days.
Example:
On forms, this field is still required, and the form won't submit without a value.