laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.5k stars 11.01k forks source link

PHP 8.4: Implicitly nullable parameter declarations deprecated #50803

Closed jnoordsij closed 7 months ago

jnoordsij commented 7 months ago

Laravel Version

any

PHP Version

8.4.0

Database Driver & Version

No response

Description

As of PHP 8.4, implicitly nullable parameter declarations will be deprecated. See also https://php.watch/versions/8.4/implicitly-marking-parameter-type-nullable-deprecated and https://wiki.php.net/rfc/deprecate-implicitly-nullable-types.

Currently, a large number of functions within this codebase still use this pattern; see also a quick example I made with rector. This should probably be adjusted.

Implementation suggestions:

Steps To Reproduce

N/A

driesvints commented 7 months ago

It's highly unlikely we'll support PHP 8.4 on Laravel v10. But if it's not too much work and there aren't any breaking changes we can give it a go. I'll try to get a CI job up soon.

jnoordsij commented 7 months ago

It's highly unlikely we'll support PHP 8.4 on Laravel v10. But if it's not too much work and there aren't any breaking changes we can give it a go. I'll try to get a CI job up soon.

It is functionally equivalent and just guessed it is probably easier to maintain by using same styling across both branches, but if it turns out that's not the case then definitely updating just 11.x sounds fine. Moreover it's only a deprecation and not a require change.

plumthedev commented 7 months ago

It is breaking change as method signature will be changed and all child classes which are overriding affected methods will throw a fatal error.

// framework class
interface Service
{
    public function func(?DateTime $date): void;
}

// application class
class FooService implements Service
{
    public function func(DateTime $date): void
    {
        echo $date->format('Y');
    }
}

// Fatal error: Declaration of FooService::func(DateTime $date): void must be compatible with Service::func(?DateTime $date): void 
(new FooService())->func(new DateTime('now'));
korkoshko commented 7 months ago

@plumthedev This isn't a BC. Your example isn't entirely accurate in this case. This applies only to parameters that default to null (they implicitly become nullable). So, int $foo = null is equal to ?int $foo = null.

Before:

// framework class
interface Service
{
    public function func(DateTime $date = null): void;
}

// application class
class FooService implements Service
{
    public function func(DateTime $date = null): void
    {
        echo $date->format('Y');
    }
}

(new FooService())->func(new DateTime('now'));

After:

// framework class
interface Service
{
    public function func(?DateTime $date = null): void;
}

// application class
class FooService implements Service
{
    public function func(DateTime $date = null): void
    {
        echo $date->format('Y');
    }
}

(new FooService())->func(new DateTime('now'));
plumthedev commented 7 months ago

Indeed you are right @korkoshko - thanks for your eagle eye 😄

crynobone commented 7 months ago

PR has been merged to 11.x branch.