Support ulid and uuid for Model (#5472)

This commit is contained in:
Deeka Wong 2023-03-05 11:19:24 +08:00 committed by GitHub
parent 0f787c8508
commit dac2959d4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 328 additions and 0 deletions

View File

@ -3,6 +3,7 @@
## Added
- [#5467](https://github.com/hyperf/hyperf/pull/5467) Support `Google\Rpc\Status` for `GRPC`.
- [#5472](https://github.com/hyperf/hyperf/pull/5472) Support `ulid` and `uuid` for Model.
- [#5476](https://github.com/hyperf/hyperf/pull/5476) Added ArrayAccess to Stringable.
## Optimized

View File

@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Database\Model\Concerns;
use Hyperf\Utils\Str;
trait HasUlids
{
/**
* Generate a new ULID for the model.
*
* @return string
*/
public function newUniqueId()
{
return strtolower((string) Str::ulid());
}
/**
* Get the columns that should receive a unique identifier.
*
* @return array
*/
public function uniqueIds()
{
return [$this->getKeyName()];
}
/**
* Get the auto-incrementing key type.
*
* @return string
*/
public function getKeyType()
{
if (in_array($this->getKeyName(), $this->uniqueIds())) {
return 'string';
}
return $this->keyType;
}
/**
* Get the value indicating whether the IDs are incrementing.
*
* @return bool
*/
public function getIncrementing()
{
if (in_array($this->getKeyName(), $this->uniqueIds())) {
return false;
}
return $this->incrementing;
}
}

View File

@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Database\Model\Concerns;
use Hyperf\Utils\Str;
trait HasUuids
{
/**
* Generate a new UUID for the model.
*
* @return string
*/
public function newUniqueId()
{
return (string) Str::orderedUuid();
}
/**
* Get the columns that should receive a unique identifier.
*
* @return array
*/
public function uniqueIds()
{
return [$this->getKeyName()];
}
/**
* Get the auto-incrementing key type.
*
* @return string
*/
public function getKeyType()
{
if (in_array($this->getKeyName(), $this->uniqueIds())) {
return 'string';
}
return $this->keyType;
}
/**
* Get the value indicating whether the IDs are incrementing.
*
* @return bool
*/
public function getIncrementing()
{
if (in_array($this->getKeyName(), $this->uniqueIds())) {
return false;
}
return $this->incrementing;
}
}

View File

@ -963,6 +963,18 @@ class Blueprint
return $this->bigIncrements($column);
}
/**
* Create a new ULID column on the table.
*
* @param string $column
* @param null|int $length
* @return \Hyperf\Database\Schema\ColumnDefinition
*/
public function ulid($column = 'ulid', $length = 26)
{
return $this->char($column, $length);
}
/**
* Create a new uuid column on the table.
*
@ -1271,6 +1283,22 @@ class Blueprint
return $this->index([new Expression($expression)], $name);
}
/**
* Create a new ULID column on the table with a foreign key constraint.
*
* @param string $column
* @param null|int $length
* @return ForeignIdColumnDefinition
*/
public function foreignUlid($column = 'ulid', $length = 26)
{
return $this->addColumnDefinition(new ForeignIdColumnDefinition($this, [
'type' => 'char',
'name' => $column,
'length' => $length,
]));
}
/**
* Create a new UUID column on the table with a foreign key constraint.
*

View File

@ -0,0 +1,59 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Database\Schema;
use Hyperf\Utils\Str;
class ForeignIdColumnDefinition extends ColumnDefinition
{
/**
* The schema builder blueprint instance.
*
* @var Blueprint
*/
protected $blueprint;
/**
* Create a new foreign ID column definition.
*
* @param array $attributes
*/
public function __construct(Blueprint $blueprint, $attributes = [])
{
parent::__construct($attributes);
$this->blueprint = $blueprint;
}
/**
* Create a foreign key constraint on this column referencing the "id" column of the conventionally related table.
*
* @param null|string $table
* @param string $column
* @return ForeignKeyDefinition
*/
public function constrained($table = null, $column = 'id')
{
return $this->references($column)->on($table ?? Str::plural(Str::beforeLast($this->name, '_' . $column)));
}
/**
* Specify which column this foreign ID references on another table.
*
* @param string $column
* @return ForeignKeyDefinition
*/
public function references($column)
{
return $this->blueprint->foreign($this->name)->references($column);
}
}

View File

@ -39,6 +39,7 @@ use Hyperf\Engine\Channel;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Utils\Collection as BaseCollection;
use Hyperf\Utils\InteractsWithTime;
use Hyperf\Utils\Str;
use HyperfTest\Database\Stubs\DateModelStub;
use HyperfTest\Database\Stubs\DifferentConnectionModelStub;
use HyperfTest\Database\Stubs\KeyTypeModelStub;
@ -57,6 +58,8 @@ use HyperfTest\Database\Stubs\ModelSaveStub;
use HyperfTest\Database\Stubs\ModelSavingEventStub;
use HyperfTest\Database\Stubs\ModelStub;
use HyperfTest\Database\Stubs\ModelStubWithTrait;
use HyperfTest\Database\Stubs\ModelStubWithUlid;
use HyperfTest\Database\Stubs\ModelStubWithUuid;
use HyperfTest\Database\Stubs\ModelWithoutRelationStub;
use HyperfTest\Database\Stubs\ModelWithoutTableStub;
use HyperfTest\Database\Stubs\ModelWithStub;
@ -1992,6 +1995,20 @@ class ModelTest extends TestCase
$chan->pop();
}
public function testUlid()
{
$model = new ModelStubWithUlid();
$this->assertTrue(Str::isUlid($model->newUniqueId()));
}
public function testUuid()
{
$model = new ModelStubWithUuid();
$this->assertTrue(Str::isUuid($model->newUniqueId()));
}
protected function getContainer()
{
$container = Mockery::mock(ContainerInterface::class);

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace HyperfTest\Database\Stubs;
use Hyperf\Database\Model\Concerns\HasUlids;
use Hyperf\Database\Model\Model;
class ModelStubWithUlid extends Model
{
use HasUlids;
protected ?string $table = 'stub';
protected string $primaryKey = 'id';
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace HyperfTest\Database\Stubs;
use Hyperf\Database\Model\Concerns\HasUuids;
use Hyperf\Database\Model\Model;
class ModelStubWithUuid extends Model
{
use HasUuids;
protected ?string $table = 'stub';
protected string $primaryKey = 'id';
}

View File

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\DbConnection\Listener;
use Hyperf\Database\Model\Concerns\HasUlids;
use Hyperf\Database\Model\Concerns\HasUuids;
use Hyperf\Database\Model\Events\Creating;
use Hyperf\Event\Contract\ListenerInterface;
class CreatingListener implements ListenerInterface
{
public function listen(): array
{
return [
Creating::class,
];
}
public function process(object $event): void
{
$model = $event->getModel();
$class = get_class($model);
foreach (class_uses_recursive($class) as $trait) {
if (! in_array($trait, [HasUuids::class, HasUlids::class])) {
continue;
}
foreach ($model->uniqueIds() as $column) {
if (empty($model->{$column})) {
$model->{$column} = $model->newUniqueId();
}
}
}
}
}