Jump to content

PHP-8's constructor property promotion


NotionCommotion
 Share

Recommended Posts

The following PHP-7 code

class CustomerDTO
{
    public string $name;

    public string $email;

    public DateTimeImmutable $birth_date;

    public function __construct(
        string $name, 
        string $email, 
        DateTimeImmutable $birth_date
    ) {
        $this->name = $name;
        $this->email = $email;
        $this->birth_date = $birth_date;
    }
}


can be written this way by using PHP-8's constructor property promotion:

class CustomerDTO
{
    public function __construct(
        public string $name, 
        public string $email, 
        public DateTimeImmutable $birth_date,
    ) {}
}

How should the following PHP-7 code be modified to utilize PHP-8's constructor property promotion? Specifically:

  1. How should the Column and Groups attributes be applied to $createAt?
  2. How is $createAt's default value set to new DateTimeImmutable()?
<?php

namespace App\Entity;

use Doctrine\ORM\Mapping\Column;
use Symfony\Component\Serializer\Annotation\Groups;
use DateTimeImmutable;

class SomeClass
{
    /**
     * @var class-string<DateTimeImmutable>|mixed|null
     */
    #[Column(type: 'datetime_immutable')]
    #[Groups(['version:read'])]
    private $createAt;

    public function __construct()
    {
        $this->createAt = new DateTimeImmutable;
    }
}

 

Link to comment
Share on other sites

Also, creating the DateTimeImmutable object within the constructor couples the SomeClass with DateTimeImmutable. If you decide at a later date to switch from plain PHP to Carbon (for instance), you've got a ton of code to change.

That's pretty much antithetical to dependency injection which - as I understand it - is the entire point of property promotion.

Link to comment
Share on other sites

13 hours ago, maxxd said:

Also, creating the DateTimeImmutable object within the constructor couples the SomeClass with DateTimeImmutable. If you decide at a later date to switch from plain PHP to Carbon (for instance), you've got a ton of code to change.

That's pretty much antithetical to dependency injection which - as I understand it - is the entire point of property promotion.

I was going to say that Symony's entity maker adds it but just realized I have been adding it since I read somewhere that I should.   That being said, I see your point and agree and will no longer do so.  Thanks!

 

15 hours ago, requinix said:

Promoted properties are also arguments to the constructor. Your constructor has no arguments. The rest isn't important.

Okay, what about the following:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping\Column;
use Symfony\Component\Serializer\Annotation\Groups;
use DateTimeImmutable;

class SomeClass
{
    /**
     * @var class-string<DateTimeImmutable>|mixed|null
     */
    #[Column(type: 'datetime_immutable')]
    #[Groups(['version:read'])]
    private $createAt;

    public function __construct(DateTimeImmutable $createAt)
    {
        $this->createAt = $createAt;
    }
}

I don't have the issue regarding setting $createAt's default value as maxxd corrected me that I shouldn't be doing so in the first place, but still have the issue regarding needing to apply attributes and not being able to declare the property twice.

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping\Column;
use Symfony\Component\Serializer\Annotation\Groups;
use DateTimeImmutable;

class SomeClass
{
    /**
     * @var class-string<DateTimeImmutable>|mixed|null
     */
    #[Column(type: 'datetime_immutable')]
    #[Groups(['version:read'])]
    private $createAt;

    public function __construct(
        private DateTimeImmutable $createAt,
    ) {}
}

Actually, I just stumbled upon the solution.  I don't believe I've seen it documented but it works.

class SomeClass
{

    public function __construct(
        #[Column(type: 'datetime_immutable')]
        #[Groups(['version:read'])]
        private DateTimeImmutable $createAt,
    ) {}
}

 

Link to comment
Share on other sites

3 hours ago, NotionCommotion said:

Actually, I just stumbled upon the solution.  I don't believe I've seen it documented but it works.

class SomeClass
{

    public function __construct(
        #[Column(type: 'datetime_immutable')]
        #[Groups(['version:read'])]
        private DateTimeImmutable $createAt,
    ) {}
}

 

It's in there.

Link to comment
Share on other sites

Oh. Also, when it comes to new features, if you're not sure where in the manual you have to look to find more information about them, try the RFC list.

https://wiki.php.net/rfc

Constructor Property Promotion's mentions the different ways it could handle attributes, and that it opts for making attributes on arguments apply both to the arguments and the promoted properties.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.