public function testBasicInflector() { $inflector = \LazyRecord\Inflector::getInstance(); is('posts', $inflector->pluralize('post')); is('blogs', $inflector->pluralize('blog')); is('categories', $inflector->pluralize('category')); is('post', $inflector->singularize('posts')); is('CreateUser', $inflector->camelize('create_user')); is('create_user', $inflector->underscore('CreateUser')); is('Create User', $inflector->humanize('create_user')); is('user_roles', $inflector->tableize('UserRole')); is('UserRole', $inflector->classify('user_roles')); }
public function reverseTableSchema($table, $referenceSchema = null) { $stm = $this->connection->query("SHOW COLUMNS FROM {$table}"); $schema = new DeclareSchema(); $schema->columnNames = $schema->columns = array(); $schema->table($table); $rows = $stm->fetchAll(); foreach ($rows as $row) { $type = $row['Type']; $typeInfo = TypeInfoParser::parseTypeInfo($type, $this->driver); $isa = $typeInfo->isa; $column = $schema->column($row['Field']); $column->type($typeInfo->type); if ($typeInfo->length) { $column->length($typeInfo->length); } if ($typeInfo->precision) { $column->decimals($typeInfo->precision); } if ($typeInfo->isa) { $column->isa($typeInfo->isa); } if ($typeInfo->unsigned) { $column->unsigned(); } if ($typeInfo->enum) { $column->enum($typeInfo->enum); } elseif ($typeInfo->set) { $column->set($typeInfo->set); } switch ($row['Null']) { case 'NO': // timestamp is set to Null=No by default. // However, it's possible that user didn't set notNull in the schema, // we should skip the check in comparator. if ($referenceSchema && isset($row['Field']) && $referenceSchema->getColumn($row['Field']) && !$referenceSchema->getColumn($row['Field'])->notNull && (strtolower($typeInfo->type) === 'timestamp' || isset($row['Key']) && $row['Key'] === 'PRI')) { } else { $column->notNull(true); } break; case 'YES': $column->null(); break; } switch ($row['Key']) { case 'PRI': $column->primary(true); $schema->primaryKey = $row['Field']; break; // If Key is MUL, multiple occurrences of a given value are // permitted within the column. The column is the first // column of a nonunique index or a unique-valued index // that can contain NULL values. // If Key is MUL, multiple occurrences of a given value are // permitted within the column. The column is the first // column of a nonunique index or a unique-valued index // that can contain NULL values. case 'MUL': break; case 'UNI': $column->unique(true); break; } // Parse information from the Extra field // @see https://dev.mysql.com/doc/refman/5.7/en/show-columns.html $extraAttributes = []; if (strtolower($row['Extra']) == 'auto_increment') { $column->autoIncrement(); } elseif (preg_match('/ON UPDATE (\\w+)/i', $row['Extra'], $matches)) { /* To specify automatic properties, use the DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP clauses in column definitions. The order of the clauses does not matter. If both are present in a column definition, either can occur first. Any of the synonyms for CURRENT_TIMESTAMP have the same meaning as CURRENT_TIMESTAMP. These are CURRENT_TIMESTAMP(), NOW(), LOCALTIME, LOCALTIME(), LOCALTIMESTAMP, and LOCALTIMESTAMP(). */ $extraAttributes['OnUpdate' . Inflector::getInstance()->camelize(strtolower($matches[1]))] = true; } elseif (preg_match('/VIRTUAL GENERATED/i', $row['Extra'])) { $extraAttributes['VirtualGenerated'] = true; } elseif (preg_match('/VIRTUAL STORED/i', $row['Extra'])) { $extraAttributes['VirtualStored'] = true; } // The default value returned from MySQL is string, we need the // type information to cast them to PHP Scalar or other // corresponding type if (null !== $row['Default']) { $default = $row['Default']; if ($typeInfo->type == 'boolean') { if ($default == '1') { $column->default(true); } elseif ($default == '0') { $column->default(false); } } elseif ($typeInfo->isa == 'int') { $column->default(intval($default)); } elseif ($typeInfo->isa == 'double') { $column->default(doubleval($default)); } elseif ($typeInfo->isa == 'float') { $column->default(floatval($default)); } elseif ($typeInfo->isa == 'str') { $column->default($default); } elseif ($typeInfo->type == 'timestamp') { // for mysql, timestamp fields' default value is // 'current_timestamp' and 'on update current_timestamp' // when the two conditions are matched, we need to elimante // the default value just as what we've defined in schema. if (isset($extraAttributes['OnUpdateCurrentTimestamp']) && strtolower($default) == 'current_timestamp') { // Don't set default value } elseif (strtolower($default) == 'current_timestamp') { $column->default(new Raw($default)); } elseif (is_numeric($default)) { $column->default(intval($default)); } } elseif ($typeInfo->type == 'datetime') { // basically, CURRENT_TIMESTAMP, transaction_timestamp() // and now() do exactly the same. CURRENT_TIMESTAMP is a // syntactical oddity for a function, having no trailing // pair of parentheses. That's according to the SQL // standard. // // @see http://dba.stackexchange.com/questions/63548/difference-between-now-and-current-timestamp if (strtolower($default) == 'current_timestamp') { // XXX: NOW() will be converted into current_timestamp $column->default(new Raw($default)); } } } } return $schema; }