NotionCommotion Posted September 19, 2021 Share Posted September 19, 2021 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: How should the Column and Groups attributes be applied to $createAt? 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; } } Quote Link to comment https://forums.phpfreaks.com/topic/313777-php-8s-constructor-property-promotion/ Share on other sites More sharing options...
requinix Posted September 19, 2021 Share Posted September 19, 2021 Promoted properties are also arguments to the constructor. Your constructor has no arguments. The rest isn't important. Quote Link to comment https://forums.phpfreaks.com/topic/313777-php-8s-constructor-property-promotion/#findComment-1590148 Share on other sites More sharing options...
maxxd Posted September 19, 2021 Share Posted September 19, 2021 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. Quote Link to comment https://forums.phpfreaks.com/topic/313777-php-8s-constructor-property-promotion/#findComment-1590151 Share on other sites More sharing options...
NotionCommotion Posted September 20, 2021 Author Share Posted September 20, 2021 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, ) {} } Quote Link to comment https://forums.phpfreaks.com/topic/313777-php-8s-constructor-property-promotion/#findComment-1590154 Share on other sites More sharing options...
requinix Posted September 20, 2021 Share Posted September 20, 2021 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. Quote Link to comment https://forums.phpfreaks.com/topic/313777-php-8s-constructor-property-promotion/#findComment-1590167 Share on other sites More sharing options...
NotionCommotion Posted September 20, 2021 Author Share Posted September 20, 2021 34 minutes ago, requinix said: It's in there. Yes it is but just didn't see it until now. Thanks Quote Attributes placed on a promoted constructor argument will be replicated to both the property and argument. Quote Link to comment https://forums.phpfreaks.com/topic/313777-php-8s-constructor-property-promotion/#findComment-1590174 Share on other sites More sharing options...
requinix Posted September 20, 2021 Share Posted September 20, 2021 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. Quote Link to comment https://forums.phpfreaks.com/topic/313777-php-8s-constructor-property-promotion/#findComment-1590180 Share on other sites More sharing options...
NotionCommotion Posted September 21, 2021 Author Share Posted September 21, 2021 Will do requinix, Thanks again. Quote Link to comment https://forums.phpfreaks.com/topic/313777-php-8s-constructor-property-promotion/#findComment-1590187 Share on other sites More sharing options...
NotionCommotion Posted October 28, 2021 Author Share Posted October 28, 2021 On 9/19/2021 at 3:54 PM, 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. Hello again maxxd, While I agree instantiating objects in a constructor goes against the concept of dependency injection, I am now thinking it might be a necessary evil under some scenarios. The alternative when using Symfony is to create a listener which gets triggered when the entity is persisted and have it call setCreateAt(new \DateTimeImmutable). As for collections, Symfony/Doctrine handles them by creating a new ArrayCollection in the constructor which is basically the same thing. Seems like more trouble than its worth. Am I missing something? Thanks Quote Link to comment https://forums.phpfreaks.com/topic/313777-php-8s-constructor-property-promotion/#findComment-1591513 Share on other sites More sharing options...
maxxd Posted October 29, 2021 Share Posted October 29, 2021 I'm not familiar with Symfony, but yeah - rules are made to be broken, right? There are situations where a tighter coupling is not entirely unavoidable, but honestly is just easier and in the long run is not a terrible idea. Instantiating SPL objects in a class constructor is really not that awful IMO as SPL objects are unlikely to change massively without a good amount of forewarning. It can be annoying when a library comes out that does something similar to the SPL class easier, but by then you've already got the SPL code working so ... so? Quote Link to comment https://forums.phpfreaks.com/topic/313777-php-8s-constructor-property-promotion/#findComment-1591524 Share on other sites More sharing options...
NotionCommotion Posted October 29, 2021 Author Share Posted October 29, 2021 Thanks maxxd, Makes good sense and understand why you qualify that they should be unlikely to change but not sure why you limit it to SPL objects. Do you mean these and if so why? Quote Link to comment https://forums.phpfreaks.com/topic/313777-php-8s-constructor-property-promotion/#findComment-1591545 Share on other sites More sharing options...
maxxd Posted October 29, 2021 Share Posted October 29, 2021 No, I'm just being a bit lazy and misusing the term. I mean core PHP objects and classes. Quote Link to comment https://forums.phpfreaks.com/topic/313777-php-8s-constructor-property-promotion/#findComment-1591584 Share on other sites More sharing options...
NotionCommotion Posted October 30, 2021 Author Share Posted October 30, 2021 Gotcha! And didn't think you were being lazy 🙂 No response necessary unless you think I am way off base but I am also going to add non-core objects and classes (i.e. Doctrine's ArrayCollection) to that list IF used within some framework and IF that framework is responsible to keep them up to date. Quote Link to comment https://forums.phpfreaks.com/topic/313777-php-8s-constructor-property-promotion/#findComment-1591590 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.