Compare commits

..

No commits in common. "main" and "v1.0.1" have entirely different histories.
main ... v1.0.1

6 changed files with 82 additions and 116 deletions

View File

@ -195,59 +195,3 @@ print_r($result);
?> ?>
``` ```
## Maintenance of database schema
When developing a project, a situation arises where the DB schema needs to be modified and distributed to all installations. To ease these problems, the Maintenance class was created, which contains several useful methods. These first check if the schema contains the requested change and if it doesn't, they apply a FIX. Here is a short demonstration of what we can fix automatically in the project when changing the DB schema.
```php
<?php
require_once __DIR__.'/../src/DBmodel.php';
require_once __DIR__.'/../src/Maintenance.php';
$db = new \TPsoft\DBmodel\DBmodel('mysql:host=127.0.0.1;dbname=test;charset=utf8mb4', 'test', 'test');
$maintenance = new \TPsoft\DBmodel\Maintenance($db);
// Check if existing table, if not create it by definition
$suc = $maintenance->checkDBTable('users', '
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
');
echo "\nCheckDBTable: "; var_dump($suc);
// Check if existing column, if not add it by definition
$suc = $maintenance->checkDBAdd('users', 'password', 'varchar(255) DEFAULT NULL');
echo "\nCheckDBAdd: "; var_dump($suc);
// Check if existing column
$suc = $maintenance->existsColumn('users', 'email');
echo "\nExistsColumn: "; var_dump($suc);
// Check if existing column in new name, if not rename it
$suc = $maintenance->checkDBRename('users', 'email', 'email_new', 'varchar(255) DEFAULT NULL');
echo "\nCheckDBRename: "; var_dump($suc);
// Chceck type of column, if not matched change it
$suc = $maintenance->checkDBRetype('users', 'email_new', 'varchar(128)', 'varchar(128) DEFAULT NULL AFTER `password`');
echo "\nCheckDBRetype: "; var_dump($suc);
// Remove column from table
$suc = $maintenance->checkDBRemove('users', 'email_new');
echo "\nCheckDBRemove: "; var_dump($suc);
// Add index for column
$suc = $maintenance->addKey('users', 'name');
echo "\nAddKey: "; var_dump($suc);
// Drop index by column name
$suc = $maintenance->dropKey('users', 'name');
echo "\nDropKey: "; var_dump($suc);
echo "\nDone\n\n";
?>
```

65
models/Test.php Normal file
View File

@ -0,0 +1,65 @@
<?php
/*
TPsoft.org 2000-2025
file for controlers/*.php
Molestones:
2025-05-27 21:36 Created
*/
class Test extends \TPsoft\DBmodel\DBmodel {
public $tables = array(
'test' => array(
'name' => 'test',
'primary_key_name' => 'id',
'allow_attributes' => array(
'name' => 'varchar(255)',
'created' => 'datetime'
)
),
);
public function exist($primary_key = null) {
return $this->existRecord('test', $primary_key);
}
public function test($primary_key = null, $data = array()) {
return $this->record('test', $primary_key, $data);
}
public function testBy($colname, $colvalue) {
return $this->recordBy('test', $colname, $colvalue);
}
public function testSave($data = array()) {
return $this->test($this->exist($data) ? $data : null, $data);
}
public function testEmpty() {
return $this->recordEmpty('test');
}
public function testAttributes() {
return $this->typesAttributes('test');
}
public function testCount() {
return $this->count('test');
}
public function getList($search = array(), $reverse = false, $concat_or = false) {
return $this->search('test')
->where($search, $concat_or)
->order(array('id' => $reverse ? 'DESC' : 'ASC'))
->toArray();
}
public function testCombo($col_key, $col_value, $add_empty = false) {
return $this->search('test')
->toCombo($col_key, $col_value, $add_empty);
}
}
?>

View File

@ -4,30 +4,20 @@ namespace TPsoft\DBmodel;
class Creator { class Creator {
private DBmodel $dbh; private $dbh;
private string $rootDir = '';
public function __construct(?DBmodel $dbh = null) { public function __construct($dbh) {
if (is_null($dbh)) { $this->dbh = $dbh;
if (!is_null(DBmodel::$instance)) {
$this->dbh = DBmodel::$instance;
} else {
throw new \Exception('DB handler is null');
}
} else {
$this->dbh = $dbh;
}
} }
public function interact() { public function interact() {
$name = $this->readline('New model name: '); $name = $this->readline('New model name: ');
$table = $this->readline('Table name: '); $table = $this->readline('Table name: ');
$entity = $this->readline('Entity name: '); $entity = $this->readline('Entity name: ');
$namespace = $this->readline('Namespace [App\Models]: ', 'App\Models');
if (strlen($entity) <= 0) { if (strlen($entity) <= 0) {
$entity = $table; $entity = $table;
} }
$model_filepath = $this->rootDir().'/Models/'.$name.'.php'; $model_filepath = $this->rootDir().'/models/'.$name.'.php';
if ($this->readline("Create MODEL class '$model_filepath'? (y - yes, other - no) ") != 'y') { if ($this->readline("Create MODEL class '$model_filepath'? (y - yes, other - no) ") != 'y') {
echo "Creating of MODEL class is skipped\n"; echo "Creating of MODEL class is skipped\n";
return false; return false;
@ -48,11 +38,11 @@ class Creator {
} }
} }
$table_columns = $this->dbh->getTableColumns($table); $table_columns = $this->dbh->getTableColumns($table);
$suc = $this->modelSave($model_filepath, $name, $table, $entity, $table_columns['pks'], $table_columns['columns'], $table_columns['types'], $namespace); $suc = $this->modelSave($model_filepath, $name, $table, $entity, $table_columns['pks'], $table_columns['columns'], $table_columns['types']);
echo $suc ? "MODEL class created" : 'Error: MODEL class not created'; echo $suc ? "MODEL class created" : 'Error: MODEL class not created';
} }
private function modelSave($filepath, $name, $tablename, $entity, $pks, $columns, $types, $namespace) { private function modelSave($filepath, $name, $tablename, $entity, $pks, $columns, $types) {
if (is_array($pks) && count($pks) > 1) { if (is_array($pks) && count($pks) > 1) {
$primary_key_name = "array('".implode("', '", $pks)."')"; $primary_key_name = "array('".implode("', '", $pks)."')";
$columns = array_merge($pks, $columns); $columns = array_merge($pks, $columns);
@ -94,7 +84,6 @@ class Creator {
$data[\'changed_dt\'] = date(\'Y-m-d H:i:s\'); $data[\'changed_dt\'] = date(\'Y-m-d H:i:s\');
}' }'
: ''; : '';
$namespace_str = strlen($namespace) > 0 ? "\nnamespace $namespace;\n" : '';
$content = '<?'."php $content = '<?'."php
/* /*
TPsoft.org 2000-".date('Y')." TPsoft.org 2000-".date('Y')."
@ -103,12 +92,12 @@ class Creator {
Milestones: Milestones:
".date('Y-m-d H:i')." Created ".date('Y-m-d H:i')." Created
*/ */
".$namespace_str."
class ".$name." extends \TPsoft\DBmodel\DBmodel { class ".$name." extends \TPsoft\DBmodel\DBmodel {
public $"."tables = array( public $"."tables = array(
'".$entity."' => array( '".$entity."' => array(
'name' => '".$tablename."', 'name' => '".$entity."',
'primary_key_name' => ".$primary_key_name.", 'primary_key_name' => ".$primary_key_name.",
'allow_attributes' => array( 'allow_attributes' => array(
".implode(",\n\t\t\t\t", $allowed_attributes)." ".implode(",\n\t\t\t\t", $allowed_attributes)."
@ -151,19 +140,6 @@ class ".$name." extends \TPsoft\DBmodel\DBmodel {
->toArray(); ->toArray();
} }
public function getListOrganize($"."cola_name, $"."search = array(), $"."reverse = false, $"."concat_or = false) {
$"."all = $"."this->getList($"."search, $"."reverse, $"."concat_or);
$"."ret = array();
if (is_array($"."all)) foreach ($"."all as $"."key => $"."row) {
$"."ret[$"."row[$"."cola_name]] = $"."row;
}
return $"."ret;
}
public function getListByID($"."search = array(), $"."reverse = false, $"."concat_or = false) {
return $"."this->getListOrganize($primary_key_name, $"."search, $"."reverse, $"."concat_or);
}
public function ".$entity_one."Combo($"."col_key, $"."col_value, $"."add_empty = false) { public function ".$entity_one."Combo($"."col_key, $"."col_value, $"."add_empty = false) {
return $"."this->search('".$entity."') return $"."this->search('".$entity."')
->toCombo($"."col_key, $"."col_value, $"."add_empty); ->toCombo($"."col_key, $"."col_value, $"."add_empty);
@ -190,14 +166,11 @@ class ".$name." extends \TPsoft\DBmodel\DBmodel {
return $line; return $line;
} }
public function rootDir(?string $dir = null) { public function rootDir() {
if (!is_null($dir)) {
$this->rootDir = $dir;
}
if (strlen($this->rootDir) > 0) return $this->rootDir;
return dirname(dirname(__FILE__)); return dirname(dirname(__FILE__));
} }
} }
?> ?>

View File

@ -674,12 +674,12 @@ class DBmodel
foreach ($data[$column] as $key => $val) { foreach ($data[$column] as $key => $val) {
$prefix = $this->extractPrefix($val, $where_prefixes); $prefix = $this->extractPrefix($val, $where_prefixes);
$n_val = str_replace($prefix, '', $val); $n_val = str_replace($prefix, '', $val);
$data[$column] = $prefix . date('Y-m-d H:i:s', is_numeric($n_val) ? $n_val : strtotime($n_val)); $data[$column] = $prefix . date('Y-m-d H:i:s', strtotime($n_val));
} }
} else { } else {
$prefix = $this->extractPrefix($data[$column], $where_prefixes); $prefix = $this->extractPrefix($data[$column], $where_prefixes);
$n_val = str_replace($prefix, '', $data[$column]); $n_val = str_replace($prefix, '', $data[$column]);
$data[$column] = $prefix . date('Y-m-d H:i:s', is_numeric($n_val) ? $n_val : strtotime($n_val)); $data[$column] = $prefix . date('Y-m-d H:i:s', strtotime($n_val));
} }
break; break;
} }
@ -851,7 +851,7 @@ class DBmodel
return $this->allowNextError(); return $this->allowNextError();
} }
public function import(DBmodel $objModel) public function import($objModel)
{ {
if (is_null($objModel)) return false; if (is_null($objModel)) return false;
if ( if (

View File

@ -24,7 +24,7 @@ class Maintenance
public string $lastMessage = ''; public string $lastMessage = '';
protected DBmodel $dbh; private DBmodel $dbh;
public function __construct(?DBmodel $dbh) public function __construct(?DBmodel $dbh)
{ {
@ -79,15 +79,7 @@ class Maintenance
return 0; return 0;
} }
public function existsTable($table_name) public function checkDBTable($table_name, $definition)
{
return $this->testDB(
'SHOW TABLES LIKE "' . $table_name . '"',
$table_name
);
}
public function checkDBTable($table_name, $definition, $after_definition = '')
{ {
if (strlen($table_name) <= 0) { if (strlen($table_name) <= 0) {
$this->lastMessage = 'Table ' . strtoupper($table_name) . ' - invalid index'; $this->lastMessage = 'Table ' . strtoupper($table_name) . ' - invalid index';
@ -99,7 +91,7 @@ class Maintenance
// TEST output // TEST output
$table_name, $table_name,
// FIX query // FIX query
'CREATE TABLE `' . $table_name . '` (' . $definition . ') ' . $after_definition 'CREATE TABLE `' . $table_name . '` (' . $definition . ')'
); );
$this->lastMessage = 'Table ' . strtoupper($table_name) . ' (' . $table_name . ')'; $this->lastMessage = 'Table ' . strtoupper($table_name) . ' (' . $table_name . ')';
return $status; return $status;
@ -146,7 +138,7 @@ class Maintenance
public function checkDBRetype($table_name, $column, $new_type, $definition) public function checkDBRetype($table_name, $column, $new_type, $definition)
{ {
if (!$this->existsColumn($table_name, $column)) { if (!$this->existsColumn($table_name, $column_old)) {
return Maintenance::ABNORMAL; return Maintenance::ABNORMAL;
} }
$status = $this->checkDB( $status = $this->checkDB(

View File

@ -7,7 +7,6 @@ $db = new \TPsoft\DBmodel\DBmodel('mysql:host=127.0.0.1;dbname=test;charset=utf8
$maintenance = new \TPsoft\DBmodel\Maintenance($db); $maintenance = new \TPsoft\DBmodel\Maintenance($db);
// Check if existing table, if not create it by definition
$suc = $maintenance->checkDBTable('users', ' $suc = $maintenance->checkDBTable('users', '
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL, `name` varchar(255) DEFAULT NULL,
@ -16,31 +15,24 @@ $suc = $maintenance->checkDBTable('users', '
'); ');
echo "\nCheckDBTable: "; var_dump($suc); echo "\nCheckDBTable: "; var_dump($suc);
// Check if existing column, if not add it by definition
$suc = $maintenance->checkDBAdd('users', 'password', 'varchar(255) DEFAULT NULL'); $suc = $maintenance->checkDBAdd('users', 'password', 'varchar(255) DEFAULT NULL');
echo "\nCheckDBAdd: "; var_dump($suc); echo "\nCheckDBAdd: "; var_dump($suc);
// Check if existing column
$suc = $maintenance->existsColumn('users', 'email'); $suc = $maintenance->existsColumn('users', 'email');
echo "\nExistsColumn: "; var_dump($suc); echo "\nExistsColumn: "; var_dump($suc);
// Check if existing column in new name, if not rename it
$suc = $maintenance->checkDBRename('users', 'email', 'email_new', 'varchar(255) DEFAULT NULL'); $suc = $maintenance->checkDBRename('users', 'email', 'email_new', 'varchar(255) DEFAULT NULL');
echo "\nCheckDBRename: "; var_dump($suc); echo "\nCheckDBRename: "; var_dump($suc);
// Chceck type of column, if not matched change it
$suc = $maintenance->checkDBRetype('users', 'email_new', 'varchar(128)', 'varchar(128) DEFAULT NULL AFTER `password`'); $suc = $maintenance->checkDBRetype('users', 'email_new', 'varchar(128)', 'varchar(128) DEFAULT NULL AFTER `password`');
echo "\nCheckDBRetype: "; var_dump($suc); echo "\nCheckDBRetype: "; var_dump($suc);
// Remove column from table
$suc = $maintenance->checkDBRemove('users', 'email_new'); $suc = $maintenance->checkDBRemove('users', 'email_new');
echo "\nCheckDBRemove: "; var_dump($suc); echo "\nCheckDBRemove: "; var_dump($suc);
// Add index for column
$suc = $maintenance->addKey('users', 'name'); $suc = $maintenance->addKey('users', 'name');
echo "\nAddKey: "; var_dump($suc); echo "\nAddKey: "; var_dump($suc);
// Drop index by column name
$suc = $maintenance->dropKey('users', 'name'); $suc = $maintenance->dropKey('users', 'name');
echo "\nDropKey: "; var_dump($suc); echo "\nDropKey: "; var_dump($suc);