rework to change from MySQLi to PDO.

This commit is contained in:
kj 2022-07-14 21:41:48 -04:00
parent afb4c914a1
commit 0db6e4a021
4 changed files with 277 additions and 195 deletions

View File

@ -1,4 +1,4 @@
# DuckBrain - PHP Microframework
* DuckBrain - PHP Microframework
Este microframework PHP tiene el objetivo de presentar un framework sencillo y potente que sea válido especialmente para proyectos pequeños o simples, sin limitar demasiado, ni depender de cosas que agranden innecesariamente proyectos.
@ -12,10 +12,10 @@ Lo ideal sería mantener el código sencillo, lo suficiente como para que cualqu
El código no es perfecto, pero lo iré perfeccionando, ya que es algo que estoy usando actualmente para mis trabajos, de modo que puedo ir viendo que cosas se pueden ir mejorando.
## Uso / Documentación
* Uso / Documentación
Queda pendiente, si quieres usarlo ya mismo, puedes leer los comeentarios que he colocado en el código.
## Contacto
* Contacto
Puedes encontrame en telegram como [@keyjay](https://telegram.me/keyjay) o contactarme mi correo: webmaster@outcontrol.net
Puedes encontrame en telegram como [[https://telegram.me/keyjay][@keyjay]] o contactarme mi correo: webmaster@outcontrol.net

93
rework.org Normal file
View File

@ -0,0 +1,93 @@
* Sobre la actualización
Previamente, el sistema usaba [[https://www.php.net/mysqli][MySQLi]] para el Modelo/ORM, como actualización, se ha cambiado para funcionar con [[https://www.php.net/pdo][PDO]].
* Migración
Estos son detalles importantes a tomar en cuenta a la hora de migrar del anterior ModelMySQL (MySQLi) al actual Model (PDO).
+ El modelo base ha cambiado de nombre de =ModelMySQL= a =Model=.
+ Se han depurado los métodos =sql_calc_found_rows= y =found_rows=.
+ Se ha añadido la necesitad de la constante =DB_TYPE= para indicar el driver PDO a usar (ej. mysql, sqlite).
* Pruebas
En la siguiente tabla se encuentra la lista de estados de los SGBD que he probado (MySQL/MariaDB) o que planeo probar (sqlite3, postgreSQL) para asegurarme de que sean realmente compatibles.
*Entiéndase*:
+ *ok* como que ha sido probado y funciona.
+ En blanco como que no ha sido probado aún.
+ *error* como que fue probado, no funciona y no ha sido aún arreglado.
+ *not supported* como no soportado por el SGBD.
+ *fixed* para aquello que no existe, pero la librería lo traduce a un equivalente.
|------------------+---------------+---------+------------|
| method | MySQL/MariaDB | sqlite3 | postgreSQL |
|------------------+---------------+---------+------------|
| db | ok | | |
|------------------+---------------+---------+------------|
| query | ok | | |
|------------------+---------------+---------+------------|
| resetQuery | ok | | |
|------------------+---------------+---------+------------|
| buildQuery | ok | | |
|------------------+---------------+---------+------------|
| getInstance | ok | | |
|------------------+---------------+---------+------------|
| getVars | ok | | |
|------------------+---------------+---------+------------|
| className | ok | | |
|------------------+---------------+---------+------------|
| table | ok | | |
|------------------+---------------+---------+------------|
| update | ok | | |
|------------------+---------------+---------+------------|
| beginTransaction | ok | | |
|------------------+---------------+---------+------------|
| rollBack | ok | | |
|------------------+---------------+---------+------------|
| commit | ok | | |
|------------------+---------------+---------+------------|
| add | ok | | |
|------------------+---------------+---------+------------|
| save | ok | | |
|------------------+---------------+---------+------------|
| delete | ok | | |
|------------------+---------------+---------+------------|
| select | ok | | |
|------------------+---------------+---------+------------|
| from | ok | | |
|------------------+---------------+---------+------------|
| where | ok | | |
|------------------+---------------+---------+------------|
| where_in | ok | | |
|------------------+---------------+---------+------------|
| leftJoin | ok | | |
|------------------+---------------+---------+------------|
| rightJoin | ok | | |
|------------------+---------------+---------+------------|
| innerJoin | ok | | |
|------------------+---------------+---------+------------|
| and | ok | | |
|------------------+---------------+---------+------------|
| or | ok | | |
|------------------+---------------+---------+------------|
| groupBy | ok | | |
|------------------+---------------+---------+------------|
| limit | ok | | |
|------------------+---------------+---------+------------|
| orderBy | ok | | |
|------------------+---------------+---------+------------|
| count | ok | | |
|------------------+---------------+---------+------------|
| getById | ok | | |
|------------------+---------------+---------+------------|
| search | ok | | |
|------------------+---------------+---------+------------|
| get | ok | | |
|------------------+---------------+---------+------------|
| getFirst | ok | | |
|------------------+---------------+---------+------------|
| all | ok | | |
|------------------+---------------+---------+------------|
| setNull | ok | | |
|------------------+---------------+---------+------------|

View File

@ -2,9 +2,9 @@
/**
* Database - DuckBrain
*
* Clase diseñada para crear y devolver una única instancia mysqli (database).
* Clase diseñada para crear y devolver una única instancia PDO (database).
* Depende de manera forzada de que estén definidas las constantes:
* dbhost, dbname, dbpass y dbuser
* DB_TYPE, DB_NAME, DB_HOST, DB_USER. DB_PASS
*
* @author KJ
* @website https://kj2.me
@ -12,25 +12,33 @@
*/
namespace Libs;
use mysqli;
class Database extends \mysqli {
static private $db;
use PDO;
use PDOException;
use Exception;
class Database extends PDO {
static private ?PDO $db = null;
private function __construct() {}
/**
* Devuelve una instancia homogénea (singlenton) a la base de datos.
* Devuelve una instancia homogénea (singlenton) de la base de datos (PDO).
*
* @return mysqli
* @return PDO
*/
static public function getConnection() : mysqli {
if (!isset(self::$db)) {
self::$db = new mysqli(dbhost, dbuser, dbpass, dbname);
if (self::$db->connect_errno) {
echo '<style>body{white-space: pre-line;}</style>';
throw new \Exception('No se ha podido conectar a la base de datos.');
static public function getInstance() : PDO {
if (is_null(self::$db)) {
$dsn = DB_TYPE.':dbname='.DB_NAME.';host='.DB_HOST;
try {
self::$db = new PDO($dsn, DB_USER, DB_PASS);
} catch (PDOException $e) {
echo "<pre>";
throw new Exception(
'Error at connect to database: ' . $e->getMessage()
);
}
self::$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
return self::$db;
}

View File

@ -1,9 +1,9 @@
<?php
/**
* ModelMysql - DuckBrain
* Model - DuckBrain
*
* Modelo ORM para objetos que hagan uso de una base de datos MySQL.
* Depende de que exista Libs\Database para poder funcionar.
* Modelo ORM para objetos que hagan uso de una base de datos.
* Depende de Libs\Database.
*
* @author KJ
* @website https://kj2.me
@ -13,9 +13,11 @@
namespace Libs;
use Libs\Database;
use mysqli;
use PDO;
use PDOException;
use Exception;
class ModelMySQL {
class Model {
public ?int $id = null;
protected array $toNull = [];
@ -24,7 +26,8 @@ class ModelMySQL {
static protected array $forceSave = [];
static protected string $table;
static protected string $tableSufix = 's';
static protected ?mysqli $db = null;
static protected ?PDO $db = null;
static protected array $queryVars = [];
static protected array $querySelect = [
'select' => ['*'],
'where' => '',
@ -35,48 +38,93 @@ class ModelMySQL {
'AndOr' => '',
'orderBy' => '',
'groupBy' => '',
'limit' => '',
'sql_calc_found_rows' => false
'limit' => ''
];
/**
* Sirve para obtener la instancia de la base de datos.
*
* @return mysqli
* @return Database
*/
protected static function db() : mysqli {
protected static function db() : PDO {
if (is_null(static::$db))
static::$db = Database::getConnection();
static::$db = Database::getInstance();
return static::$db;
}
/**
* Ejecuta PDO::beginTransaction para iniciar una transacción.
* Más info: https://www.php.net/manual/es/pdo.begintransaction.php
*
* @return bool
*/
public function beginTransaction() : bool {
return static::db()->beginTransaction();
}
/**
* Ejecuta PDO::rollBack para deshacher los cambios de una transacción.
* Más info: https://www.php.net/manual/es/pdo.rollback.php
*
* @return bool
*/
public function rollBack() : bool {
return static::db()->rollBack();
}
/**
* Ejecuta PDO::commit para consignar una transacción.
* Más info: https://www.php.net/manual/es/pdo.commit.php
*
* @return bool
*/
public function commit() : bool {
return static::db()->commit();
}
/**
* Ejecuta una sentencia SQL en la base de datos.
*
* @param string $query
* Contiene la sentencia SQL que se desea ejecutar.
*
* @throws \Exception
* En caso de que la sentencia SQL falle, devolverá un error en pantalla.
* @throws Exception
* En caso de que la sentencia SQL falle, devolverá un error en pantalla
* y hará rolllback en caso de estar dentro de una transacción.
*
* @return mixed
* Contiene el resultado de la llamada SQL (mysqli_result o bool).
* @param bool $resetQuery
* Indica si el query debe reiniciarse o no (por defecto es true).
*
* @return array
* Contiene el resultado de la llamada SQL .
*/
protected static function query($query) {
protected static function query(string $query, bool $resetQuery = true) : array {
$db = static::db();
$result = $db->query($query);
if ($db->errno) {
echo '<style>body{white-space: pre-line;}</style>';
throw new \Exception(
"\nFallo al consultar la base de datos\n" .
"Errno: $db->errno\n" .
"Error: $db->error\n" .
"Query: $query\n"
try {
$prepared = $db->prepare($query);
$prepared->execute(static::$queryVars);
} catch (PDOException $e) {
if ($db->inTransaction())
$db->rollBack();
$vars = json_encode(static::$queryVars);
echo "<pre>";
throw new Exception(
"\nError at query to database.\n" .
"Query: $query\n" .
"Vars: $vars\n" .
"Error:\n" . $e->getMessage()
);
}
$result = $prepared->fetchAll();
if ($resetQuery)
static::resetQuery();
return $result;
}
@ -94,9 +142,9 @@ class ModelMySQL {
'AndOr' => '',
'orderBy' => '',
'groupBy' => '',
'limit' => '',
'sql_calc_found_rows' => false
'limit' => ''
];
static::$queryVars = [];
}
/**
@ -110,10 +158,7 @@ class ModelMySQL {
* Contiene la sentencia SQL.
*/
protected static function buildQuery(bool $resetQuery = true) : string {
if (static::$querySelect['sql_calc_found_rows'])
$sql = 'SELECT SQL_CALC_FOUND_ROWS '.join(', ', static::$querySelect['select']);
else
$sql = 'SELECT '.join(', ', static::$querySelect['select']);
$sql = 'SELECT '.join(', ', static::$querySelect['select']);
if (static::$querySelect['from'] != '') {
$sql .= ' FROM '.static::$querySelect['from'];
@ -153,9 +198,6 @@ class ModelMySQL {
$sql .= ' LIMIT '.static::$querySelect['limit'];
}
if ($resetQuery)
static::resetQuery();
return $sql;
}
@ -166,10 +208,10 @@ class ModelMySQL {
* Puede recibir un arreglo o un objeto que contiene los valores
* que tendrán sus atributos.
*
* @return ModelMySQL
* @return Model
* Retorna un objeto de la clase actual.
*/
protected static function getInstance(array $elem = []) : ModelMySQL {
protected static function getInstance(array $elem = []) : Model {
$class = get_called_class();
$instance = new $class;
@ -243,11 +285,12 @@ class ModelMySQL {
foreach ($atts as $key => $value) {
if (isset($value)) {
$value = static::db()->real_escape_string($value);
if (in_array($key, $this->toNull))
$set[]="$key=NULL";
else
$set[]="$key='$value'";
else {
$set[]="$key=:$key";
static::$queryVars[':'.$key] = $value;
}
} else {
if (in_array($key, $this->toNull))
$set[]="$key=NULL";
@ -272,7 +315,8 @@ class ModelMySQL {
foreach ($atts as $key => $value) {
if (isset($value)) {
$into[] = "`$key`";
$values[] = "'".$db->real_escape_string($value)."'";
$values[] = ":$key";
static::$queryVars[":$key"] = $value;
}
}
@ -281,7 +325,7 @@ class ModelMySQL {
static::query($sql);
$pk = static::$primaryKey;
$this->$pk = $db->insert_id;
$this->$pk = $db->lastInsertId();
}
/**
@ -300,17 +344,11 @@ class ModelMySQL {
* Elimina el objeto actual de la base de datos.
*/
public function delete() {
$atts = $this->getVars();
foreach ($atts as $key => $value) {
$value = static::db()->real_escape_string($value);
$set[]="$key='$value'";
}
$table = static::table();
$pk = static::$primaryKey;
$pkv = $this->$pk;
$sql = "DELETE FROM $table WHERE $pk='$pkv'";
$sql = "DELETE FROM $table WHERE $pk=:$pk";
static::$queryVars[":$pk"] = $this->$pk;
static::query($sql);
}
@ -320,16 +358,10 @@ class ModelMySQL {
* @param array $columns
* Columnas que se selecionarán en la consulta SQL.
*
* @return ModelMySQL
* @return Model
*/
public static function select(array $columns) : ModelMySQL {
$db = static::db();
$select = [];
foreach($columns as $column) {
$select[] = $db->real_escape_string($column);
}
static::$querySelect['select'] = $select;
public static function select(array $columns) : Model {
static::$querySelect['select'] = $columns;
return new static();
}
@ -340,16 +372,10 @@ class ModelMySQL {
* @param array $tables
* Tablas que se selecionarán en la consulta SQL.
*
* @return ModelMySQL
* @return Model
*/
public static function from(array $tables) : ModelMySQL {
$db = static::db();
$from = [];
foreach($tables as $table) {
$from[] = $db->real_escape_string($table);
}
static::$querySelect['from'] = join(', ', $from);
public static function from(array $tables) : Model {
static::$querySelect['from'] = join(', ', $tables);
return new static();
}
@ -366,23 +392,23 @@ class ModelMySQL {
* @param string $value
* (opcional) El valor el valor a comparar en la columna.
*
* @param bool $no_quote
* (opcional) Se usa cuando $value es una columna o un valor que no requiere comillas.
* @param bool $no_filter
* (opcional) Se usa cuando $value es una columna o un valor que no requiere filtros contra ataques SQLI.
*
* @return ModelMySQL
* @return Model
*/
public static function where(string $column, string $operatorOrValue, string $value=null, bool $no_quote = false) : ModelMySQL {
public static function where(string $column, string $operatorOrValue, string $value=null, bool $no_filter = false) : Model {
if (is_null($value)) {
$value = $operatorOrValue;
$operatorOrValue = '=';
}
$value = static::db()->real_escape_string($value);
if ($no_quote)
static::$querySelect['where'] = "$column$operatorOrValue$value";
else
static::$querySelect['where'] = "$column$operatorOrValue'$value'";
if ($no_filter) {
static::$querySelect['where'] = "$column$operatorOrValue$value";
} else {
static::$queryVars[":where_$column"] = $value;
static::$querySelect['where'] = "$column$operatorOrValue:where_$column";
}
return new static();
}
@ -399,17 +425,19 @@ class ModelMySQL {
* @param bool $in
* Define si se tienen que comprobar negativa o positivamente.
*
* @return ModelMySQL
* @return Model
*/
public static function where_in(string $column, array $arr, bool $in = true) : ModelMySQL {
public static function where_in(string $column, array $arr, bool $in = true) : Model {
$arrIn = [];
foreach($arr as $index => $value) {
$arr[$index] = static::db()->real_escape_string($value);
$arrIn[] = ":on_$index";
static::$queryVars[":on_$index"] = $value;
}
if ($in)
static::$querySelect['where'] = "$column IN ('".join('\', \'',$arr)."')";
static::$querySelect['where'] = "$column IN (".join(', ', $arrIn).")";
else
static::$querySelect['where'] = "$column NOT IN ('".join('\', \'',$arr)."')";
static::$querySelect['where'] = "$column NOT IN (".join(', ', $arrIn).")";
return new static();
}
@ -429,20 +457,16 @@ class ModelMySQL {
* @param string $columnB
* (opcional) Columna a comparar para hacer el join.
*
* @return ModelMySQL
* @return Model
*/
public static function leftJoin(string $table, string $columnA, string $operatorOrColumnB, string $columnB = null) : ModelMySQL {
public static function leftJoin(string $table, string $columnA, string $operatorOrColumnB, string $columnB = null) : Model {
if (is_null($columnB)) {
$columnB = $operatorOrColumnB;
$operatorOrColumnB = '=';
}
$columnA = static::db()->real_escape_string($columnA);
$columnB = static::db()->real_escape_string($columnB);
static::$querySelect['leftJoin'] .= ' LEFT JOIN ' . $table . ' ON ' . "$columnA$operatorOrColumnB$columnB";
return new static();
}
@ -461,17 +485,14 @@ class ModelMySQL {
* @param string $columnB
* (opcional) Columna a comparar para hacer el join.
*
* @return ModelMySQL
* @return Model
*/
public static function rightJoin(string $table, string $columnA, string $operatorOrColumnB, string $columnB = null) : ModelMySQL {
public static function rightJoin(string $table, string $columnA, string $operatorOrColumnB, string $columnB = null) : Model {
if (is_null($columnB)) {
$columnB = $operatorOrColumnB;
$operatorOrColumnB = '=';
}
$columnA = static::db()->real_escape_string($columnA);
$columnB = static::db()->real_escape_string($columnB);
static::$querySelect['rightJoin'] .= ' RIGHT JOIN ' . $table . ' ON ' . "$columnA$operatorOrColumnB$columnB";
return new static();
@ -492,17 +513,14 @@ class ModelMySQL {
* @param string $columnB
* (opcional) Columna a comparar para hacer el join.
*
* @return ModelMySQL
* @return Model
*/
public static function innerJoin(string $table, string $columnA, string $operatorOrColumnB, string $columnB = null) : ModelMySQL {
public static function innerJoin(string $table, string $columnA, string $operatorOrColumnB, string $columnB = null) : Model {
if (is_null($columnB)) {
$columnB = $operatorOrColumnB;
$operatorOrColumnB = '=';
}
$columnA = static::db()->real_escape_string($columnA);
$columnB = static::db()->real_escape_string($columnB);
static::$querySelect['innerJoin'] .= ' INNER JOIN ' . $table . ' ON ' . "$columnA$operatorOrColumnB$columnB";
return new static();
@ -520,23 +538,23 @@ class ModelMySQL {
* @param string $value
* (opcional) El valor el valor a comparar en la columna.
*
* @param bool $no_quote
* (opcional) Se usa cuando $value es una columna o un valor que no requiere comillas.
* @param bool $no_filter
* (opcional) Se usa cuando $value es una columna o un valor que no requiere filtros contra ataques SQLI.
*
* @return ModelMySQL
* @return Model
*/
public static function and(string $column, string $operatorOrValue, string $value=null, bool $no_quote = false) : ModelMySQL {
public static function and(string $column, string $operatorOrValue, string $value=null, bool $no_filter = false) : Model {
if (is_null($value)) {
$value = $operatorOrValue;
$operatorOrValue = '=';
}
$value = static::db()->real_escape_string($value);
if ($no_quote)
if ($no_filter)
static::$querySelect['AndOr'] .= " AND $column$operatorOrValue$value";
else
static::$querySelect['AndOr'] .= " AND $column$operatorOrValue'$value'";
else {
static::$queryVars[":and_$column"] = $value;
static::$querySelect['AndOr'] .= " AND $column$operatorOrValue:and_$column";
}
return new static();
}
@ -553,23 +571,23 @@ class ModelMySQL {
* @param string $value
* (opcional) El valor el valor a comparar en la columna.
*
* @param bool $no_quote
* (opcional) Se usa cuando $value es una columna o un valor que no requiere comillas.
* @param bool $no_filter
* (opcional) Se usa cuando $value es una columna o un valor que no requiere filtros contra ataques SQLI.
*
* @return ModelMySQL
* @return Model
*/
public static function or(string $column, string $operatorOrValue, string $value=null, bool $no_quote = false) : ModelMySQL {
public static function or(string $column, string $operatorOrValue, string $value=null, bool $no_filter = false) : Model {
if (is_null($value)) {
$value = $operatorOrValue;
$operatorOrValue = '=';
}
$value = static::db()->real_escape_string($value);
if ($no_quote)
if ($no_filter)
static::$querySelect['AndOr'] .= " OR $column$operatorOrValue$value";
else
static::$querySelect['AndOr'] .= " OR $column$operatorOrValue'$value'";
else {
static::$queryVars[":or_$column"] = $value;
static::$querySelect['AndOr'] .= " OR $column$operatorOrValue:or_$column";
}
return new static();
}
@ -580,9 +598,9 @@ class ModelMySQL {
* @param array $arr
* Columnas por las que se agrupará.
*
* @return ModelMySQL
* @return Model
*/
public static function groupBy(array $arr) : ModelMySQL {
public static function groupBy(array $arr) : Model {
static::$querySelect['groupBy'] = join(', ', $arr);
return new static();
}
@ -593,9 +611,9 @@ class ModelMySQL {
* @param int $initial
* @param int $final
*
* @return ModelMySQL
* @return Model
*/
public static function limit(int $initial, int $final = 0) : ModelMySQL {
public static function limit(int $initial, int $final = 0) : Model {
if ($final==0)
static::$querySelect['limit'] = $initial;
else
@ -614,16 +632,14 @@ class ModelMySQL {
* (opcional) Define si el orden será de manera ascendente (ASC),
* descendente (DESC) o aleatorio (RAND).
*
* @return ModelMySQL
* @return Model
*/
public static function orderBy(string $value, string $order = 'ASC') : ModelMySQL {
public static function orderBy(string $value, string $order = 'ASC') : Model {
if ($value == "RAND") {
static::$querySelect['orderBy'] = 'RAND()';
return new static();
}
$value = static::db()->real_escape_string($value);
if (!(strtoupper($order) == 'ASC' || strtoupper($order) == 'DESC'))
$order = 'ASC';
@ -647,60 +663,36 @@ class ModelMySQL {
if (!$resetQuery)
$backup = [
'select' => static::$querySelect['select'],
'sql_calc_found_rows' => static::$querySelect['sql_calc_found_rows'],
'limit' => static::$querySelect['limit'],
'orderBy' => static::$querySelect['orderBy']
];
if ($useLimit && static::$querySelect['limit'] != '') {
static::$querySelect['select'] = ['1'];
static::$querySelect['sql_calc_found_rows'] = false;
static::$querySelect['orderBy'] = '';
static::$querySelect['select'] = ['1'];
static::$querySelect['orderBy'] = '';
$sql = 'SELECT COUNT(1) AS quantity FROM ('.static::buildQuery($resetQuery).') AS counted';
$queryResult = static::query($sql)->fetch_assoc();
$result = $queryResult['quantity'];
$queryResult = static::query($sql);
$result = $queryResult[0]['quantity'];
} else {
static::$querySelect['select'] = ['1'];
static::$querySelect['sql_calc_found_rows'] = true;
static::$querySelect['limit'] = '1';
static::$querySelect['orderBy'] = '';
static::$querySelect['select'] = ["COUNT(".static::$primaryKey.") as quantity"];
static::$querySelect['limit'] = '1';
static::$querySelect['orderBy'] = '';
$sql = static::buildQuery($resetQuery);
static::query($sql);
$result = static::found_row();
$queryResult = static::query($sql);
$result = $queryResult[0]['quantity'];
}
if (!$resetQuery) {
static::$querySelect['select'] = $backup['select'];
static::$querySelect['sql_calc_found_rows'] = $backup['sql_calc_found_rows'];
static::$querySelect['limit'] = $backup['limit'];
static::$querySelect['orderBy'] = $backup['orderBy'];
static::$querySelect['select'] = $backup['select'];
static::$querySelect['limit'] = $backup['limit'];
static::$querySelect['orderBy'] = $backup['orderBy'];
}
return $result;
}
/**
* Retorna las filas contadas en el último query.
*
* @return int
*/
public static function found_row() : int {
$result = static::query('SELECT FOUND_ROWS() AS quantity')->fetch_assoc();
return $result['quantity'];
}
/**
* Habilita el conteo de todos las coincidencias posibles incluso usando limit.
*
* @return ModelMySQL
*/
public static function sql_calc_found_rows() : ModelMySQL {
static::$querySelect['sql_calc_found_rows'] = true;
return new static();
}
/**
* Obtiene una instancia según su primary key (generalmente id).
* Si no encuentra una instancia, devuelve nulo.
@ -721,9 +713,9 @@ class ModelMySQL {
* @param array $in
* (opcional) Columnas en las que se va a buscar (null para buscar en todas).
*
* @return ModelMySQL
* @return Model
*/
public static function search(string $search, array $in = null) : ModelMySQL {
public static function search(string $search, array $in = null) : Model {
if ($in == null) {
$className = get_called_class();
$in = array_keys((new $className())->getVars());
@ -731,12 +723,11 @@ class ModelMySQL {
$db = static::db();
$search = $db->real_escape_string($search);
static::$queryVars[':search'] = $search;
$where = [];
foreach($in as $row) {
$where[] = "$row LIKE '%$search%'";
$where[] = "$row LIKE CONCAT('%', :search, '%')";
}
if (static::$querySelect['where']=='')
@ -762,7 +753,7 @@ class ModelMySQL {
$instances = [];
while ($row = $result->fetch_assoc()) {
foreach ($result as $row) {
$instances[] = static::getInstance($row);
}
@ -776,7 +767,7 @@ class ModelMySQL {
* (opcional) Indica si el query debe reiniciarse o no (por defecto es true).
*
* @return mixed
* Puede retornar un objeto ModelMySQL o null.
* Puede retornar un objeto Model o null.
*/
public static function getFirst(bool $resetQuery = true) { // Devuelve null si no encuentra nada.
static::limit(1);
@ -792,14 +783,12 @@ class ModelMySQL {
*/
public static function all() : array {
$sql = 'SELECT * FROM '.static::table();
$result = static::query($sql);
$instances = [];
while ($row = $result->fetch_assoc()) {
foreach ($result as $row)
$instances[] = static::getInstance($row);
}
return $instances;
}
@ -808,17 +797,9 @@ class ModelMySQL {
* Permite definir como nulo el valor de un atributo.
* Sólo funciona para actualizar un elemento de la BD, no para insertar.
*
* @trows \Exception
* Devolverá un error en caso de usarse en un insert.
*
* @param array $atts
*/
public function setNull(array $atts) {
if (!isset($this->id))
throw new \Exception(
"\nEl método setNull sólo funciona para actualizar, no al insertar."
);
foreach ($atts as $att) {
if (!in_array($att, $this->toNull))
$this->toNull[] = $att;