You like Laravel Collections, but you don't use Laravel? You've used the Collections, but you feel like something missing? Like type hints? It's your package!
From PHP 7.0 you can typehint many things in php functions. Like:
function hello(string $name): string {
return sprintf('Hello %s!', $name);
}
But what if you want a string list? You can't typehint the content of arrays, you can only hint the array:
function hello(array $names): array;
And not like this:
function hello(array[string] $names): array[string];
It's sad.
If you use this package, you can use type hinted Collections instead of simple arrays. Like this:
$names = new StringCollection(['Pete', 'Steve', 'John']);
function hello(StringCollection $names): StringCollection {
...
}
It's so simple!
composer require esemve/typed-collection
You can use these default types:
- ArrayCollection
- BooleanCollection
- CallableCollection
- ClassCollection
- FloatCollection
- IntegerCollection
- NullCollection
- ObjectCollection
- ResourceCollection
- StringCollection
If you want create your own typed collection, just create a new Collection file, and extend the AbstractTypedCollection. After this your only task is to fill the isValid function. It will check every added value, and if you try to add a value that is not allowed, the AbstractTypedCollection will automatically throw an InvalidTypedException.
/// PostCollection.php:
<?php
declare(strict_types=1);
namespace Esemve\Collection;
use Entity\Post;
class PostCollection extends AbstractTypedCollection
{
protected function isValid($element): bool
{
return $element instanceof Post;
}
}
That's it. If you want to add your exception message, just add a getErrorMessage method to your class:
protected function getErrorMessage(): ?string
{
return 'It\'s my own error message';
}
There is a simple way to specify an 'instance of' typed collection:
$photo1 = new Photo();
$photo2 = new Photo();
$photoCollection = new ClassCollection(Photo::class, [$photo1, $photo2])
If you want to, you can use the CollectionFactory. It helps you to create a collection if you don't want to hardcode the types to your code. If you use the CollectionFactory, you can use this methods from it:
- createBooleanCollection(array $array): BooleanCollection;
- createCallableCollection(array $array): CallableCollection;
- createClassCollection(string $classname, array $array): ClassCollection;
- createFloatCollection(array $array): FloatCollection;
- createIntegerCollection(array $array): IntegerCollection;
- createNullCollection(array $array): NullCollection;
- createObjectCollection(array $array): ObjectCollection;
- createResourceCollection(array $array): ResourceCollection;
- createStringCollection(array $array): StringCollection;
- createCollection(array $array): Collection;
- create(PostCollection::class, $array): Collection (PostCollection just an example. It return a PostCollection)
In the factory you can remap the ::class classnames in the factory constructor param.
I've disabled the combine method from the original Collection class, because if you use that, your collection type can get mixed up.
The keys() method always return a StringCollection.
You can use this package without Laravel, thanks to the "tightenco/collect" package that I've used.
If you use this package with Laravel, the tightenco package will automatically disable itself, and the TypedCollection will use the default Laravel Collection package.
This package is open source software licensed under the MIT License.