mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-12-03 12:17:48 +08:00
Merge pull request #1328 from kakuilan/master
Added `ModelRewriteInheritanceVisitor` to rewrite the model inheritance for command `gen:model`.
This commit is contained in:
commit
6daca6b65d
@ -2,6 +2,7 @@
|
||||
|
||||
## Added
|
||||
|
||||
- [#1328](https://github.com/hyperf/hyperf/pull/1328) Added `ModelRewriteInheritanceVisitor` to rewrite the model inheritance for command `gen:model`.
|
||||
- [#1331](https://github.com/hyperf/hyperf/pull/1331) Added `Hyperf\LoadBalancer\LoadBalancerInterface::getNodes()`.
|
||||
|
||||
## Changed
|
||||
|
103
src/database/src/Commands/Ast/ModelRewriteInheritanceVisitor.php
Normal file
103
src/database/src/Commands/Ast/ModelRewriteInheritanceVisitor.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://doc.hyperf.io
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace Hyperf\Database\Commands\Ast;
|
||||
|
||||
use Hyperf\Database\Commands\ModelData;
|
||||
use Hyperf\Database\Commands\ModelOption;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
|
||||
class ModelRewriteInheritanceVisitor extends NodeVisitorAbstract
|
||||
{
|
||||
/**
|
||||
* @var ModelOption
|
||||
*/
|
||||
protected $option;
|
||||
|
||||
/**
|
||||
* @var ModelData
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
protected $parentClass;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $shouldAddUseUse = true;
|
||||
|
||||
public function __construct(ModelOption $option, ModelData $data)
|
||||
{
|
||||
$this->option = $option;
|
||||
$this->data = $data;
|
||||
|
||||
if (! empty($option->getUses())) {
|
||||
preg_match_all('/\s*([a-z0-9\\\\]+)(as)?([a-z0-9]+)?;?\s*/is', $option->getUses(), $match);
|
||||
if (isset($match[1][0])) {
|
||||
$this->parentClass = $match[1][0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function afterTraverse(array $nodes)
|
||||
{
|
||||
if (empty($this->option->getUses())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$use = new Node\Stmt\UseUse(
|
||||
new Node\Name($this->parentClass),
|
||||
$this->option->getInheritance()
|
||||
);
|
||||
|
||||
foreach ($nodes as $namespace) {
|
||||
if (! $namespace instanceof Node\Stmt\Namespace_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->shouldAddUseUse) {
|
||||
array_unshift($namespace->stmts, new Node\Stmt\Use_([$use]));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node)
|
||||
{
|
||||
switch ($node) {
|
||||
case $node instanceof Node\Stmt\Class_:
|
||||
$inheritance = $this->option->getInheritance();
|
||||
if (is_object($node->extends) && ! empty($inheritance)) {
|
||||
$node->extends->parts = [$inheritance];
|
||||
}
|
||||
return $node;
|
||||
case $node instanceof Node\Stmt\UseUse:
|
||||
$class = implode('\\', $node->name->parts);
|
||||
$alias = is_object($node->alias) ? $node->alias->name : null;
|
||||
if ($class == $this->parentClass) {
|
||||
// The parent class is exists.
|
||||
$this->shouldAddUseUse = false;
|
||||
if (end($node->name->parts) !== $this->option->getInheritance() && $alias !== $this->option->getInheritance()) {
|
||||
// Rewrite the alias, if the class is not equal with inheritance.
|
||||
$node->alias = new Identifier($this->option->getInheritance());
|
||||
}
|
||||
}
|
||||
return $node;
|
||||
}
|
||||
}
|
||||
}
|
@ -98,7 +98,8 @@ class ModelCommand extends Command
|
||||
->setRefreshFillable($this->getOption('refresh-fillable', 'commands.gen:model.refresh_fillable', $pool, false))
|
||||
->setTableMapping($this->getOption('table-mapping', 'commands.gen:model.table_mapping', $pool, []))
|
||||
->setIgnoreTables($this->getOption('ignore-tables', 'commands.gen:model.ignore_tables', $pool, []))
|
||||
->setWithComments($this->getOption('with-comments', 'commands.gen:model.with_comments', $pool, false));
|
||||
->setWithComments($this->getOption('with-comments', 'commands.gen:model.with_comments', $pool, false))
|
||||
->setVisitors($this->getOption('visitors', 'commands.gen:model.visitors', $pool, []));
|
||||
|
||||
if ($table) {
|
||||
$this->createModel($table, $option);
|
||||
@ -121,6 +122,7 @@ class ModelCommand extends Command
|
||||
$this->addOption('table-mapping', 'M', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Table mappings for model.');
|
||||
$this->addOption('ignore-tables', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Ignore tables for creating models.');
|
||||
$this->addOption('with-comments', null, InputOption::VALUE_NONE, 'Whether generate the property comments for model.');
|
||||
$this->addOption('visitors', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Custom visitors for ast traverser.');
|
||||
}
|
||||
|
||||
protected function getSchemaBuilder(string $poolName): MySqlBuilder
|
||||
@ -172,7 +174,6 @@ class ModelCommand extends Command
|
||||
if (! is_dir($dir)) {
|
||||
@mkdir($dir, 0755, true);
|
||||
}
|
||||
|
||||
file_put_contents($path, $this->buildClass($table, $class, $option));
|
||||
}
|
||||
|
||||
@ -180,12 +181,15 @@ class ModelCommand extends Command
|
||||
|
||||
$stms = $this->astParser->parse(file_get_contents($path));
|
||||
$traverser = new NodeTraverser();
|
||||
$visitor = make(ModelUpdateVisitor::class, [
|
||||
$traverser->addVisitor(make(ModelUpdateVisitor::class, [
|
||||
'columns' => $columns,
|
||||
'option' => $option,
|
||||
]);
|
||||
$traverser->addVisitor($visitor);
|
||||
]));
|
||||
$traverser->addVisitor(make(ModelRewriteConnectionVisitor::class, [$class, $option->getPool()]));
|
||||
foreach ($option->getVisitors() as $visitorClass) {
|
||||
$data = make(ModelData::class)->setClass($class)->setColumns($columns);
|
||||
$traverser->addVisitor(make($visitorClass, [$option, $data]));
|
||||
}
|
||||
$stms = $traverser->traverse($stms);
|
||||
$code = $this->printer->prettyPrintFile($stms);
|
||||
|
||||
@ -233,7 +237,7 @@ class ModelCommand extends Command
|
||||
if (in_array($name, ['force-casts', 'refresh-fillable', 'with-comments'])) {
|
||||
$nonInput = false;
|
||||
}
|
||||
if (in_array($name, ['table-mapping', 'ignore-tables'])) {
|
||||
if (in_array($name, ['table-mapping', 'ignore-tables', 'visitors'])) {
|
||||
$nonInput = [];
|
||||
}
|
||||
|
||||
|
48
src/database/src/Commands/ModelData.php
Normal file
48
src/database/src/Commands/ModelData.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://doc.hyperf.io
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace Hyperf\Database\Commands;
|
||||
|
||||
class ModelData
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $columns;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $class;
|
||||
|
||||
public function getColumns(): array
|
||||
{
|
||||
return $this->columns;
|
||||
}
|
||||
|
||||
public function setColumns(array $columns): self
|
||||
{
|
||||
$this->columns = $columns;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getClass(): string
|
||||
{
|
||||
return $this->class;
|
||||
}
|
||||
|
||||
public function setClass(string $class): self
|
||||
{
|
||||
$this->class = $class;
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -64,12 +64,17 @@ class ModelOption
|
||||
*/
|
||||
protected $ignoreTables = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $visitors = [];
|
||||
|
||||
public function getPool(): string
|
||||
{
|
||||
return $this->pool;
|
||||
}
|
||||
|
||||
public function setPool(string $pool): ModelOption
|
||||
public function setPool(string $pool): self
|
||||
{
|
||||
$this->pool = $pool;
|
||||
return $this;
|
||||
@ -80,7 +85,7 @@ class ModelOption
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
public function setPath(string $path): ModelOption
|
||||
public function setPath(string $path): self
|
||||
{
|
||||
$this->path = $path;
|
||||
return $this;
|
||||
@ -91,7 +96,7 @@ class ModelOption
|
||||
return $this->forceCasts;
|
||||
}
|
||||
|
||||
public function setForceCasts(bool $forceCasts): ModelOption
|
||||
public function setForceCasts(bool $forceCasts): self
|
||||
{
|
||||
$this->forceCasts = $forceCasts;
|
||||
return $this;
|
||||
@ -102,7 +107,7 @@ class ModelOption
|
||||
return $this->prefix;
|
||||
}
|
||||
|
||||
public function setPrefix(string $prefix): ModelOption
|
||||
public function setPrefix(string $prefix): self
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
return $this;
|
||||
@ -113,7 +118,7 @@ class ModelOption
|
||||
return $this->inheritance;
|
||||
}
|
||||
|
||||
public function setInheritance(string $inheritance): ModelOption
|
||||
public function setInheritance(string $inheritance): self
|
||||
{
|
||||
$this->inheritance = $inheritance;
|
||||
return $this;
|
||||
@ -124,7 +129,7 @@ class ModelOption
|
||||
return $this->uses;
|
||||
}
|
||||
|
||||
public function setUses(string $uses): ModelOption
|
||||
public function setUses(string $uses): self
|
||||
{
|
||||
$this->uses = $uses;
|
||||
return $this;
|
||||
@ -135,7 +140,7 @@ class ModelOption
|
||||
return $this->refreshFillable;
|
||||
}
|
||||
|
||||
public function setRefreshFillable(bool $refreshFillable): ModelOption
|
||||
public function setRefreshFillable(bool $refreshFillable): self
|
||||
{
|
||||
$this->refreshFillable = $refreshFillable;
|
||||
return $this;
|
||||
@ -146,7 +151,7 @@ class ModelOption
|
||||
return $this->tableMapping;
|
||||
}
|
||||
|
||||
public function setTableMapping(array $tableMapping): ModelOption
|
||||
public function setTableMapping(array $tableMapping): self
|
||||
{
|
||||
foreach ($tableMapping as $item) {
|
||||
[$key, $name] = explode(':', $item);
|
||||
@ -161,7 +166,7 @@ class ModelOption
|
||||
return $this->ignoreTables;
|
||||
}
|
||||
|
||||
public function setIgnoreTables(array $ignoreTables): ModelOption
|
||||
public function setIgnoreTables(array $ignoreTables): self
|
||||
{
|
||||
$this->ignoreTables = $ignoreTables;
|
||||
return $this;
|
||||
@ -172,9 +177,20 @@ class ModelOption
|
||||
return $this->withComments;
|
||||
}
|
||||
|
||||
public function setWithComments(bool $withComments): ModelOption
|
||||
public function setWithComments(bool $withComments): self
|
||||
{
|
||||
$this->withComments = $withComments;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVisitors(): array
|
||||
{
|
||||
return $this->visitors;
|
||||
}
|
||||
|
||||
public function setVisitors(array $visitors): self
|
||||
{
|
||||
$this->visitors = $visitors;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -408,7 +408,7 @@ class Blueprint
|
||||
*
|
||||
* @param array|string $columns
|
||||
* @param string $name
|
||||
* @return \Hyperf\Utils\Fluent|\Hyperf\Database\Schema\ForeignKeyDefinition
|
||||
* @return \Hyperf\Database\Schema\ForeignKeyDefinition|\Hyperf\Utils\Fluent
|
||||
*/
|
||||
public function foreign($columns, $name = null)
|
||||
{
|
||||
|
@ -15,7 +15,7 @@ namespace Hyperf\Database\Schema;
|
||||
use Hyperf\Utils\Fluent;
|
||||
|
||||
/**
|
||||
* @method ForeignKeyDefinition references(string|array $columns) Specify the referenced column(s)
|
||||
* @method ForeignKeyDefinition references(array|string $columns) Specify the referenced column(s)
|
||||
* @method ForeignKeyDefinition on(string $table) Specify the referenced table
|
||||
* @method ForeignKeyDefinition onDelete(string $action) Add an ON DELETE action
|
||||
* @method ForeignKeyDefinition onUpdate(string $action) Add an ON UPDATE action
|
||||
@ -24,4 +24,4 @@ use Hyperf\Utils\Fluent;
|
||||
*/
|
||||
class ForeignKeyDefinition extends Fluent
|
||||
{
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user