spatie/php-cloneable
Trait for PHP 8.1+ that makes objects with readonly properties cloneable. Safely “clone with changes” by copying an object while overriding readonly fields—handy until PHP gets native clone-with support.
Cloneable objects with readonly properties cannot be cloned via __clone() without explicit handling. This is a low-level but critical issue for Laravel models, DTOs, or value objects that rely on cloning for deep copying, caching, or state management.Illuminate\Support\Carbon, custom DTOs) and collection operations (e.g., Collection->map() may trigger clones). Useful for:
readonly attributes (PHP 8.1+).Money, Address) requiring deep copies.__clone() implementation or reflection-based workarounds (higher maintenance). This package standardizes the solution.use Cloneable; trait + #[Cloneable] attribute (PHP 8.1+). No database/migrations required.readonly properties are copied, not referenced).readonly properties are modified post-clone, behavior may differ from expectations (shallow vs. deep copy).readonly properties could introduce overhead (mitigate via lazy cloning or selective use).User->posts->user).#[Cloneable] must be applied correctly to avoid runtime errors.__clone() methods or augment them?User with 50 readonly relations).cloneIfNeeded()) for expensive objects.#[Cloneable] on DTOs").Replicator (for Eloquent) or serialization (e.g., json_decode(json_encode($obj))) is sufficient for some use cases.laravel-data for DTOs).Uuid or Carbon for immutable objects.User, Order, custom DTOs).readonly properties in PHP 8.1+ code.Money, Address).use Cloneable; and #[Cloneable] to a single class; test thoroughly.readonly attributes.Collection->map).__clone() methods (replace with trait where applicable).__clone() logic in favor of the trait.readonly attributes (PHP 8.1+).Collection->pluck).ArrayObject). May need refactoring.| Step | Task | Dependencies | Owner |
|---|---|---|---|
| 1 | PHP 8.1+ Upgrade | DevOps | Engineering |
| 2 | Audit Cloneable Objects | Codebase | QA/Dev |
| 3 | Pilot: Add Trait to DTOs | - | Backend |
| 4 | Test Cloning Behavior | Unit tests | QA |
| 5 | Rollout to Eloquent Models | PHP 8.1+ | Backend |
| 6 | Deprecate Custom __clone() |
- | Backend |
| 7 | Document Patterns | - | Tech Writers |
__clone() methods for readonly properties.#[Cloneable] must be kept in sync with readonly properties (risk of drift).readonly properties (e.g., nested objects).readonly properties if the original must remain immutable."User with 100 relations).cloneWithout(['sensitiveData'])).cloneOnce() pattern).readonly properties may need optimized queries to avoid cloning heavy relations.| Scenario | Risk | Mitigation |
|---|---|---|
| Circular References | Infinite recursion during clone | Use #[Cloneable(ignore: ['self'])] or manual __clone() for cycles. |
Shared readonly References |
Clone modifies original | Add validation in __clone() (e.g., deep copy sensitive properties). |
| PHP 8.1 Regression | Trait breaks in future PHP | Monitor PHP updates; test on new versions early. |
| Overuse | Performance degradation | Enforce cloning via interfaces (e.g., CloneableInterface). |
readonly properties and cloning patterns.#[Cloneable] for all DTOs").readonly classes.#[Cloneable] on readonly classes.readonly properties exist without #[Cloneable].How can I help you explore Laravel packages today?