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

Refactor resolving of null information for custom casted attribute types #1330

Merged
merged 2 commits into from
Feb 20, 2023

Conversation

wimski
Copy link
Contributor

@wimski wimski commented Mar 11, 2022

Summary

Let's say we have the following custom cast:

class MyCustomCast implements CastsAttributes
{
    /**
     * @param Model                $model
     * @param string               $key
     * @param mixed                $value
     * @param array<string, mixed> $attributes
     * @return SomeObject|null
     */
    public function get($model, string $key, $value, $attributes): ?SomeObject
    {
        if ($value === null) {
            return null;
        }

        return new SomeObject($value);
    }

    // setter omitted from example for brevity
}

Now suppose we have two pretty much identical models which use this cast:

class ModelA extends Model
{
    protected $table = 'models_a';

    /**
     * @var array<string, string>
     */
    protected $casts = [
        'casted_column' => MyCustomCast::class,
    ];
}
class ModelB extends Model
{
    protected $table = 'models_b';

    /**
     * @var array<string, string>
     */
    protected $casts = [
        'casted_column' => MyCustomCast::class,
    ];
}

These models have tables created with the following migrations:

Schema::create('models_a', function (Blueprint $table) {
	$table->id();
	$table->string('casted_column');
	$table->timestamps();
});
Schema::create('models_b', function (Blueprint $table) {
	$table->id();
	$table->string('casted_column')->nullable();
	$table->timestamps();
});

The only difference between A and B is the nullable() setting on the column. Based on that difference I would expect the following properties to be written by the IDE helper:

/**
 * @property SomeObject $casted_column
 */
class ModelA extends Model
/**
 * @property SomeObject|null $casted_column
 */
class ModelB extends Model

However, both models will receive SomeObject|null as the property type, because currently the IDE helper only check the cast class without taking the migration into account. In my opinion the migration should inform the possibility of a null value and not the cast, because the cast doesn't know anything about the column it's going to be used for and should always implement X|null.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

In my opnion this is a fix for behaviour that was always incorrect, but because it changes behaviour (and outcome), I do consider it a breaking change. I'll let it up to the maintainers how they want to deal with this.

Checklist

  • Existing tests have been adapted and/or new tests have been added
  • Add a CHANGELOG.md entry
  • Update the README.md
  • Code style has been fixed via composer fix-style

@wimski wimski marked this pull request as ready for review March 11, 2022 13:40
Comment on lines -31 to +32
* @property array|null $casted_property_with_return_primitive_docblock
* @property array|null $casted_property_with_return_nullable_primitive
* @property array $casted_property_with_return_primitive_docblock
* @property array $casted_property_with_return_nullable_primitive
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is this changed? Is it intentional based on the fix? Thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this is intentional. I didn't change the migration for these properties and they weren't marked as nullable(), so the |null gets removed by the fix in this PR.

@daniel-de-wit
Copy link
Contributor

@mfn Can you please take another look at this?

Copy link
Collaborator

@mfn mfn left a comment

Choose a reason for hiding this comment

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

applyNullability make my head hurt but me feel is this is a "LGTM"!

@mfn
Copy link
Collaborator

mfn commented Feb 18, 2023

@wimski can you please update the changelog too?

@barryvdh barryvdh merged commit 9f97f7c into barryvdh:master Feb 20, 2023
@wimski wimski deleted the refactor/nullable-types-with-cast branch February 20, 2023 08:37
@barryvdh
Copy link
Owner

Added to changelog in aa1aa66
Thanks!

@mfn mfn mentioned this pull request Jan 28, 2024
9 tasks
d3v2a pushed a commit to d3v2a/laravel-ide-helper that referenced this pull request Feb 16, 2024
…pes (barryvdh#1330)

* Refactor resolving of null information for custom casted attribute types

* composer fix-style

---------

Co-authored-by: laravel-ide-helper <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants