Prepare for future with php-generic
According to this article
which shows how to create strictly typed arrays and collections in Php7, php-generic generator was born., (*1)
There is some discusion about generic in Php
but who knows when it comes to us., (*2)
It is not exacly what you know from Java or C++ where generic looks like
Vector<int>(), Array<bool>() or Vector<\Namespace\Entity\User>()., (*3)
Here generics looks like VectorInt, ArrayBool and VectorUser
so I hope when they come to nativ Php all what you need to do will be:
1. Replace all VectorType, ArrayType to Vector<Type>, array<Type>,
2. Delete directory where you store all generated array/vector,
3. Enjoy a nice day., (*4)
What generics are (not)
They are not collections like Doctrine or Laravel Collections. They are like normal php array
which can store values one type. array<int> can store only numeric values which will converted to int
so you can not push 'some string value' to it., (*5)
Install
$ composer require d0niek/php-generic
Generate generic array<Type>
There is a bin command that you should find in vendor/bin
or somewhere else according to your composer.json settings., (*6)
To generate a generic array run:, (*7)
$ bin/generic generate:array [-s|--save [SAVE]] [--] <type> <namespace>
where:
* -s|--saveCollection - do you want to save generated array for future regenerate (default true),
* type - is a type of generic array. It can be simple type (bool, int, float, string, array)
or complex type (\YourApp\Module\Repository\User),
* namespace - is a namespace where new generic array will be save.
Remember that namespace's directory have to exists.
To separate namespace parts use \\ or / to speed up typing
if your namespace is 1:1 with your directory structure, (*8)
For example you have project in /path/to/project and your composer.json contains this kind of entry:, (*9)
"autoload": {
"psr-4": {
"VendorName\\AppName\\": "src/"
}
}
Now, when you call command like this:, (*10)
$ bin/generic generate:array int VendorName\\AppName\\Collections
new generic array ArrayInt will be save to /path/to/project/src/Collections/ directory.
If this directory does not exists, exceptions will be throw., (*11)
Tip! Store all php-generics in one diretory and add it to .gitignore.
When php will start support generics, replace ArrayInt to array<int> and remove php-generic directory., (*12)
Generate generic Vector<Type>
You can alse generate generic \Ds\Vector
(it is new data structure since Php7,
here
you can and you should read about it!). To do this just run:, (*13)
$ bin/generic generate:vector [-s|--save [SAVE]] [--] <type> <namespace>
parameters means exacly the same whats means when you run generate:array., (*14)
Regenerate
By defaule generated array/vector are save in generated-colletions.json file in your root app path.
Keep this file in repository and ignore all generated php-generics. When you clone repository,
after composer install run:, (*15)
$ bin/generic collections:regenerate
and all your collections will be regenerate., (*16)
Select data from DB
Now you can create in easy way specific generic when you are selecting data from DB, (*17)
class UserRepository implements UserRepositoryInterface
{
...
/**
* @inheritDoc
*/
public function findAll(): VectorUser
{
$users = new VectorUser();
$mysqli = new \mysqli('localhost:3306', 'user', 'password', 'db');
$mysqliResult = $mysqli->query('SELECT id, name FROM users LIMIT 10');
if ($mysqliResult !== false) {
while (($user = $mysqliResult->fetch_object(User::class)) !== null) {
$users->push($user);
}
}
$mysqli->close();
return $users;
}
...
}
Test
Before you run tests remember to regenerate collections. Run:, (*18)
$ bin/generic collections:regenerate
and now you can run, (*19)
$ phpunit