DeepCopy - Create deep copies (clones) of your objects

Overview

DeepCopy

DeepCopy helps you create deep copies (clones) of your objects. It is designed to handle cycles in the association graph.

Build Status Coverage Status Scrutinizer Quality Score Total Downloads

Table of Contents

  1. How
  2. Why
    1. Using simply clone
    2. Overridding __clone()
    3. With DeepCopy
  3. How it works
  4. Going further
    1. Matchers
      1. Property name
      2. Specific property
      3. Type
    2. Filters
      1. SetNullFilter
      2. KeepFilter
      3. DoctrineCollectionFilter
      4. DoctrineEmptyCollectionFilter
      5. DoctrineProxyFilter
      6. ReplaceFilter
      7. ShallowCopyFilter
  5. Edge cases
  6. Contributing
    1. Tests

How?

Install with Composer:

composer require myclabs/deep-copy

Use simply:

use DeepCopy\DeepCopy;

$copier = new DeepCopy();
$myCopy = $copier->copy($myObject);

Why?

  • How do you create copies of your objects?
$myCopy = clone $myObject;
  • How do you create deep copies of your objects (i.e. copying also all the objects referenced in the properties)?

You use __clone() and implement the behavior yourself.

  • But how do you handle cycles in the association graph?

Now you're in for a big mess :(

association graph

Using simply clone

Using clone

Overridding __clone()

Overridding __clone

With DeepCopy

With DeepCopy

How it works

DeepCopy recursively traverses all the object's properties and clones them. To avoid cloning the same object twice it keeps a hash map of all instances and thus preserves the object graph.

To use it:

use function DeepCopy\deep_copy;

$copy = deep_copy($var);

Alternatively, you can create your own DeepCopy instance to configure it differently for example:

use DeepCopy\DeepCopy;

$copier = new DeepCopy(true);

$copy = $copier->copy($var);

You may want to roll your own deep copy function:

namespace Acme;

use DeepCopy\DeepCopy;

function deep_copy($var)
{
    static $copier = null;
    
    if (null === $copier) {
        $copier = new DeepCopy(true);
    }
    
    return $copier->copy($var);
}

Going further

You can add filters to customize the copy process.

The method to add a filter is DeepCopy\DeepCopy::addFilter($filter, $matcher), with $filter implementing DeepCopy\Filter\Filter and $matcher implementing DeepCopy\Matcher\Matcher.

We provide some generic filters and matchers.

Matchers

  • DeepCopy\Matcher applies on a object attribute.
  • DeepCopy\TypeMatcher applies on any element found in graph, including array elements.

Property name

The PropertyNameMatcher will match a property by its name:

use DeepCopy\Matcher\PropertyNameMatcher;

// Will apply a filter to any property of any objects named "id"
$matcher = new PropertyNameMatcher('id');

Specific property

The PropertyMatcher will match a specific property of a specific class:

use DeepCopy\Matcher\PropertyMatcher;

// Will apply a filter to the property "id" of any objects of the class "MyClass"
$matcher = new PropertyMatcher('MyClass', 'id');

Type

The TypeMatcher will match any element by its type (instance of a class or any value that could be parameter of gettype() function):

use DeepCopy\TypeMatcher\TypeMatcher;

// Will apply a filter to any object that is an instance of Doctrine\Common\Collections\Collection
$matcher = new TypeMatcher('Doctrine\Common\Collections\Collection');

Filters

  • DeepCopy\Filter applies a transformation to the object attribute matched by DeepCopy\Matcher
  • DeepCopy\TypeFilter applies a transformation to any element matched by DeepCopy\TypeMatcher

SetNullFilter (filter)

Let's say for example that you are copying a database record (or a Doctrine entity), so you want the copy not to have any ID:

use DeepCopy\DeepCopy;
use DeepCopy\Filter\SetNullFilter;
use DeepCopy\Matcher\PropertyNameMatcher;

$object = MyClass::load(123);
echo $object->id; // 123

$copier = new DeepCopy();
$copier->addFilter(new SetNullFilter(), new PropertyNameMatcher('id'));

$copy = $copier->copy($object);

echo $copy->id; // null

KeepFilter (filter)

If you want a property to remain untouched (for example, an association to an object):

use DeepCopy\DeepCopy;
use DeepCopy\Filter\KeepFilter;
use DeepCopy\Matcher\PropertyMatcher;

$copier = new DeepCopy();
$copier->addFilter(new KeepFilter(), new PropertyMatcher('MyClass', 'category'));

$copy = $copier->copy($object);
// $copy->category has not been touched

DoctrineCollectionFilter (filter)

If you use Doctrine and want to copy an entity, you will need to use the DoctrineCollectionFilter:

use DeepCopy\DeepCopy;
use DeepCopy\Filter\Doctrine\DoctrineCollectionFilter;
use DeepCopy\Matcher\PropertyTypeMatcher;

$copier = new DeepCopy();
$copier->addFilter(new DoctrineCollectionFilter(), new PropertyTypeMatcher('Doctrine\Common\Collections\Collection'));

$copy = $copier->copy($object);

DoctrineEmptyCollectionFilter (filter)

If you use Doctrine and want to copy an entity who contains a Collection that you want to be reset, you can use the DoctrineEmptyCollectionFilter

use DeepCopy\DeepCopy;
use DeepCopy\Filter\Doctrine\DoctrineEmptyCollectionFilter;
use DeepCopy\Matcher\PropertyMatcher;

$copier = new DeepCopy();
$copier->addFilter(new DoctrineEmptyCollectionFilter(), new PropertyMatcher('MyClass', 'myProperty'));

$copy = $copier->copy($object);

// $copy->myProperty will return an empty collection

DoctrineProxyFilter (filter)

If you use Doctrine and use cloning on lazy loaded entities, you might encounter errors mentioning missing fields on a Doctrine proxy class (...\__CG__\Proxy). You can use the DoctrineProxyFilter to load the actual entity behind the Doctrine proxy class. Make sure, though, to put this as one of your very first filters in the filter chain so that the entity is loaded before other filters are applied!

use DeepCopy\DeepCopy;
use DeepCopy\Filter\Doctrine\DoctrineProxyFilter;
use DeepCopy\Matcher\Doctrine\DoctrineProxyMatcher;

$copier = new DeepCopy();
$copier->addFilter(new DoctrineProxyFilter(), new DoctrineProxyMatcher());

$copy = $copier->copy($object);

// $copy should now contain a clone of all entities, including those that were not yet fully loaded.

ReplaceFilter (type filter)

  1. If you want to replace the value of a property:
use DeepCopy\DeepCopy;
use DeepCopy\Filter\ReplaceFilter;
use DeepCopy\Matcher\PropertyMatcher;

$copier = new DeepCopy();
$callback = function ($currentValue) {
  return $currentValue . ' (copy)'
};
$copier->addFilter(new ReplaceFilter($callback), new PropertyMatcher('MyClass', 'title'));

$copy = $copier->copy($object);

// $copy->title will contain the data returned by the callback, e.g. 'The title (copy)'
  1. If you want to replace whole element:
use DeepCopy\DeepCopy;
use DeepCopy\TypeFilter\ReplaceFilter;
use DeepCopy\TypeMatcher\TypeMatcher;

$copier = new DeepCopy();
$callback = function (MyClass $myClass) {
  return get_class($myClass);
};
$copier->addTypeFilter(new ReplaceFilter($callback), new TypeMatcher('MyClass'));

$copy = $copier->copy([new MyClass, 'some string', new MyClass]);

// $copy will contain ['MyClass', 'some string', 'MyClass']

The $callback parameter of the ReplaceFilter constructor accepts any PHP callable.

ShallowCopyFilter (type filter)

Stop DeepCopy from recursively copying element, using standard clone instead:

use DeepCopy\DeepCopy;
use DeepCopy\TypeFilter\ShallowCopyFilter;
use DeepCopy\TypeMatcher\TypeMatcher;
use Mockery as m;

$this->deepCopy = new DeepCopy();
$this->deepCopy->addTypeFilter(
	new ShallowCopyFilter,
	new TypeMatcher(m\MockInterface::class)
);

$myServiceWithMocks = new MyService(m::mock(MyDependency1::class), m::mock(MyDependency2::class));
// All mocks will be just cloned, not deep copied

Edge cases

The following structures cannot be deep-copied with PHP Reflection. As a result they are shallow cloned and filters are not applied. There is two ways for you to handle them:

  • Implement your own __clone() method
  • Use a filter with a type matcher

Contributing

DeepCopy is distributed under the MIT license.

Tests

Running the tests is simple:

vendor/bin/phpunit

Support

Get professional support via the Tidelift Subscription.

Comments
  • DeepCopy ignores Doctrine2 proxies

    DeepCopy ignores Doctrine2 proxies

    If the relation is fully hydrated (ie, no proxy) everything is good, and my "id" property matcher can set the property to null.

    If, however, the relation isn't retrieved in the query, the related object is Proxy instance, and DeepCopy won't set the ID of that object to null.

    Has anyone had this problem, and has anyone got a workaround, other than hydrating everything before copying (which might be the most sensible thing to do anyway)?

    opened by mrthehud 27
  • Matchers & Filters: use the right ReflectionProperty

    Matchers & Filters: use the right ReflectionProperty

    Currently DeepCopy does not allow to copy private properties on the parent class when Matchers and Filters are used, as I show in this new test: https://github.com/myclabs/DeepCopy/pull/35/files#diff-0fe594d8935dca0233edc25909b8267dR59

    This is because the ReflectionHelper gathers all the properties from parent classes but the Matchers and the Filters try to instantiate their own ReflectionProperty, which raise an ReflectionException because private properties on parent class are not part of sub classes: https://3v4l.org/MuZPG

    There are two solutions:

    1. Use in every matcher and in every filter a new helper to find the property through the parent classes, which is backward compatible, but you have to test that everyone uses this "helper"
    2. Change the Matcher and Filter interface to match the ReflectionProperty gathered be the ReflectionHelper, which is a BC break if someone is using a custom implementation of this two interfaces, but is way more solid

    For this PR I chose the latter.

    The current test on this subject, testPrivatePropertyOfParentObjectCopy, passes because no matchers and no filters are used.

    opened by Slamdunk 17
  • Use the user clone implementation when there is one

    Use the user clone implementation when there is one

    IMO if a user use the __clone function, it is because he has a precise idea on how the object should be cloned. For that reason, I'm inclined to think that DeepCopy should rely on that implementation instead of try to do the work on its own.

    Another win is that it's potentially faster as well to rely on the user clone, so users would be able to optimize some parts if they see the need for it by implementing themselves the clone function.

    opened by theofidry 14
  • unexpected function error in deep copy

    unexpected function error in deep copy

    Hello,

    I just did a composer update, and my website went down. The logs showed this message:

    [Fri Jun 29 01:10:09.028655 2018] [:error] [pid 22125] [client 10.0.10.4:47366] PHP Parse error: syntax error, unexpected 'function' (T_FUNCTION), expecting identifier (T_STRING) or \\\\ (T_NS_SEPARATOR) in /var/www/website/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php on line 5

    the composer.lock file shows

    "name": "myclabs/deep-copy",
    "url": "https://github.com/myclabs/DeepCopy.git",
    "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3e01bdad3e18354c3dce54466b7fbe33a9f9f7f8",
    "myclabs/deep-copy": "self.version"
    "myclabs/deep-copy": "^1.3",
    

    not sure even what this does, but commenting out line 5 in deep_copy.php restored my website to functioning.

    cheers

    Ben

    opened by benmadin 12
  • Bug in \DeepCopy\DeepCopy::copyObject method

    Bug in \DeepCopy\DeepCopy::copyObject method

    Hi. next lines in code are buggy, that our project failing today:

    $objectHash = spl_object_hash($object);
    ..........
    ..........
    $newObject = clone $object;
    //One of two situations (I do not know correct solution)
    //1)
    $this->hashMap[spl_object_hash($newObject)] = $newObject; //<--- BUG: need use spl_object_hash($newObject) instead previous $objectHash
    
    //2)
    $this->hashMap[$objectHash] = $object;//<---- store old object
    

    What is happening: The current $object will free (as cloned from previous recursions). The php reusing this $objectHash for new cloned $object. But in this case, the copy process returning old not correct $object from $this->hashMap.

    PLEASE fix it and inform me (I don't want to inject my codes inside ).

    bug 
    opened by lemaxya 12
  • How to deal with uncloneable objects ?

    How to deal with uncloneable objects ?

    Hey guys, I am facing a bit of dilemma here. The situation is as follows:

    I am currently trying to clone a rather complex tree of documents that I retrieved via doctrine from MongoDB. In order to persist the newly clones documents again, I need to either strip them of their ids or replace new them with new ids (\MongoId to be precise).

    My initial approach therefore was to either use replace filter or a setNullFilter like this:

    $deepCopy->addFilter(new SetNullFilter(), new PropertyNameMatcher('id'));

    But then I ran into the exception that DeepCopy still encountered some MongoId Objects that are uncloneable (Which is how I stumbled over the bug I fixed the other day). As it turns out, MongoId Objects are also used in properties that are not called 'id'. Still I thought the fix was rather easy:

    $deepCopy->addFilter(new SetNullFilter(), new PropertyTypeMatcher('MongoId'));

    After all, this approach should handle all Objects of the MongoId kind, right ? In fact, it does but not in the way I intended it to. It turns out, we use MongoId Objects to reference other objects. These references however should be kept during copying and not be nulled.

    Still, I thought the fix was rather easy. I just write my own filter that either duplicates the id manually or keeps it, depending on the property name:

    
    use DeepCopy\Filter\Filter;
    
    class MongoIdFilter implements Filter
    {
        /**
         * {@inheritdoc}
         */
        public function apply($object, $property, $objectCopier)
        {
            $reflectionProperty = new \ReflectionProperty($object, $property);
            $reflectionProperty->setAccessible(true);
    
            if ($property === 'id') {
                $value = new \MongoId();
            } else {
                ldd($reflectionProperty->getValue($object));
    
                $value = new \MongoId((string) $reflectionProperty->getValue($object));
            }
    
            $reflectionProperty->setValue($object, $value);
        }
    }
    

    Yet, I still run into the exception:

    [DeepCopy\Exception\CloneException]
    Class "MongoId" is not clone able.
    

    Via debugging I found out that my filter is being executed, but apparently not in every case. I seem to be missing something. Is there any other, preferred way, I should handle this situation ?

    Best regards

    Jan

    opened by Jan0707 11
  • Maximum function nesting level of '200' reached, aborting

    Maximum function nesting level of '200' reached, aborting

    Hi, I've updated to 1.4.0 and my tests failed with a Maximum function nesting level of '200' reached, aborting exception.

    Rolled back to 1.3.1 everything went back to normal.

    I don't know if I missed something (config or ... something) but I thought you might be notified.

    thanks

    question 
    opened by raoul2000 10
  • General error: property queryString is read only

    General error: property queryString is read only

    Since we upgraded to the latest version, 1.4.0 we are getting this error when running tests in codeception.

    • Removing myclabs/deep-copy (1.3.1)
    • Installing myclabs/deep-copy (1.4.0)
    PDOException: SQLSTATE[HY000]: General error: property queryString is read only
    
    #1  /var/jenkins/workspace/Integration-API-MAIN-PHP-Testing/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php:160
    #2  /var/jenkins/workspace/Integration-API-MAIN-PHP-Testing/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php:123
    #3  /var/jenkins/workspace/Integration-API-MAIN-PHP-Testing/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php:75
    #4  /var/jenkins/workspace/Integration-API-MAIN-PHP-Testing/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php:160
    #5  /var/jenkins/workspace/Integration-API-MAIN-PHP-Testing/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php:123
    #6  /var/jenkins/workspace/Integration-API-MAIN-PHP-Testing/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php:75
    #7  /var/jenkins/workspace/Integration-API-MAIN-PHP-Testing/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php:86
    #8  DeepCopy\DeepCopy->DeepCopy\{closure}
    #9  /var/jenkins/workspace/Integration-API-MAIN-PHP-Testing/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php:89
    #10 /var/jenkins/workspace/Integration-API-MAIN-PHP-Testing/vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php:68
    
    opened by sameg14 10
  • Add strict types

    Add strict types

    Closes #111

    • Bumps to PHP 7.2
    • Add typehints when possible
    • Remove the final annotations in favour of the final keyword
    • Add declare strict types statement
    opened by theofidry 9
  • Fix for Exception

    Fix for Exception

    We cannot assume that EVERY object we receive here implements the getName method. Therefore we should fall back to the ReflectionObject which implements the method (via ReflectionClass).

    opened by Jan0707 9
  • Add DataFilter

    Add DataFilter

    Add new filter, In the way to handle data property (refer to readme.md changed for more details).

    My use case : I have to copy doctrine entity object who contains a JsonArray property, I must set some values to false and let unchanged others.

    I know we can achieve this without DeepCopy but in order to keep the code simple as possible and consistency, retrieve a real clean and formed copied object directly without implement something like "AfterObjectDuplication" to changed some property wich can be done during the process is better IMO.

    enhancement 
    opened by jjsaunier 9
  • Migrate to  phpspec/prophecy-phpunit

    Migrate to phpspec/prophecy-phpunit

    https://github.com/sebastianbergmann/phpunit/issues/5033 changed phpunit to no longer depend on phpspec/prophecy. This results in the need to add a development dependency for phpspec/prophecy. Doing so results in a warning, since PHPUnit\Framework\TestCase::prophesize() is deprecated and will be removed in PHPUnit 10. Let's use the trait provided by phpspec/prophecy-phpunit instead.

    • Fixes #177
    opened by athos-ribeiro 5
  • phpspec/prophecy is now explicitely needed for tests

    phpspec/prophecy is now explicitely needed for tests

    Hi,

    Since PHPUnit dropped phpspec/prophecy from its dependencies (https://github.com/sebastianbergmann/phpunit/issues/5033), the following error is triggered when running the testsuite with latest PHPUnit.

    There was 1 error:
    
    1) DeepCopyTest\TypeFilter\Spl\ArrayObjectFilterTest::test_it_deep_copies_an_array_object
    PHPUnit\Framework\Exception: This test uses TestCase::prophesize(), but phpspec/prophecy is not installed. Please run "composer require --dev phpspec/prophecy".
    

    Regards

    David

    opened by DavidPrevot 1
  • Allow applying further filters after DoctrineProxyFilter

    Allow applying further filters after DoctrineProxyFilter

    Backport PR #101 and #133 (based issue #98) on version 1, after discussions on #173.

    I continue to think that being unable to apply 2 filters with Doctrine Proxy is a bug. If you think it's a BC break, I can create a new DoctrineProxyFilter class and depreciate the existing class, but I'm not sure how to name it.

    opened by fsevestre 3
  • readonly properties in constructor

    readonly properties in constructor

    PHP version 8.1.5

    following code

    class A {
        public function __construct(
            public readonly string $prop,
        )
        {
        }
    }
    
    $a = new A('some value');
    $b = \DeepCopy\deep_copy($a);
    

    throws following:

    PHP Fatal error:  Uncaught Error: Cannot modify readonly property A::$prop in .../vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php:257
    Stack trace:
    #0 .../vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php(257): ReflectionProperty->setValue()
    #1 .../vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php(213): DeepCopy\DeepCopy->copyObjectProperty()
    #2 .../vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php(149): DeepCopy\DeepCopy->copyObject()
    #3 .../vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php(94): DeepCopy\DeepCopy->recursiveCopy()
    #4 .../vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php(18): DeepCopy\DeepCopy->copy()
    #5 .../test.php(57): DeepCopy\deep_copy()
    #6 {main}
      thrown in .../vendor/myclabs/deep-copy/src/DeepCopy/DeepCopy.php on line 257
    
    opened by leongrdic 2
  • What about Version 2

    What about Version 2

    Hello, i am wondering if there is going to be a release of version 2. It seems the branch has not really gotten a lot of attentien.

    mainly i am asking because i need this pr: https://github.com/myclabs/DeepCopy/pull/101 Maybe i just did not see how this can be done on version 1, but as i understand it this can not be achieved currently in version 1.

    opened by djschilling 5
Releases(1.11.0)
Owner
My C-Labs
My C-Labs
Yab copy to new - A Textpattern plugin. Copies the current article content to a new one.

yab_copy_to_new Displays a new button in article write tab to copy the current article to a new one. Version: 0.2 Table of contents Plugin requirement

Tommy Schmucker 2 Dec 15, 2017
PHP package to make your objects strict and throw exception when you try to access or set some undefined property in your objects.

?? Yell PHP package to make your objects strict and throw exception when you try to access or set some undefined property in your objects. Requirement

Zeeshan Ahmad 20 Dec 8, 2018
A high-level machine learning and deep learning library for the PHP language.

Rubix ML A high-level machine learning and deep learning library for the PHP language. Developer-friendly API is delightful to use 40+ supervised and

Rubix 1.7k Jan 1, 2023
Rubix ML - A high-level machine learning and deep learning library for the PHP language.

A high-level machine learning and deep learning library for the PHP language. Developer-friendly API is delightful to use 40+ supervised and

Rubix 1.7k Jan 6, 2023
A list of ICs and IPs for AI, Machine Learning and Deep Learning.

AI Chip (ICs and IPs) Editor S.T.(Linkedin) Welcome to My Wechat Blog StarryHeavensAbove for more AI chip related articles Latest updates Add news of

Shan Tang 1.4k Jan 3, 2023
The tool converts different error reporting standards for deep compatibility with popular CI systems (TeamCity, IntelliJ IDEA, GitHub Actions, etc).

JBZoo / CI-Report-Converter Why? Installing Using as GitHub Action Example GitHub Action workflow Available Directions Help description in terminal Co

JBZoo Toolbox 17 Jun 16, 2022
Deeper is a easy way to compare if 2 objects is equal based on values in these objects. This library is heavily inspired in Golang's reflect.DeepEqual().

Deeper Deeper is a easy way to compare if 2 objects is equal based on values in these objects. This library is heavily inspired in Golang's reflect.De

Joubert RedRat 4 Feb 12, 2022
Creating data transfer objects with the power of php objects. No php attributes, no reflection api, and no other under the hook work.

Super Simple DTO Creating data transfer objects with the power of php objects. No php attributes, no reflection api, and no other under the hook work.

Mohammed Manssour 8 Jun 8, 2023
A set of classes to create and manipulate HTML objects abstractions

HTMLObject HTMLObject is a set of classes to create and manipulate HTML objects abstractions. Static calls to the classes echo Element::p('text')->cla

Emma Fabre 128 Dec 22, 2022
Samsui is a factory library for building PHP objects useful for setting up test data in your applications.

#Samsui Samsui is a factory library for building PHP objects useful for setting up test data in your applications. It is mainly inspired by Rosie for

Sam Yong 31 Nov 11, 2020
A bunch of general-purpose value objects you can use in your Laravel application.

Laravel Value Objects A bunch of general-purpose value objects you can use in your Laravel application. The package requires PHP ^8.0 and Laravel ^9.7

Michael Rubél 136 Jan 4, 2023
:date: The VObject library for PHP allows you to easily parse and manipulate iCalendar and vCard objects

sabre/vobject The VObject library allows you to easily parse and manipulate iCalendar and vCard objects using PHP. The goal of the VObject library is

sabre.io 532 Dec 25, 2022
Enforced disposal of objects in PHP. 🐘

Enforced disposal of objects in PHP. This package provides a Disposable interface and using() global function that can be used to enforce the disposal

Ryan Chandler 52 Oct 12, 2022
Allows generate class files parse from json and map json to php object, including multi-level and complex objects;

nixihz/php-object Allows generate class files parse from json and map json to php object, including multi-level and complex objects; Installation You

zhixin 2 Sep 9, 2022
SAPI request and response objects for PHP 8.1

Sapien This package provides server API (SAPI) request and response objects for PHP 8.1: Sapien\Request, composed of readonly copies of PHP supergloba

null 37 Jan 3, 2023
Share value objects that contain the same primitive value as a singleton

sharable-value-objects Share value objects that contain the same primitive value as a singleton. Singletons are kept under WeakReference objects. Inst

mpyw 5 Nov 14, 2021
Collection of value objects that represent the types of the PHP type system

sebastian/type Collection of value objects that represent the types of the PHP type system. Installation You can add this library as a local, per-proj

Sebastian Bergmann 1.1k Dec 29, 2022
Silverstripe-searchable - Adds to the default Silverstripe search by adding a custom results controller and allowing properly adding custom data objects and custom fields for searching

SilverStripe Searchable Module UPDATE - Full Text Search This module now uses Full Text Support for MySQL/MariaDB databases in version 3.* Adds more c

ilateral 13 Apr 14, 2022
An object store for specific objects.

Object Storage A simple object storage class that will only allow "supported" objects. class MyObjectStorage extends Herrera\Util\ObjectStorage {

KHerGe - Archived Projects 17 Jan 31, 2020