-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Add CakePHP ORM #428
Add CakePHP ORM #428
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<?php | ||
|
||
namespace Faker\ORM\CakePHP; | ||
|
||
class ColumnTypeGuesser | ||
{ | ||
protected $generator; | ||
|
||
public function __construct(\Faker\Generator $generator) | ||
{ | ||
$this->generator = $generator; | ||
} | ||
|
||
public function guessFormat($column, $table) | ||
{ | ||
$generator = $this->generator; | ||
$schema = $table->schema(); | ||
|
||
switch ($schema->columnType($column)) { | ||
case 'boolean': | ||
return function() use ($generator) { | ||
return $generator->boolean; | ||
}; | ||
case 'integer': | ||
return function() { | ||
return mt_rand(0, intval('2147483647')); | ||
}; | ||
case 'biginteger': | ||
return function() { | ||
return mt_rand(0, intval('18446744073709551615')); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. may break on 32bits systems There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See above comment - then Propel would break too? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. probably... |
||
}; | ||
case 'decimal': | ||
case 'float': | ||
return function() { | ||
return mt_rand(0, intval('4294967295')) / mt_rand(1, intval('4294967295')); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as before. |
||
}; | ||
case 'uuid': | ||
return function() { | ||
return \Cake\Utility\String::uuid(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not use Faker's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can change that. |
||
}; | ||
case 'string': | ||
$columnData = $schema->column($column); | ||
$length = $columnData['length']; | ||
return function () use ($generator, $length) { | ||
return $generator->text($length); | ||
}; | ||
case 'text': | ||
return function () use ($generator) { | ||
return $generator->text(); | ||
}; | ||
case 'date': | ||
case 'datetime': | ||
case 'timestamp': | ||
case 'time': | ||
return function () use ($generator) { | ||
return $generator->datetime(); | ||
}; | ||
|
||
case 'binary': | ||
default: | ||
return null; | ||
} | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
<?php | ||
|
||
namespace Faker\ORM\CakePHP; | ||
|
||
use Cake\ORM\TableRegistry; | ||
use Faker\Guesser\Name as NameGuesser; | ||
|
||
class EntityPopulator | ||
{ | ||
protected $class; | ||
protected $columnFormatters = []; | ||
protected $modifiers = []; | ||
|
||
public function __construct($class) | ||
{ | ||
$this->class = $class; | ||
} | ||
|
||
public function __get($name) | ||
{ | ||
return $this->{$name}; | ||
} | ||
|
||
public function __set($name, $value) | ||
{ | ||
$this->{$name} = $value; | ||
} | ||
|
||
public function mergeColumnFormattersWith($columnFormatters) | ||
{ | ||
$this->columnFormatters = array_merge($this->columnFormatters, $columnFormatters); | ||
} | ||
|
||
public function mergeModifiersWith($modifiers) | ||
{ | ||
$this->modifiers = array_merge($this->modifiers, $modifiers); | ||
} | ||
|
||
public function guessColumnFormatters($populator) | ||
{ | ||
$formatters = []; | ||
$class = $this->class; | ||
$table = TableRegistry::get($class); | ||
$schema = $table->schema(); | ||
$pk = $schema->primaryKey(); | ||
$guessers = $populator->getGuessers() + ['ColumnTypeGuesser' => new ColumnTypeGuesser($populator->getGenerator())]; | ||
$isForeignKey = function ($column) use ($table) { | ||
foreach ($table->associations()->type('BelongsTo') as $assoc) { | ||
if ($column == $assoc->foreignKey()) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
}; | ||
|
||
|
||
foreach ($schema->columns() as $column) { | ||
if ($column == $pk[0] || $isForeignKey($column)) { | ||
continue; | ||
} | ||
|
||
foreach ($guessers as $guesser) { | ||
if ($formatter = $guesser->guessFormat($column, $table)) { | ||
$formatters[$column] = $formatter; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
return $formatters; | ||
} | ||
|
||
public function guessModifiers($populator) | ||
{ | ||
$modifiers = []; | ||
$table = TableRegistry::get($this->class); | ||
|
||
$belongsTo = $table->associations()->type('BelongsTo'); | ||
foreach ($belongsTo as $assoc) { | ||
$modifiers['belongsTo' . $assoc->name()] = function ($data, $insertedEntities) use ($assoc) { | ||
$table = $assoc->target(); | ||
$foreignModel = $table->alias(); | ||
$foreignKey = $insertedEntities[$foreignModel][array_rand($insertedEntities[$foreignModel])]; | ||
$primaryKey = $table->primaryKey(); | ||
$data[$assoc->foreignKey()] = $foreignKey; | ||
return $data; | ||
}; | ||
} | ||
|
||
// TODO check if TreeBehavior attached to modify lft/rgt cols | ||
|
||
return $modifiers; | ||
} | ||
|
||
public function execute($class, $insertedEntities, $options = []) | ||
{ | ||
$table = TableRegistry::get($class); | ||
$entity = $table->newEntity(); | ||
|
||
foreach ($this->columnFormatters as $column => $format) { | ||
if (!is_null($format)) { | ||
$entity->{$column} = is_callable($format) ? $format($insertedEntities, $table) : $format; | ||
} | ||
} | ||
|
||
foreach ($this->modifiers as $modifier) { | ||
$entity = $modifier($entity, $insertedEntities); | ||
} | ||
|
||
if (!$entity = $table->save($entity, $options)) { | ||
throw new \RuntimeException("Failed saving $class record"); | ||
} | ||
|
||
$pk = $table->primaryKey(); | ||
return $entity->{$pk}; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<?php | ||
|
||
namespace Faker\ORM\CakePHP; | ||
|
||
class Populator | ||
{ | ||
|
||
protected $generator; | ||
protected $entities = []; | ||
protected $quantities = []; | ||
protected $guessers = []; | ||
|
||
public function __construct(\Faker\Generator $generator) | ||
{ | ||
$this->generator = $generator; | ||
} | ||
|
||
public function getGenerator() | ||
{ | ||
return $this->generator; | ||
} | ||
|
||
public function getGuessers() | ||
{ | ||
return $this->guessers; | ||
} | ||
|
||
public function removeGuesser($name) | ||
{ | ||
if ($this->guessers[$name]) { | ||
unset($this->guessers[$name]); | ||
} | ||
return $this; | ||
} | ||
|
||
public function addGuesser($class) | ||
{ | ||
if (!is_object($class)) { | ||
$class = new $class($this->generator); | ||
} | ||
|
||
if (!method_exists($class, 'guessFormat')) { | ||
throw new \Exception('Missing required custom guesser method: ' . get_class($class) . '::guessFormat()'); | ||
} | ||
|
||
$this->guessers[get_class($class)] = $class; | ||
return $this; | ||
} | ||
|
||
public function addEntity($entity, $number, $customColumnFormatters = [], $customModifiers = []) | ||
{ | ||
if (!$entity instanceof EntityPopulator) { | ||
$entity = new EntityPopulator($entity); | ||
} | ||
|
||
$entity->columnFormatters = $entity->guessColumnFormatters($this); | ||
if ($customColumnFormatters) { | ||
$entity->mergeColumnFormattersWith($customColumnFormatters); | ||
} | ||
|
||
$entity->modifiers = $entity->guessModifiers($this); | ||
if ($customModifiers) { | ||
$entity->mergeModifiers($customModifiers); | ||
} | ||
|
||
$class = $entity->class; | ||
$this->entities[$class] = $entity; | ||
$this->quantities[$class] = $number; | ||
return $this; | ||
} | ||
|
||
public function execute($options = []) | ||
{ | ||
$insertedEntities = []; | ||
|
||
foreach ($this->quantities as $class => $number) { | ||
for ($i = 0; $i < $number; $i++) { | ||
$insertedEntities[$class][] = $this->entities[$class]->execute($class, $insertedEntities, $options); | ||
} | ||
} | ||
|
||
return $insertedEntities; | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not use `randomNumber()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can change those, I took those directly from here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
randomFloat
formatter and others were probably added after the Propel ORM populator. But they are faster and more robust than usingmt_rand()
(see their code).