'*', 'where' => '', 'leftJoin' => '', 'rightJoin' => '', 'on' => '', 'AndOr' => '', 'orderBy'=>'', 'groupBy'=>'', 'limit' => '', ]; /* * Sirve para obtener la instancia de la base de datos * * @return mysqli */ private static function db(){ if (is_null(self::$db)) self::$db = Database::getConnection(); return self::$db; } /* * 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. * * @return mysqli_result * Contiene el resultado de la llamada SQL. */ private static function query($query){ $db = self::db(); $result = $db->query($query); if ($db->errno){ echo ''; throw new \Exception( "\nFallo al consultar la base de datos\n" . "Errno: $db->errno\n" . "Error: $db->error\n" . "Query: $query\n" ); } return $result; } /* * Reinicia la configuración de la sentencia SQL. */ private static function resetQuery(){ self::$querySelect = [ 'select' => '*', 'where' => '', 'leftJoin' => '', 'rightJoin' => '', 'on' => '', 'AndOr' => '', 'orderBy'=>'', 'groupBy'=>'', 'limit' => '', ]; } /* * Construye la sentencia SQL a partir self::$querySelect y una vez * construída, llama a resetQuery. * * @return string * Contiene la sentencia SQL. */ private static function buildQuery(){ $sql = 'SELECT '.self::$querySelect['select'].' FROM '.self::table(); if (self::$querySelect['leftJoin'] != ''){ $sql .= ' LEFT JOIN ' . self::$querySelect['leftJoin']; $sql .= ' ON '. self::$querySelect['on']; } elseif(self::$querySelect['rightJoin'] != ''){ $sql .= ' RIGHT JOIN ' . self::$querySelect['leftJoin']; $sql .= ' ON '. self::$querySelect['on']; } if (self::$querySelect['where'] != ''){ $sql .= ' WHERE '.self::$querySelect['where']; if (self::$querySelect['AndOr'] != ''){ $sql .= self::$querySelect['AndOr']; } } if (self::$querySelect['groupBy'] != ''){ $sql .= ' GROUP BY '.self::$querySelect['groupBy']; } if (self::$querySelect['orderBy'] != ''){ $sql .= ' ORDER BY '.self::$querySelect['orderBy']; } if (self::$querySelect['limit'] != ''){ $sql .= ' LIMIT '.self::$querySelect['limit']; } self::resetQuery(); return $sql; } /* * Crea una instancia del objeto actual a partir de un arreglo. * * @param mixed $elem * Puede recibir un arreglo o un objeto que contiene los valores * que tendrán sus atributos. * * @return ModelMySQL * Retorna un objeto de la clase actual. */ public function getInstance($elem = []){ $class = get_called_class(); $instace = new $class; foreach ($elem as $key => $value){ $instace->$key = $value; } return $instace; } /* * @return array * Contiene los atributos indexados del objeto actual. */ private function getVars(){ // Source: https://stackoverflow.com/questions/10009015/show-all-public-attributes-name-and-value-of-an-object $get_vars_proxy = create_function('$obj', 'return get_object_vars($obj);'); $result = $get_vars_proxy($this); foreach ($this->ignoreSave as $del){ unset($result[$del]); } foreach ($this->forceSave as $value){ $result[$value] = $this->$value; } return $result; } /* * @return string * Devuelve el nombre de la clase actual */ public static function className(){ return strtolower(substr(strrchr(get_called_class(), '\\'), 1)); } /* * Construye (a partir del nombre de la clase y el sufijo en self::$tableSufix) * y/o develve el nombre de la tabla de la BD en la que se alojará o * se aloja el objeto actual. * * @return string */ private static function table(){ if (isset(self::$table)) return self::$table; return self::className().self::$tableSufix; } /* * Actualiza los valores en la BD con los valores del objeto actual */ private function update(){ $atts = $this->getVars(); foreach ($atts as $key => $value){ $value = self::db()->real_escape_string($value); $set[]="$key='$value'"; } $table = self::table(); $pk = $this->primaryKey; $pkv = $this->$pk; $sql = "UPDATE $table SET ".join(', ', $set)." WHERE $pk='$pkv'"; self::query($sql); } /* * Inserta una nueva fila en la base de datos a partir del * objeto actual. */ private function add(){ $db = self::db(); $atts = $this->getVars(); foreach ($atts as $key => $value){ $into[] = "`$key`"; $values[] = "'".$db->real_escape_string($value)."'"; } $table = self::table(); $sql = "INSERT INTO $table (".join(', ', $into).") VALUES (".join(', ', $values).")"; self::query($sql); $pk = $this->primaryKey; $this->$pk = $db->insert_id; } /* * Revisa si el objeto a guardar es nuevo o no y según el resultado * llama a update para actualizar o add para insertar una nueva fila. */ public function save(){ $pk = $this->primaryKey; if (isset($this->$pk)) $this->update(); else $this->add(); } /* * Elimina el objeto actual de la base de datos. */ public function delete(){ $atts = $this->getVars(); foreach ($atts as $key => $value){ $value = self::db()->real_escape_string($value); $set[]="$key='$value'"; } $table = self::table(); $pk = $this->primaryKey; $pkv = $this->$pk; $sql = "DELETE FROM $table WHERE $pk='$pkv'"; self::query($sql); } /* * Define SELECT en la sentencia SQL. * * @param array $columns * Columnas que se selecionarán en la consulta SQL. */ public static function select($columns){ $db = self::db(); $select = []; foreach($columns as $column){ $select[] = $db->real_escape_string($column); } self::$querySelect['select'] = join(', ', $select); return new static(); } /* * Define el WHERE en la sentencia SQL. * * @param string $column * La columna a comparar. * * @param string $operador * El operador o el valor a comparar en la columna en caso de que eloperador sea "=". * * @param string $value * El valor el valor a comparar en la columna. * * Sintaxis posibles: * - self::where(columna, operador, valor) * - self::where(columna, valor) // Operador por defecto "=" */ public static function where($column, $operator, $value=null){ if (is_null($value)){ $value = $operator; $operator = '='; } $value = self::db()->real_escape_string($value); self::$querySelect['where'] = "$column$operator'$value'"; return new static(); } /* * Define WHERE usando IN en la sentencia SQL. * * @param string $column * La columna a comparar. * * @param array $arr * Arreglo con todos los valores a comparar con la columna. * * @param boolean $in * Define si se usará IN o NOT IN en la sentencia SQL. */ public static function where_in($column,$arr, $in = true){ foreach($arr as $index => $value){ $arr[$index] = self::db()->real_escape_string($value); } if ($in) self::$querySelect['where'] = "$column IN (".join(', ',$arr).")"; else self::$querySelect['where'] = "$column NOT IN (".join(', ',$arr).")"; return new static(); } /* * Define LEFT JOIN en la sentencia SQL. * * @param string $table * Tabla que se va a juntar a la del objeto actual. * * @param string $columnA * Columna a comparar para hacer el join. * * @param string $operador * Operador o columna a comparar para hacer el join en caso de que el operador sea "=". * * @param string $columnB * Columna a comparar para hacer el join. * * Sintaxis posibles: * - self::leftJoin(tabla,columnaA, operador, columnB) * - self::leftJoin(tabla,columnaA, columnB) // Operador por defecto "=" */ public static function leftJoin($table, $columnA, $operator, $columnB = null){ if (is_null($columnB)){ $columnB = $operator; $operator = '='; } $columnA = self::db()->real_escape_string($columnA); $columnB = self::db()->real_escape_string($columnB); self::$querySelect['leftJoin'] = $table; self::$querySelect['on'] = "$columnA$operator$columnB"; return new static(); } /* * Define RIGHT JOIN en la sentencia SQL. * * @param string $table * Tabla que se va a juntar a la del objeto actual. * * @param string $columnA * Columna a comparar para hacer el join. * * @param string $operador * Operador o columna a comparar para hacer el join en caso de que el operador sea "=". * * @param string $columnB * Columna a comparar para hacer el join. * * Sintaxis posibles: * - self::rightJoin(tabla,columnaA, operador, columnB) * - self::rightJoin(tabla,columnaA, columnB) // Operador por defecto "=" */ public static function rightJoin($table, $columnA, $operator, $columnB = null){ if (is_null($columnB)){ $columnB = $operator; $operator = '='; } $columnA = self::db()->real_escape_string($columnA); $columnB = self::db()->real_escape_string($columnB); self::$querySelect['rightJoin'] = $table; self::$querySelect['on'] = "$columnA$operator$columnB"; return new static(); } /* * Define AND en la sentencia SQL (se puede anidar). * * @param string $column * La columna a comparar. * * @param string $operador * El operador o el valor a comparar en la columna en caso de que eloperador sea "=". * * @param string $value * El valor el valor a comparar en la columna. * * Sintaxis posibles: * - self::and(columna, operador, valor) * - self::and(columna, valor) // Operador por defecto "=" * - self::and(columna, valor)->and(columna, valor)->and(columna, valor) // anidado */ public static function and($column, $operator, $value=null){ if (is_null($value)){ $value = $operator; $operator = '='; } $value = self::db()->real_escape_string($value); self::$querySelect['AndOr'] .= " AND $column$operator'$value'"; return new static(); } /* * Define OR en la sentencia SQL (se puede anidar). * * @param string $column * La columna a comparar. * * @param string $operador * El operador o el valor a comparar en la columna en caso de que eloperador sea "=". * * @param string $value * El valor el valor a comparar en la columna. * * Sintaxis posibles: * - self::or(columna, operador, valor) * - self::or(columna, valor) // Operador por defecto "=" * - self::or(columna, valor)->or(columna, valor)->or(columna, valor) // anidado */ public static function or($column, $operator, $value=null){ if (is_null($value)){ $value = $operator; $operator = '='; } $value = self::db()->real_escape_string($value); self::$querySelect['AndOr'] .= " OR $column$operator'$value'"; return new static(); } /* * Define GROUP BY en la sentencia SQL * * @param array $arr * Columnas por las que se agrupará. */ public static function groupBy($arr){ self::$querySelect['groupBy'] = join(', ', $arr); return new static(); } public static function limit($initial, $final = 0){ $initial = (int)$initial; $final = (int)$final; if ($final==0) self::$querySelect['limit'] = $initial; else self::$querySelect['limit'] = $initial.', '.$final; return new static(); } /* * Define ORDER BY en la sentencia SQL * * @param string $value * Columna por la que se ordenará. * * @param string $order * Define si el orden será de manera ascendente (ASC), * descendente (DESC) o aleatorio (RAND). */ public static function orderBy($value, $order = 'ASC'){ if ($value == "RAND"){ self::$querySelect['orderBy'] = 'RAND()'; return new static(); } $value = self::db()->real_escape_string($value); if (!(strtoupper($order) == 'ASC' || strtoupper($order) == 'DESC')) $order = 'ASC'; self::$querySelect['orderBy'] = $value.' '.$order; return new static(); } /* * Retorna la cantidad de filas que hay en un query. * * @return int */ public static function count(){ self::$querySelect['select'] = 'count(*) as quantity'; $sql = self::buildQuery(); $result = self::query($sql)->fetch_assoc(); return $result['quantity']; } /* * Obtiene una instancia según su id. * * @param int $id * @return ModelMySQL */ public static function getById($id){ return self::where('id', $id)->getFirst(); } /* * Realiza una búsqueda en la tabla de la instancia actual. * * @param string $search * Contenido a buscar. * * @param array $in * Columnas en las que se va a buscar (null para buscar en todas) */ public static function search($search, $in = null){ if ($in == null){ $className = get_called_class(); $objAtts = array_keys((new $className())->getVars()); } $db = self::db(); $search = $db->real_escape_string($search); $where = []; foreach($in as $row){ if(in_array($row, $objAtts)) $where[] = "$row LIKE '%$search%'"; } if (self::$querySelect['where']=='') self::$querySelect['where'] = join($where, ' OR '); else self::$querySelect['where'] = self::$querySelect['where'] .' AND ('.join($where, ' OR ').')'; return new static(); } /* * Obtener los resultados de la consulta SQL. * * @return ModelMySQL[] */ public static function get(){ // Devuelve array vacío si no encuentra nada $sql = self::buildQuery(); $result = self::query($sql); $instaces = []; while ($row = $result->fetch_assoc()){ $instaces[] = self::getInstance($row); } return $instaces; } /* * El primer elemento de la consulta SQL. * * @return mixed * Puede retornar un objeto ModelMySQL o null. */ public static function getFirst(){ // Devuelve null si no encuentra nada self::limit(1); $instaces = self::get(); return empty($instaces) ? null : $instaces[0]; } /* * Obtener todos los elementos del la tabla de la instancia actual. * * @return ModelMySQL[] */ public static function all(){ $sql = 'SELECT * FROM '.self::table(); $result = self::query($sql); $instaces = []; while ($row = $result->fetch_assoc()){ $instaces[] = self::getInstance($row); } return $instaces; } } ?>