Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: add isSet() method to identify properties without a value #11

Merged
merged 3 commits into from
May 10, 2024

Conversation

stratease
Copy link
Contributor

@stratease stratease commented May 3, 2024

Avoid a false positive in fetching defaults with a check that validates whether one is truly set or not. This avoids situations where we might force a null into a database, instead of allowing the MySQL default to take precedence.

@stratease stratease self-assigned this May 3, 2024
@stratease stratease requested a review from borkweb May 3, 2024 22:24
@stratease stratease marked this pull request as ready for review May 3, 2024 22:37
@JasonTheAdams
Copy link
Contributor

Hi @stratease!

I like this. I want to think through it a bit. The isset() function considers null to be a non-value. So I believe the following reveals the value isn't set:

class Foo extends Model
{
  protected $properties = [
    "bar" => "int"
  ];
}

$foo = new Foo();
isset($foo->bar); // false

Now it's not possible to know from this method whether a value started as null or was made null after the fact. For example, a model could be retrieved from the database, a property made null, and then the model saved. Or it could be a new model with a property explicitly set as null.

It looks like you're using array_key_exists to circumvent this. I'm confused by the [1] present and the hard-coded 1 check. What's going on there?

@stratease
Copy link
Contributor Author

stratease commented May 10, 2024

Hi @stratease!

I like this. I want to think through it a bit. The isset() function considers null to be a non-value. So I believe the following reveals the value isn't set:

class Foo extends Model
{
  protected $properties = [
    "bar" => "int"
  ];
}

$foo = new Foo();
isset($foo->bar); // false

Now it's not possible to know from this method whether a value started as null or was made null after the fact. For example, a model could be retrieved from the database, a property made null, and then the model saved. Or it could be a new model with a property explicitly set as null.

Correct, I'm with you there. Lots of nuance around checking an explicitly set null versus one that hasn't been set.

It looks like you're using array_key_exists to circumvent this. I'm confused by the [1] present and the hard-coded 1 check. What's going on there?

Not sure the "why" but it appears we define a default with this shape 'firstName' => [ 'string', 'Michael' ] see our test Model. This is to determine we explicitly have a default defined or nothing.

Thoughts?

@JasonTheAdams
Copy link
Contributor

Not sure the "why" but it appears we define a default with this shape 'firstName' => [ 'string', 'Michael' ] see our test Model. This is to determine we explicitly have a default defined or nothing.

Ohhh! Right, hahah! I was thinking about the wrong thing. That's just a visual syntax sort of thing.

My suggestion is to make hasDefault a protected function, and add an $model->isSet('foo') function that uses array_key_exists on $this->attributes[] to actually know the difference between whether a model is truly missing a property value.

@stratease
Copy link
Contributor Author

Updated per comments.

Copy link
Contributor

@JasonTheAdams JasonTheAdams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awesome! What a great addition, @stratease! 🙌

@stratease stratease merged commit 7c21d23 into main May 10, 2024
1 check passed
@stratease stratease deleted the fix/nullable-default-conflict-with-mysql-default branch May 10, 2024 21:20
@JasonTheAdams JasonTheAdams changed the title Bug fix for fetching set of defaults, don't always add a null. Feature: add isSet() method to identify properties without a value May 10, 2024
@JasonTheAdams
Copy link
Contributor

@stratease I'm trying to think. Is this change backwards-breaking in any way? I don't think so. We're not setting a null value in attributes anymore for every property upon instantiation. But I don't think it actually changes the behavior of any public methods. 🤔

@stratease
Copy link
Contributor Author

stratease commented May 10, 2024

@stratease I'm trying to think. Is this change backwards-breaking in any way? I don't think so. We're not setting a null value in attributes anymore for every property upon instantiation. But I don't think it actually changes the behavior of any public methods. 🤔

@JasonTheAdams I don't think it will but there might be a possibility if we assume it will always fill undefined attributes with a null, now it won't. I think toArray() will only return what was explicitly set now, and not every property regardless of what was hydrated. Which was the intended result.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants