230 lines
8.5 KiB
PHP
230 lines
8.5 KiB
PHP
<?php
|
|
|
|
namespace lib\Core;
|
|
|
|
use \PDO;
|
|
use PDOException;
|
|
use PDOStatement;
|
|
|
|
abstract class Model
|
|
{
|
|
private $_db = null;
|
|
private $_debug = false;
|
|
private $_reset = true;
|
|
private $_querys = ['SELECT' => 'SELECT *', 'JOIN' => [], 'ORDERBY' => [], 'LIMIT' => ''];
|
|
private $_wheres = [];
|
|
private $_lastQuery = "";
|
|
protected function __construct()
|
|
{
|
|
$this->init();
|
|
} //
|
|
abstract public function getTable(): string;
|
|
abstract public function getPKField(): string;
|
|
abstract public function getTitleField(): string;
|
|
final public function getConnect(): PDO
|
|
{
|
|
if ($this->_db === null) {
|
|
$driver = $_ENV['DATABASE_DRIVER'] ?? $_SERVER['DATABASE_DRIVER'] ?? 'mysql';
|
|
$host = $_ENV['DATABASE_HOST'] ?? $_SERVER['DATABASE_HOST'] ?? 'localhost';
|
|
$dbname = $_ENV['DATABASE_DB'] ?? $_SERVER['DATABASE_DB'] ?? 'test';
|
|
$charset = $_ENV['DATABASE_CHARSET'] ?? $_SERVER['DATABASE_CHARSET'] ?? 'utf8';
|
|
$user = $_ENV['DATABASE_ID'] ?? $_SERVER['DATABASE_ID'] ?? 'root';
|
|
$pass = $_ENV['DATABASE_PASSWORD'] ?? $_SERVER['DATABASE_PASSWORD'] ?? '';
|
|
$dsn = sprintf("%s:host=%s;dbname=%s;charset=%s", $driver, $host, $dbname, $charset);
|
|
try {
|
|
$this->_db = new PDO($dsn, $user, $pass);
|
|
$this->_db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
|
$this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
} catch (PDOException $e) {
|
|
throw new \Exception("❌ DB 연결 실패: " . $e->getMessage());
|
|
}
|
|
}
|
|
$this->init();
|
|
return $this->_db;
|
|
}
|
|
final public function setDebug($debug)
|
|
{
|
|
$this->_debug = $debug;
|
|
}
|
|
final public function getDebug()
|
|
{
|
|
return $this->_debug;
|
|
}
|
|
private function init(): void
|
|
{
|
|
$debug = $_ENV['DATABASE_QUERY_DEBUG'] ?? $_SERVER['DATABASE_QUERY_DEBUG'] ?? 'false';
|
|
if ($debug === "true") {
|
|
$this->_debug = true;
|
|
}
|
|
$this->_reset = true;
|
|
$this->_querys = ['SELECT' => 'SELECT *', 'JOIN' => [], 'ORDERBY' => [], 'LIMIT' => ''];
|
|
$this->_wheres = [];
|
|
$this->_lastQuery = "";
|
|
}
|
|
final public function getLastQuery(): string
|
|
{
|
|
return $this->_lastQuery;
|
|
}
|
|
|
|
//Where절관련
|
|
private function getWhereValue(mixed $datas, $delimeter = ","): string
|
|
{
|
|
$value = "";
|
|
if ($datas === null) {
|
|
return "";
|
|
}
|
|
if (is_array($datas)) {
|
|
$temps = [];
|
|
foreach ($datas as $data) {
|
|
$data = trim($data);
|
|
$temps[] = is_string($data) ? "'{$data}'" : $data;
|
|
}
|
|
$value = implode($delimeter, $temps);
|
|
} else {
|
|
$value = is_string($datas) ? "='{$datas}'" : $datas;
|
|
}
|
|
return $value;
|
|
}
|
|
private function getWhereColumn(mixed $columns, mixed $datas = null): string
|
|
{
|
|
$temps = [];
|
|
if (is_array($columns)) {
|
|
//복합배열형태로 들어온 경우
|
|
foreach ($columns as $column => $data) {
|
|
$value = $this->getWhereValue($data);
|
|
$temps[] = "{$column}{$value}";
|
|
}
|
|
} else {
|
|
$value = $this->getWhereValue($datas);
|
|
$temps[] = "{$columns}{$value}";
|
|
}
|
|
// throw new \Exception("DATA:" . $columns . $value === null ? "NULL" : $value);
|
|
return implode(" ", $temps);
|
|
}
|
|
final public function getWhere(): string
|
|
{
|
|
return count($this->_wheres) ? "WHERE " . implode(" ", $this->_wheres) : "";
|
|
}
|
|
|
|
final public function where(mixed $columns, mixed $values = null, string $delimeter = "AND"): void
|
|
{
|
|
$query = $this->getWhereColumn($columns, $values);
|
|
$this->_wheres[] = count($this->_wheres) ? $delimeter . " " . $query : $query;
|
|
}
|
|
final public function orWhere(mixed $columns, mixed $values = null, string $delimeter = "OR"): void
|
|
{
|
|
$this->where($columns, $values, $delimeter);
|
|
}
|
|
final public function whereLike(string $column, string $value, string $option = "both", string $delimeter = "AND"): void
|
|
{
|
|
switch ($option) {
|
|
case 'before':
|
|
$value = "%{$value}";
|
|
break;
|
|
case 'after':
|
|
$value = "{$value}%";
|
|
break;
|
|
default:
|
|
$value = "%{$value}%";
|
|
break;
|
|
}
|
|
$this->where("{$column} LIKE '{$value}'", null, $delimeter);
|
|
}
|
|
final public function orWhereLike(string $column, string $value, string $option = "both", string $delimeter = "OR"): void
|
|
{
|
|
$this->whereLike($column, $value, $option, $delimeter);
|
|
}
|
|
final public function whereIn(string $column, array $values, string $delimeter = "AND", $range = "IN")
|
|
{
|
|
$query = " {$column} {$range} (" . $this->getWhereValue($values) . ")";
|
|
$this->_wheres[] = count($this->_wheres) ? $delimeter . " " . $query : $query;
|
|
}
|
|
final public function whereNotIn(string $column, array $values, string $delimeter = "AND", $range = "NOT IN")
|
|
{
|
|
$this->whereIn($column, $values, $delimeter, $range);
|
|
}
|
|
|
|
final public function execute(string $query): bool|PDOStatement
|
|
{
|
|
if ($this->_debug) {
|
|
echo "\n<BR>Query:" . $query . "\n<BR>";
|
|
}
|
|
$this->_lastQuery = $query;
|
|
$stmt = $this->getConnect()->prepare($query);
|
|
$stmt->execute();
|
|
if ($this->_reset) {
|
|
$this->init();
|
|
}
|
|
return $stmt;
|
|
}
|
|
|
|
//CURD문
|
|
final protected function create_process(mixed $columns, mixed $values = null): bool|PDOStatement
|
|
{
|
|
$query = sprintf("INSERT INTO %s VALUES(%s) %s", $this->getTable(), $this->getWhereColumn($columns, $values), $this->getWhere());
|
|
return $this->execute($query);
|
|
} //
|
|
final protected function modify_process(mixed $columns, mixed $values = null): bool|PDOStatement
|
|
{
|
|
$query = sprintf("UPDATE %s SET %s %s", $this->getTable(), $this->getWhereColumn($columns, $values), $this->getWhere());
|
|
return $this->execute($query);
|
|
} //
|
|
final protected function delete_process(): bool|PDOStatement
|
|
{
|
|
$query = sprintf("DELETE FROM %s %s", $this->getTable(), $this->getWhere());
|
|
return $this->execute($query);
|
|
} //
|
|
public function select(mixed $columns = "*"): void
|
|
{
|
|
$columns = is_array($columns) ? implode(",", $columns) : $columns;
|
|
$this->_querys["SELECT"] = "SELECT {$columns}";
|
|
}
|
|
//join_type : LEFT, RIGHT, INNER, OUTER
|
|
final public function join(string $table, mixed $match = null, $join_type = ""): void
|
|
{
|
|
$this->_querys['JOIN'][] = " {$join_type} JOIN {$table} ON {$match}";
|
|
}
|
|
final public function orderBy(mixed $columns, string $default_direction = ""): void
|
|
{
|
|
$orderBy = "";
|
|
if (is_array($columns)) {
|
|
foreach ($columns as $column => $direction) {
|
|
$this->orderBy($column, $direction ?? $default_direction);
|
|
}
|
|
} else {
|
|
$this->_querys['ORDERBY'][] = "{$columns} {$default_direction}";
|
|
}
|
|
}
|
|
final public function limit(int $start, int $offset = 0): void
|
|
{
|
|
$offset = $offset > 0 ? ",{$offset}" : "";
|
|
$this->_querys["LIMIT"] = " LIMIT {$start} {$offset}";
|
|
}
|
|
|
|
//Result
|
|
private function getResultQuery(string $head, string $tail = ""): string
|
|
{
|
|
$join = count($this->_querys['JOIN']) ? implode(",", $this->_querys['JOIN']) : "";
|
|
$where = $this->getWhere();
|
|
$orderby = count($this->_querys['ORDERBY']) ? "ORDER BY " . implode(",", $this->_querys['ORDERBY']) : "";
|
|
return "{$head} FROM {$this->getTable()} {$join} {$where} {$tail} {$orderby} {$this->_querys['LIMIT']}";
|
|
}
|
|
public function getResult($mode = PDO::FETCH_ASSOC): mixed
|
|
{
|
|
$stmt = $this->execute($this->getResultQuery($this->_querys['SELECT']));
|
|
return $stmt->fetch($mode);
|
|
}
|
|
public function getResults($mode = PDO::FETCH_ASSOC): mixed
|
|
{
|
|
$stmt = $this->execute($this->getResultQuery($this->_querys['SELECT']));
|
|
return $stmt->fetchAll($mode);
|
|
}
|
|
final public function countAllResults(string $column = "*", $reset = true): int
|
|
{
|
|
$this->_reset = $reset;
|
|
$stmt = $this->execute($this->getResultQuery("SELECT COUNT({$column})"));
|
|
$count = $stmt->fetchColumn(0);
|
|
$this->_reset = true;
|
|
return $count;
|
|
}
|
|
} //Class
|