Skip to content

A 'virtual properties' attribute#3

Open
gwillz wants to merge 37 commits intomasterfrom
feat/virtual-attributes
Open

A 'virtual properties' attribute#3
gwillz wants to merge 37 commits intomasterfrom
feat/virtual-attributes

Conversation

@gwillz
Copy link
Copy Markdown
Collaborator

@gwillz gwillz commented Nov 2, 2022

We already have a very handy UpdateVirtualTrait that lets us apply functions whenever updating data via constructor or update(). This lets us normalise or parse complex data. However, it's a little cumbersome (and broken for strong types).

Attributes

Declare an attribute for properties to define how it should be marshalled into the correct type.

There are three attributes:

  • VirtualProperty - this defines a method to call when updating this property.
  • VirtualObject - this converts arrays into objects using configurable logic.
  • VirtualArray - for create object arrays, same configurable logic.

Such as:

class MyModel extends DataObject
{
   use UpdateTrait;
   use AttributesVirtualTrait;

   #[VirtualProperty('setComplex')]
   public $complex;

   #[VirtualObject(OtherModel::class)]
   public $object;
   
   public function setComplex($value)
   {
      this->complex = new Complex($value);
   }
}

Strong Types

This introduces the UpdateVirtualInterface with a setVirtual() method to replace the wonky applyVirtual() approach.

Where instead of modifying types in-place on the object (which doesn't work with strong types), instead we convert and apply virtual properties first.

The relevant update traits are updated to use the new interface. This is technically a breaking change.

Important considerations

Something like this feels redundant, and you would be right.

#[VirtualObject(SomeModel::class)
public SomeModel $object;

The target object is right there and we could simply use that instead of the attribute. However this scenario is also common:

#[VirtualObject(SomeModel::class)
public BaseModel $object;

Where BaseModel is abstract or an interface.

@gwillz gwillz force-pushed the feat/virtual-attributes branch 3 times, most recently from 22b31e4 to e7247c0 Compare November 7, 2022 05:25
gwillz added 22 commits April 9, 2026 20:08
This adds VirtualObject for shorthand goodness using the
Configure helper. However, this doesn't gel so well with
strict property types introduced in PHP 7.4.

We'll likely need to rework how update() and applyVirtual() works.
…ely.

This permits 'strict' updates to report errors for bad types.
Lots of complexity and we don't need doc tags.
Why when attributes are always superior?
This trait only exists for backward compat.
@gwillz gwillz force-pushed the feat/virtual-attributes branch from c0dd6df to 09442b9 Compare April 9, 2026 11:03
@gwillz gwillz marked this pull request as ready for review April 9, 2026 11:27
gwillz added 2 commits April 10, 2026 15:05
Where the virtual trait is used without the interface.
Common if using DataObject instead of Collection as the base class.
UpdateVirtualTrait was already opt-in. So now it simply overrides
the default (attributes) behaviour.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Introduces PHP 8 attribute-based “virtual properties” (method-based, object, and array conversion) and a new UpdateVirtualInterface::setVirtual() flow so virtual conversions happen before assignment (supporting strongly typed properties).

Changes:

  • Added VirtualProperty, VirtualObject, VirtualArray attributes and shared reflection parsing via VirtualPropertyBase.
  • Added UpdateVirtualInterface and updated update traits to apply virtual conversions pre-assignment.
  • Updated Collection (and Url) to participate in the new virtual-update mechanism; added tests for attribute behavior.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
tests/CollectionTest.php Adds coverage for attribute-based virtual property conversion.
src/AttributeVirtualTrait.php Implements setVirtual() via reflection over virtual-property attributes.
src/VirtualPropertyBase.php Base + parser for virtual-property attributes.
src/VirtualProperty.php Attribute to bind a property to a setter method.
src/VirtualObject.php Attribute to convert arrays into a configured object.
src/VirtualArray.php Attribute to convert arrays into arrays of configured objects.
src/UpdateVirtualInterface.php New interface for the “pre-assignment virtual update” API.
src/UpdateVirtualTrait.php Adds setVirtual() and deprecates applyVirtual().
src/UpdateTrait.php Applies setVirtual() before property assignment.
src/UpdateTidyTrait.php Same as above, with property filtering/type checks.
src/UpdateStrictTrait.php Same as above, with strict unknown/invalid field errors.
src/Collection.php Makes Collections implement virtual-update interface and uses attribute virtuals.
src/Url.php Implements UpdateVirtualInterface so existing virtual behavior still runs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/UpdateTrait.php Outdated
Comment thread src/UpdateStrictTrait.php Outdated
Comment thread src/AttributeVirtualTrait.php Outdated
Comment thread src/VirtualObject.php Outdated
Comment thread tests/CollectionTest.php Outdated
Comment thread src/UpdateVirtualTrait.php
Comment thread src/VirtualPropertyBase.php Outdated
Comment thread tests/CollectionTest.php
Comment thread src/UpdateVirtualTrait.php Outdated
Comment thread src/AttributeVirtualTrait.php Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Collection.php
Comment thread src/VirtualProperty.php Outdated
Comment thread src/VirtualArray.php
Comment thread src/UpdateVirtualTrait.php
Comment thread src/AttributeVirtualTrait.php Outdated
Comment thread src/VirtualPropertyBase.php
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.

2 participants