Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[11.x] Add typed getters for configuration #50140

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

Merged
merged 9 commits into from
Feb 25, 2024

Conversation

AlexandreGerault
Copy link
Contributor

Hi

I've been struggling sometimes with Laravel and Larastan on high levels (8 & 9 mostly). Indeed, the configuration helper config give values as mixed which requires annotation or assertion each time it is used to satisfy static analysis. It gives this kind of errors:

Parameter #1 $config of method Class::method() expects array, mixed given.

I think it can be great to have, like the Request object, typed getters, like ->string($key);, ->integer($key); etc.

This would make it much more easier to satisfy static analysis. Only array might be complaining sometimes.

@henzeb
Copy link
Contributor

henzeb commented Feb 18, 2024

interesting idea. But the Contract changes are breaking ones. If this wants to be added, this should be done in a major version like 11.

@AlexandreGerault
Copy link
Contributor Author

Thanks for the answer. I wonder how the contracts are breaking changes since I just added new methods 🤔 Is the contract used somewhere else?

@driesvints
Copy link
Member

Is the contract used somewhere else?

That's the whole point of a contract 🙂 so it can be used somewhere else. Can you revert the changes to the contract and mark this as ready?

@driesvints driesvints marked this pull request as draft February 19, 2024 00:56
@AlexandreGerault
Copy link
Contributor Author

I can but how do we make sure the contract would be updated on the next major release and won't be forgotten?

Is that a good idea to merge without the contract being changed?

@driesvints
Copy link
Member

To be fair. I don’t think this pr will get accepted as it’s easy enough to typecast. I feel like this is a bit of feature creep. You can either remove the changes to the contract here, mark the pr as ready for review or sent it in to master.

@AlexandreGerault AlexandreGerault changed the base branch from 10.x to master February 19, 2024 08:31
@AlexandreGerault
Copy link
Contributor Author

AlexandreGerault commented Feb 19, 2024

I think it's worth to have these methods, as we do for request.

Nowadays we often tend to use static analysis tools to improve our codebase quality and spot bugs before it can ever happen. Using the config helper will always bring error on strict Larastan configuration as it returns mixed.

Today the only way to make sure we comply with strict static analysis is to either use annotation to type the return of config calls, either to use assertions everytime we use the config helper. In my opinion this can become cumbersome very quickly.

Instead of doing this:

$normalizers = config('serializer.normalizers');

Assert::isArray($normalizers); // works for static analysis when having the webmozart/assert extension installed

Serializer::make($normalizers);

or

$normalizers = config('serializer.normalizers');

if (!is_array($normalizers)) {
    throw new InvalidArgumentException("The normalizers config must be an array");
 }
 
Serializer::make($normalizers);

We can do

Serializer::make(config()->array('serializer.normalizers'));

This make it so much easier on a larger codebase and also clearer to read.

Maybe I'm wrong but I don't see any real drawbacks with this 🤔

EDIT: I know it's also possible to just type hint with annotations like so:

/** @var array $normalizers */
$normalizers = config('serializer.normalizers');
 
Serializer::make($normalizers);

But I believe it's still cumbersome to this every time. Yet I understand your point of it being feature creep 😄
I just thought Laravel was going more typed so I thought this could be a good idea

@AlexandreGerault AlexandreGerault marked this pull request as ready for review February 19, 2024 08:39
@AlexandreGerault
Copy link
Contributor Author

I just rebased the branch correctly so it doesn't include commits from 10.x 😅

@AlexandreGerault AlexandreGerault changed the title [10.x] Add typed getters for configuration [11.x] Add typed getters for configuration Feb 19, 2024
@taylorotwell
Copy link
Member

taylorotwell commented Feb 19, 2024

I think you can just drop the methods from the contract entirely and only put them on the repository. 👍 Also you need docblocks like the rest of the framework for consistency. Please mark as ready for review again when you want me to take another look.

@taylorotwell taylorotwell marked this pull request as draft February 19, 2024 15:37
@AlexandreGerault
Copy link
Contributor Author

AlexandreGerault commented Feb 19, 2024

I think you can just drop the methods from the contract entirely and only put them on the repository. 👍 Also you need docblocks like the rest of the framework for consistency. Please mark as ready for review again when you want me to take another look.

Should I also support the default parameter in the methods? Just realized now, but I think it makes sens. However I don't think it makes sens to support many keys here 🤔

/**
 * Get the specified configuration value typed as a string.
 * If the value isn't a string it should throw an exception.
 *
 * @param  string  $key
 * @param  ?string  $default
 * @return string
 */
public function string(string $key, ?string $default = null): string
{
    $value = $this->get($key, $default);

    if (! is_string($value)) {
        throw new \InvalidArgumentException(
            sprintf('Configuration value for key [%s] must be a string, %s given.', $key, gettype($value))
        );
    }

    return $value;
}

@AlexandreGerault AlexandreGerault marked this pull request as ready for review February 19, 2024 16:57
@AlexandreGerault
Copy link
Contributor Author

I think default values can be added on a next PR if that's not the moment 😄

@taylorotwell taylorotwell merged commit 6802941 into laravel:master Feb 25, 2024
@AlexandreGerault AlexandreGerault deleted the feature/typed-config branch February 26, 2024 08:35
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
Morty Proxy This is a proxified and sanitized view of the page, visit original site.