dshafik / bag Goto Github PK
View Code? Open in Web Editor NEWImmutable Value Objects for PHP
Home Page: https://bagvalueobjects.com/
License: MIT License
Immutable Value Objects for PHP
Home Page: https://bagvalueobjects.com/
License: MIT License
Currently in order to create Bag value objects you must extend the \Bag\Bag
class. This requirement limits where you can use Bag value objects — you cannot simply add Value Object behavior to an existing value-object-like class. This is intended as an alternative way to use Bag.
We can solve this in two ways:
BagInterface
and AsBag
TraitThe first approach is more type-safe, by creating a BagInterface
we enforce Bag-like UX on any class that wishes to be a Bag Value Object. Primarily this means enforcing the following methods:
interface BagInterface
{
public static function from(mixed $values): BagInterface;
public static function rules(): array;
public static function collect(iterable $values = []): Collection;
public static function validate(LaravelCollection|array $values): bool;
public function with(mixed ...$values): BagInterface;
public function get(?string $key = null): mixed;
public function getRaw(?string $key = null): mixed;
public function unwrapped(): array;
public function toArray(): array;
public function jsonSerialize(): array;
public function toJson($options = 0): string;
}
We can then provide the implementation using the AsBag
trait, meaning that to implement Bag functionality in any object, you can do the following:
use Bag\Contracts\BagInterface;
use Bag\Traits\AsBag;
readonly class MyValue implements BagInterface {
use AsBag;
public function __construct(…) { }
}
and the default Bag
class can simply be the following to continue allowing the existing extend Bag
UX:
readonly class Bag implements Arrayable, Jsonable, JsonSerializable, Castable, BagInterface
{
use AsBag;
}
Alternatively, we can implement a Bag::make()
method with the following signature:
/**
* @template T of object
* @param class-string<T> $className
* @return T
*/
public static function make(string $className, mixed $values): object;
This would then resolve the constructor arguments for $className
and create a new instance. In addition static methods such as Bag::validate()
and Bag::collect()
can be updated to support objects that don't extend Bag
.
However, with()
is an instance method and the alternative to this to re-use Bag::make()
and pass in the original value object values along with the new changes.
To enable support for features such as Hidden
, we would also need to implement output functions such as toArray()
, and toJson()
/jsonSerialize()
, which would either need to make heavy of (slow) reflection, or wrap around those functions in the underlying object.
With the interface-and-trait implementation the resulting class has all the functionality and UX of Bag
value objects, however it still requires you to update your existing class definition. The Bag::make()
option requires less changes to the class, although you can opt-in to features using the attributes for features like casting or validation.
The primary downfall of the Bag::make()
implementation is that the pipeline must be changed from working on Bag
objects and instead just use object
instead, losing any type safety in the process.
It should be noted that both of these solutions and the original extend Bag
solution can co-exist, however there are concerns about complicating the UX by being too flexible.
Describe the bug
Attempting to install Bag via the CLI leards to In ProviderRepository.php line 206: Class "BagServiceProvider" not found
To Reproduce
composer require dshafik/bag
Expected behavior
System (please complete the following information):
Additional context
Laravel 11.0.6, brand new install, I do need to change stability in composer to to "dev" order to get this far
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.