mvc init...

This commit is contained in:
최준흠 2024-08-23 14:41:51 +09:00
parent bc057be7d1
commit 9e5eec030c
14 changed files with 620 additions and 0 deletions

4
.env.ini Normal file
View File

@ -0,0 +1,4 @@
[db]
dsn="mysql:host=localhost;dbname=wordpress;charset=UTF8"
id="wordpress"
passwd="12clqkidc@!"

33
app.php Normal file
View File

@ -0,0 +1,33 @@
<?php
define("APP", dirname(__FILE__));
define("CONTROLLER", "lib\\Controller\\");
define("MODEL", "lib\\Model\\");
define("ENTITY", "lib\\Entity\\");
define("VIEW", "lib\\Vew\\");
define("MANGBOARD_ADMIN_ID", "admin");
define("MANGBOARD_POINT_UNIT", 1000);
define("MANGBOARD_LEVEL_USER_MIN", 1);
define("MANGBOARD_LEVEL_USER_MAX", 5);
define("MANGBOARD_LEVEL_ADMIN", 10);
require_once __DIR__ . DIRECTORY_SEPARATOR . "lib/autoload.php";
try {
if (1 > $argc) {
throw new \Exception("사용법 : php app.php 클래스명 [함수명(default:execute) parameters]\n");
}
//php 파일명
$phpName = array_shift($argv);
//클래스 검사(Autoload)
$className = CONTROLLER . array_shift($argv);
$class = new $className();
//함수 검사
$functionName = array_shift($argv) ?: "execute";
if (!method_exists($class, $functionName)) {
throw new \Exception("클래스[{$className}]에 함수[{$functionName}]는 존재하지 않습니다.\n");
}
echo $class->$functionName($argv);
} catch (\Exception $e) {
echo $e->getMessage();
} //

View File

@ -0,0 +1,13 @@
<?php
namespace lib\Controller\Mangboard;
use lib\Core\Controller;
class BaseController extends Controller
{
public function __construct()
{
parent::__construct();
} //
}

View File

@ -0,0 +1,96 @@
<?php
namespace lib\Controller\Mangboard;
use lib\Entity\Mangboard\UserEntity;
class UserController extends BaseController
{
private $_model = null;
public function __construct()
{
parent::__construct();
$this->_model = $this->getModel("Mangboard\\UserModel");
} //
final public function setPoint($params)
{
if (count($params) != 3) {
return "사용법: php app.php Mangboard\UserController setPoint 아이디 포인트 +|-\n" . var_export($params);
}
$id = $params[0];
$point = intval($params[1]);
if (!is_int($point)) {
return "{$params[1]}은 숫자형식이 아닙니다.";
}
$point = intval($params[1]);
switch ($params[2]) {
case '+':
case '-':
$sign = $params[2];
break;
default:
return "형식오류 +/- 가 아닙니다";
// break;
}
$this->_model->where("user_id", $id);
$entity = $this->_model->getEntity();
if (!$entity) {
return "[{$id}]에 해당하는 회원은 없습니다";
}
$old_point = $entity->getPoint();
if (is_int($point)) {
$entity = $this->_model->setPoint($entity, $point, $sign);
}
return "[{$entity}] 회원님의 포인트는 {$old_point}->{$entity->getPoint()} 입니다.";
} //
final public function getPoint($params)
{
if (count($params) == 1) {
$id = $params[0];
if ($id) {
$this->_model->where("user_id", $id);
$entity = $this->_model->getEntity();
if (!$entity) {
return "[{$id}]에 해당하는 회원은 없습니다";
}
}
}
$msgs = [];
foreach ($this->_model->getEntitys() as $entity) {
$msgs[] = "[{$entity}] 회원님의 포인트는 {$entity->getPoint()} 입니다.";
}
return implode("\n", $msgs);
} //
private function setLevel(UserEntity $entity, int $level)
{
$old_level = $entity->getLevel();
$entity = $this->_model->setLevel($entity, $level);
return "[{$entity}] 회원님의 레벨 {$old_level} -> {$entity->getLevel()}로 변경되었습니다.";
}
final public function checkLevel($id = false)
{
$entitys = [];
if ($id) {
$this->_model->where("user_id", $id);
$entity = $this->_model->getEntity();
if (!$entity) {
return "[{$id}]에 해당하는 회원은 없습니다";
}
$entitys[] = $entity;
} else {
$entitys = $this->_model->getEntitys();
}
$msgs = [];
foreach ($entitys as $entity) {
$level = intval($entity->getPoint() / MANGBOARD_POINT_UNIT * MANGBOARD_POINT_UNIT / MANGBOARD_POINT_UNIT);
if ($entity->getLevel() != $level) {
$msgs[] = $this->setLevel($entity, $level);
}
}
return PHP_EOL . "------" . date('Y/m/d-H:m') . "---------" . PHP_EOL . implode(PHP_EOL, $msgs) . PHP_EOL . "------------------------------" . PHP_EOL;
} //
}

38
lib/Core/Controller.php Normal file
View File

@ -0,0 +1,38 @@
<?php
namespace lib\Core;
abstract class Controller
{
private $_models = [];
private $_view = null;
private $_datas = [];
protected function __construct()
{
$this->_view = new View();
} //
final public function __get($name)
{
return array_key_exists($name, $this->_datas) ? $this->_datas[$name] : null;
}
final public function __set($name, $value)
{
$this->_datas[$name] = $value;
}
//Model
final public function getModel($name)
{
if (!array_key_exists($name, $this->_models)) {
$className = MODEL . $name;
$this->_models[$name] = new $className();
}
return $this->_models[$name];
}
final public function view($file, array $datas = [])
{
return $this->_view->render($file, $datas);
}
} //Class

53
lib/Core/Entity.php Normal file
View File

@ -0,0 +1,53 @@
<?php
namespace lib\Core;
abstract class Entity
{
private $_origins = [];
private $_values = [];
private $_isChanged = false;
private $_changedFields = [];
protected function __construct() {} //
final public function __get($key)
{
return $this->_values[$key];
}
final public function __set($key, $value)
{
if (array_key_exists($key, $this->_values)) {
// echo "{$this->_values[$key]} !== {$value}";
if ($this->_values[$key] !== $value) {
$this->_isChanged = true;
$this->_changedFields[] = $key;
$this->_origins[$key] = $this->_values[$key];
$this->_values[$key] = $value;
}
} else {
$this->_isChanged = true;
$this->_changedFields[] = $key;
$this->_origins = $this->_values;
$this->_values[$key] = $value;
}
}
final public function isChanged()
{
return $this->_isChanged;
}
final public function clearChangedFields()
{
$this->_isChanged = false;
$this->_changedFields = $this->_values;
}
final public function getChangedFields(): array
{
return $this->_changedFields;
}
final public function getOrigins(): array
{
return $this->_origins;
}
} //Class

145
lib/Core/Model.php Normal file
View File

@ -0,0 +1,145 @@
<?php
namespace lib\Core;
use Exception;
use PDO;
use PDOException;
use PDOStatement;
abstract class Model
{
private $_db = null;
private $_wheres = [];
private $_primaryKey = false;
protected $resultMode = 'array';
protected function __construct(string $primaryKey)
{
$this->_primaryKey = $primaryKey;
} //
abstract public function getTable();
final public function getPrimaryKey(): string
{
if (!$this->_primaryKey) {
throw new \Exception("PrimayKey가 지정되지 않았습니다.");
}
return $this->_primaryKey;
}
final public function getDB()
{
if ($this->_db === null) {
$envs = parse_ini_file(APP . DIRECTORY_SEPARATOR . ".env.ini", true);
if (!$envs) {
throw new Exception(var_export($envs, true));
}
$this->_db = new PDO($envs['db']['dsn'], $envs['db']['id'], $envs['db']['passwd']);
// $this->_db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// echo "Connected successfully: " . $this->_db->getAttribute(PDO::ATTR_CONNECTION_STATUS) . "\n";
}
return $this->_db;
}
final public function where($key, $value, $condition = "AND")
{
if (is_array($value)) {
throw new \Exception("Value is Array:" . var_export($value, true));
}
$this->_wheres[] = sprintf(
" %s {$key}=%s",
count($this->_wheres) ? $condition : "WHERE",
is_int($value) ? $value : "'{$value}'"
);
}
private function chanegValueToSQLTypeValue($value)
{
return is_int($value) ? $value : "'{$value}'";
}
final public function execute($sql): bool|PDOStatement
{
$sql .= implode(" ", $this->_wheres);
//echo $sql . "\n";
$stmt = $this->getDB()->prepare($sql);
if (!$stmt->execute()) {
throw new Exception("SQL 오류: {$stmt->errorInfo()} \n{$sql}\n");
}
$this->_wheres = [];
return $stmt;
}
//SQL문
final public function select(array $columns = ["*"]): bool|PDOStatement
{
$sql = sprintf("SELECT %s FROM %s", implode(",", $columns), $this->getTable());
return $this->execute($sql);
}
final public function insert(array $datas)
{
$sqlDatas = [];
foreach ($datas as $key => $value) {
$sqlDatas[$key] = $this->chanegValueToSQLTypeValue($value);
}
$sql = sprintf("INSERT INTO {$this->getTable()} SET (%s) VALUES (%s}", array_keys($sqlDatas), array_values($sqlDatas));
return $this->execute($sql);
}
final public function update(array $datas)
{
$sqlDatas = [];
foreach ($datas as $key => $value) {
if ($key === $this->getPrimaryKey()) { //PrimaryKey변경불가
continue;
}
$value = $this->chanegValueToSQLTypeValue($value);
$sqlDatas[] = "{$key}={$value}";
}
$sql = sprintf("UPDATE {$this->getTable()} SET %s", implode(",", $sqlDatas));
return $this->execute($sql);
}
public function save($entity)
{
if ($entity->isChanged()) {
$pk = $this->getPrimaryKey();
if ($entity->$pk) {
$this->where($pk, $entity->$pk);
$datas = [];
foreach ($entity->getChangedFields() as $key) {
$datas[$key] = $entity->$key;
}
$this->update($datas);
$entity->clearChangedFields();
} else {
$datas = [];
foreach ($entity->getChangedFields() as $key) {
$datas[$key] = $entity->$key;
}
$this->insert($datas);
$entity->$pk = $this->getDB()->lastInsertId();
$entity->clearChangedFields();
}
}
return $entity;
}
final public function getEntity()
{
$stmt = $this->select();
if (class_exists($this->resultMode)) {
$stmt->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, $this->resultMode);
return $stmt->fetch();
}
return $stmt->fetch(PDO::FETCH_DEFAULT);
}
final public function getEntitys()
{
$stmt = $this->select();
if (class_exists($this->resultMode)) {
$stmt->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, $this->resultMode);
return $stmt->fetchAll();
}
return $stmt->fetchAll(PDO::FETCH_DEFAULT);
}
} //Class

42
lib/Core/View.php Normal file
View File

@ -0,0 +1,42 @@
<?php
namespace lib\Core;
use Exception;
class View
{
private $_viewPath = "./View";
private $_values = [];
public function __construct(array $datas = [])
{
$this->_values = $datas;
} //
final public function __get($name)
{
return $this->_values[$name];
}
final public function __set($name, $value)
{
$this->_values[$name] = $value;
}
final public function setDatas(array $datas)
{
foreach ($datas as $key => $value) {
$this->_values[$key] = $value;
}
}
final public function render($name, array $datas = [])
{
$fullPath = $this->_viewPath . DIRECTORY_SEPARATOR . $name . ".php";
if (!file_exists($fullPath)) {
throw new Exception(sprintf("%s 파일이 존재하지 않습니다.", $fullPath));
}
$this->setDatas($datas);
ob_start();
include $fullPath;
return ob_end_flush();
}
} //Class

View File

@ -0,0 +1,12 @@
<?php
namespace lib\Entity\Mangboard;
use lib\Core\Entity;
abstract class BaseEntity extends Entity
{
protected function __construct()
{
parent::__construct();
} //
} //Class

View File

@ -0,0 +1,42 @@
<?php
namespace lib\Entity\Mangboard;
class UserEntity extends BaseEntity
{
public function __construct()
{
parent::__construct();
} //
public function __toString()
{
return "{$this->getName()}";
}
public function getUserID()
{
return $this->user_id;
}
public function getName()
{
return $this->user_name;
}
public function getPoint()
{
return $this->user_point;
}
public function setPoint(int $point)
{
return $this->user_point = $point;
}
public function getLevel()
{
return $this->user_level;
}
public function setLevel(int $level)
{
return $this->user_level = $level;
}
} //Class

View File

@ -0,0 +1,13 @@
<?php
namespace lib\Model\Mangboard;
use lib\Core\Model;
abstract class BaseModel extends Model
{
protected function __construct(string $primaryKey)
{
parent::__construct($primaryKey);
} //
} //Class

View File

@ -0,0 +1,51 @@
<?php
namespace lib\Model\Mangboard;
use lib\Entity\Mangboard\UserEntity;
class UserModel extends BaseModel
{
protected $resultMode = UserEntity::class;
public function __construct()
{
parent::__construct("pid");
} //
final public function getTable()
{
return 'mb_users';
}
public function setPoint(UserEntity $entity, int $point, $sign = '+'): UserEntity
{
switch (strtolower($sign)) {
case '-':
if ($entity->getPoint() < $point) {
throw new \Exception("기존포인트:{$entity->getPoint()}가 감소 포인트:-{$point} 작습니다.\n");
}
$entity->setPoint($entity->getPoint() - $point);
break;
case '+':
$entity->setPoint($entity->getPoint() + $point);
break;
default:
throw new \Exception("{$sign}에 해당하는 작업은 수행할수 없습니다.\n");
// break;
}
return $this->save($entity);
}
final public function setLevel(UserEntity $entity, int $level): UserEntity
{
//관리자면 변경불가
if ($entity->getUserID() == MANGBOARD_ADMIN_ID) {
return $entity;
}
//사용자 Level 1~5;
$level = $level < MANGBOARD_LEVEL_USER_MIN ? MANGBOARD_LEVEL_USER_MIN : $level;
$level = MANGBOARD_LEVEL_USER_MAX < $level ? MANGBOARD_LEVEL_USER_MAX : $level;
$entity->setLevel($level);
return $this->save($entity);
}
} //Class

View File

@ -0,0 +1,70 @@
<style>
table {
border-collapse: collapse;
}
table,
td,
th {
border: 1px solid black;
text-align: center;
}
</style>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<td rowspan="2">고객명</td>
<td colspan="2">일반</td>
<td colspan="2">방어</td>
<td colspan="2">전용</td>
<td colspan="2">대체</td>
<td colspan="3">테스트</td>
<td colspan="3">합계</td>
</tr>
<tr>
<td>도쿄</td>
<td>치바</td>
<td>도쿄</td>
<td>치바</td>
<td>도쿄</td>
<td>치바</td>
<td>도쿄</td>
<td>치바</td>
<td>도쿄</td>
<td>치바</td>
<td>합계</td>
<td>도쿄</td>
<td>치바</td>
<td>합계</td>
</tr>
</thead>
<tbody>
<?php foreach ($this->results as $company => $service) {?>
<tr>
<td><?php echo $company ?></td>
<?php foreach ($service as $name => $location) {?>
<td><?php echo $location['Tokyo']; ?></td>
<td><?php echo $location['Chiba']; ?></td>
<?php }?>
<td><?php echo $service['test']['Tokyo'] + $service['test']['Chiba']; ?></td>
<td><?php echo $this->summary[$company]['Tokyo'] - $service['test']['Tokyo']; ?></td>
<td><?php echo $this->summary[$company]['Chiba'] - $service['test']['Chiba']; ?></td>
<td><?php echo $this->summary[$company]['Tokyo'] - $service['test']['Tokyo'] + $this->summary[$company]['Chiba'] - $service['test']['Chiba']; ?></td>
</tr>
<?php }?>
</tbody>
<tfoot>
<tr>
<td>총합계</td>
<?php foreach ($this->_values['types'] as $type) {?>
<td><?php echo $this->summary[$type]['Tokyo']; ?></td>
<td><?php echo $this->summary[$type]['Chiba']; ?></td>
<?php }?>
<td><?php echo $this->summary['test']['Tokyo'] + $this->summary['test']['Chiba']; ?></td>
<td><?php echo $this->total['Tokyo'] - $this->summary['test']['Tokyo']; ?></td>
<td><?php echo $this->total['Chiba'] - $this->summary['test']['Chiba']; ?></td>
<td><?php echo $this->total['Tokyo'] - $this->summary['test']['Tokyo'] + $this->total['Chiba'] - $this->summary['test']['Chiba']; ?></td>
</tr>
</tfoot>
</table>

8
lib/autoload.php Normal file
View File

@ -0,0 +1,8 @@
<?php
spl_autoload_register(function ($class) {
$classFile = APP . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $class) . ".php";
if (!file_exists($classFile)) {
throw new \Exception("{$class} || {$classFile}을 찾을수 없습니다.\n");
};
require_once $classFile;
});