Skip to content

Instantly share code, notes, and snippets.

@davebarnwell
Last active July 7, 2017 09:36
Show Gist options
  • Select an option

  • Save davebarnwell/9bef38967d30bead4230bbbf6871cce0 to your computer and use it in GitHub Desktop.

Select an option

Save davebarnwell/9bef38967d30bead4230bbbf6871cce0 to your computer and use it in GitHub Desktop.
generate PHP docblock @properties from a mysql table, great when using magic setters and getters
#!/usr/bin/env php
<?php
/**
* Generate PHP Doc blocks @property values for a given table
* helps when a class wraps a table and the class uses magic setters and getters
*
* Usage:-
* ./propsOfTable.php {mysqlTableName}
*/
$database = 'your_database';
$user = 'your_db_user';
$password = 'your_db_password';
$db = new PDO($dsn = 'mysql:dbname=' . $database . ';host=127.0.0.1', $user, $password);
$tableName = $argv[1] ?? null;
if (empty($tableName)) {
echo <<<HELP
First parameter must be a table name in $database
HELP;
exit;
}
$obj = new mysqlTableToPhp($tableName, $db);
$maxFieldNameWidth = 0;
foreach ($obj->getPhpDocPropertyIterator() as $property) {
$maxFieldNameWidth = max($maxFieldNameWidth, strlen($property->name));
}
echo '/**' . PHP_EOL;
echo ' * table fields : auto-generated by .' . __FILE__ . ' ' . $tableName . PHP_EOL;
echo ' *' . PHP_EOL;
foreach ($obj->getPhpDocPropertyIterator() as $property) {
echo sprintf(" * @property %-6s $%-{$maxFieldNameWidth}s %s\n", $property->type, $property->name,
$property->comment);
}
echo ' */' . PHP_EOL;
class mysqlTableToPhp
{
private $tableName;
private $db;
public function __construct(string $tableName, PDO $db)
{
$this->tableName = $tableName;
$this->db = $db;
}
/**
* @return PDOStatement
*/
private function getTableColumnQuery()
{
return $this->db->query('SHOW columns FROM ' . $this->tableName);
}
/**
* @return Generator
*/
public function getColumnIterator()
{
$result = $this->getTableColumnQuery();
while ($row = $result->fetchObject()) {
yield $row;
}
}
/**
* @return Generator
*/
public function getPhpDocPropertyIterator()
{
foreach ($this->getColumnIterator() as $row) {
$props = new stdClass();
$props->name = $row->Field;
$props->type = $this->getTypeFromDbType($row->Type);
$props->comment = $this->getCommentFromDbType($row->Type, $row->Null);
yield $props;
}
}
private function getTypeFromDbType(string $type)
{
switch ($type) {
case 'blob':
case 'tinyblob':
case 'mediumblob':
case 'longblob':
case 'varbinary':
case 'binary':
case 'text':
case 'tinytext':
case 'mediumtext':
case 'longtext':
case 'time':
case 'date':
case 'datetime':
case 'timestamp':
case 'year':
return 'string';
case 'bit':
case 'bool':
case 'boolean':
return 'int';
default:
// Fields with additional options
if (preg_match('/^(float|decimal|dec|double)/', $type) == 1) {
return 'float';
}
if (preg_match('/^(tinyint|int|mediumint|smallint|integer|bigint|serial)/', $type) == 1) {
return 'int';
}
if (preg_match('/^(varchar|char|enum|set)/', $type) == 1) {
return 'string';
}
break;
}
}
private function getCommentFromDbType(string $type, string $nullAllowed)
{
$format = [];
$optionsLabel = 'size: ';
switch ($type) {
case 'time':
$format[] = 'format: H:i:s';
break;
case 'date':
$format[] = 'format: Y-m-d';
break;
case 'datetime':
case 'timestamp':
$format[] = 'format: Y-m-d H:i:s';
break;
case 'year':
$format[] = 'format: Y';
break;
case 'bit':
case 'bool':
case 'boolean':
break;
default:
if (preg_match('/^(enum|set)/', $type, $matches) == 1) {
$optionsLabel = $matches[1] . ': ';
}
break;
}
if (preg_match_all('/\(([^\(]+)\)/', $type, $matches) == 1) {
$format[] = $optionsLabel . $matches[1][0];
}
if (preg_match('/unsigned/', $type) == 1) {
$format[] = 'unsigned';
}
$format[] = $nullAllowed == 'YES' ? 'Null Allowed' : 'Not Null';
return implode('; ', $format);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment