cfmgrv4 init...1

This commit is contained in:
최준흠 2024-10-03 19:29:11 +09:00
parent 2b5c8de10a
commit d5fd167712
22 changed files with 130 additions and 66 deletions

View File

@ -40,7 +40,6 @@ $routes->group('admin', ['namespace' => 'App\Controllers\Admin'], function ($rou
$routes->get('download/(:alpha)/(:any)', 'MapurlController::download/$1/$2');
});
$routes->group('cloudflare', ['namespace' => 'App\Controllers\Admin\Cloudflare'], function ($routes) {
$routes->cli('/reload', 'CloudflareController::reload');
$routes->group('auth', function ($routes) {
$routes->get('/', 'AuthController::index');
$routes->get('create', 'AuthController::create_form');
@ -52,12 +51,20 @@ $routes->group('admin', ['namespace' => 'App\Controllers\Admin'], function ($rou
$routes->post('batchjob', 'AuthController::batcjob');
$routes->get('download/(:alpha)', 'AuthController::download/$1');
$routes->get('download/(:alpha)/(:any)', 'AuthController::download/$1/$2');
$routes->get('reload/(:num)', 'AuthController::reload/$1');
$routes->get('reload', 'AuthController::reload');
$routes->cli('reload/(:num)', 'AuthController::reload/$1');
$routes->cli('reload', 'AuthController::reload');
});
$routes->group('account', function ($routes) {
$routes->get('/', 'AccountController::index');
$routes->post('create/(:uuid)', 'AccountController::create');
$routes->get('download/(:alpha)', 'AccountController::download/$1');
$routes->get('download/(:alpha)/(:any)', 'AccountController::download/$1/$2');
$routes->get('reload/(:alphanum)', 'AccountController::reload/$1');
$routes->get('reload', 'AccountController::reload');
$routes->cli('reload/(:alphanum)', 'AccountController::reload/$1');
$routes->cli('reload', 'AccountController::reload');
});
$routes->group('zone', function ($routes) {
$routes->get('/', 'ZoneController::index');
@ -68,6 +75,10 @@ $routes->group('admin', ['namespace' => 'App\Controllers\Admin'], function ($rou
$routes->post('batchjob', 'ZoneController::batcjob');
$routes->get('download/(:alpha)', 'ZoneController::download/$1');
$routes->get('download/(:alpha)/(:any)', 'ZoneController::download/$1/$2');
$routes->get('reload/(:alphanum)', 'ZoneController::reload/$1');
$routes->get('reload', 'ZoneController::reload');
$routes->cli('reload/(:alphanum)', 'ZoneController::reload/$1');
$routes->cli('reload', 'ZoneController::reload');
});
$routes->group('record', function ($routes) {
$routes->get('/', 'RecordController::index');

View File

@ -22,6 +22,7 @@ class AccountController extends CloudflareController
$this->class_name = "Account";
$this->class_path = $this->root . $this->class_name;
$this->title = lang("{$this->class_path}.title");
$this->action_form = getenv("mvc.default." . strtolower($this->class_name) . ".form") ?: "modal_form";
helper($this->class_path);
}
final protected function getModel(): AccountModel
@ -76,15 +77,18 @@ class AccountController extends CloudflareController
return $this->download_procedure($output_type, $uid);
}
//Zone Reload By Account
protected function reload_process(): void
protected function reload_process(mixed $uid = false): void
{
foreach ($this->getModel()->getEntitys as $entity) {
if ($uid) {
$this->getModel()->where($this->getModel()::PK, $uid);
}
foreach ($this->getModel()->getEntitys() as $entity) {
$zone_socket = new ZoneSocket($entity);
$zone_socket->reload();
}
}
public function reload(): RedirectResponse
public function reload(mixed $uid = false): RedirectResponse
{
return $this->reload_procedure();
return $this->reload_procedure($uid);
}
}

View File

@ -19,6 +19,7 @@ class AuthController extends CloudflareController
$this->class_name = "Auth";
$this->class_path = $this->root . $this->class_name;
$this->title = lang("{$this->class_path}.title");
$this->action_form = getenv("mvc.default." . strtolower($this->class_name) . ".form") ?: "modal_form";
helper($this->class_path);
}
final protected function getModel(): AuthModel
@ -45,7 +46,7 @@ class AuthController extends CloudflareController
public function create(): RedirectResponse|string
{
$this->init(__FUNCTION__);
return $this->create_procedure();
return $this->create_procedure($this->action_form);
}
//수정
public function modify_form(string $uid): RedirectResponse|string
@ -56,7 +57,7 @@ class AuthController extends CloudflareController
public function modify(string $uid): RedirectResponse|string
{
$this->init(__FUNCTION__);
return $this->modify_procedure($uid);
return $this->modify_procedure($uid, $this->action_form);
}
//일괄처리작업
public function batcjob(): RedirectResponse
@ -89,15 +90,18 @@ class AuthController extends CloudflareController
return $this->download_procedure($output_type, $uid);
}
//Account Reload by Auth
protected function reload_process(): void
protected function reload_process(mixed $uid = false): void
{
foreach ($this->getModel()->getEntitys as $entity) {
if ($uid && intval($uid) > 0) {
$this->getModel()->where($this->getModel()::PK, intval($uid));
}
foreach ($this->getModel()->getEntitys() as $entity) {
$account_socket = new AccountSocket($entity);
$account_socket->reload();
}
}
public function reload(): RedirectResponse
public function reload(mixed $uid = false): RedirectResponse
{
return $this->reload_procedure();
return $this->reload_procedure($uid);
}
}

View File

@ -53,15 +53,16 @@ abstract class CloudflareController extends AdminController
return $this->_recordModel;
}
protected function reload_process(): void {}
final protected function reload_procedure(): RedirectResponse
protected function reload_process(mixed $uid = false): void {}
final protected function reload_procedure(mixed $uid = false): RedirectResponse
{
//Transaction Start
$this->getModel()->transStart();
try {
$this->reload_process();
log_message("notice", __FUNCTION__ . "=> 작업을 완료하였습니다.");
$this->session->setFlashdata(SESSION_NAMES['RETURN_MSG'], __FUNCTION__ . " => 작업을 완료하였습니다.\n");
$this->reload_process($uid);
$message = "Reload 작업을 완료하였습니다.";
log_message("notice", $message);
$this->session->setFlashdata(SESSION_NAMES['RETURN_MSG'], $message);
$this->getModel()->transCommit();
return redirect()->to($this->session->getFlashdata(SESSION_NAMES['RETURN_URL']) ?: "/");
} catch (\Exception $e) {

View File

@ -19,6 +19,7 @@ class RecordController extends CloudflareController
$this->class_name = "Record";
$this->class_path = $this->root . $this->class_name;
$this->title = lang("{$this->class_path}.title");
$this->action_form = getenv("mvc.default." . strtolower($this->class_name) . ".form") ?: "modal_form";
helper($this->class_path);
}
final protected function getModel(): RecordModel
@ -109,7 +110,7 @@ class RecordController extends CloudflareController
}
$cnt++;
}
return $this->create_procedure();
return $this->create_procedure($this->action_form);
}
//수정 (modify,toggle,batchjob사용)
protected function modify_process(string $uid): void
@ -154,7 +155,7 @@ class RecordController extends CloudflareController
$this->action = __FUNCTION__;
$this->fields = [$this->getModel()::PARENT, $this->getModel()::TITLE, 'type', 'content', 'ttl', 'proxied', 'locked', 'updated_at', 'created_at'];
$this->field_rules = $this->getModel()->getFieldRules($this->action, $this->fields);
$this->filter_fields = [$this->getModel()::PARENT, 'type', 'proxied'];
$this->filter_fields = [$this->getModel()::PARENT, 'type', 'proxied', 'fixed'];
$this->field_options = $this->getFormFieldOptions($this->filter_fields);
$this->batchjob_fields = ['proxied'];
return $this->list_procedure();

View File

@ -22,6 +22,7 @@ class ZoneController extends CloudflareController
$this->class_name = "Zone";
$this->class_path = $this->root . $this->class_name;
$this->title = lang("{$this->class_path}.title");
$this->action_form = getenv("mvc.default." . strtolower($this->class_name) . ".form") ?: "modal_form";
helper($this->class_path);
}
final protected function getModel(): ZoneModel
@ -152,7 +153,7 @@ class ZoneController extends CloudflareController
}
$cnt++;
}
return $this->create_procedure();
return $this->create_procedure($this->action_form);
}
//수정 (modify,toggle,batchjob사용)
protected function modify_process(string $uid): void
@ -214,15 +215,18 @@ class ZoneController extends CloudflareController
return $this->download_procedure($output_type, $uid);
}
//reload Record By Zone
protected function reload_process(): void
protected function reload_process(mixed $uid = false): void
{
foreach ($this->getModel()->getEntitys as $entity) {
if ($uid) {
$this->getModel()->where($this->getModel()::PK, $uid);
}
foreach ($this->getModel()->getEntitys() as $entity) {
$record_socket = new RecordSocket($entity);
$record_socket->reload();
}
}
public function reload(): RedirectResponse
public function reload(mixed $uid = false): RedirectResponse
{
return $this->reload_procedure();
return $this->reload_procedure($uid);
}
}

View File

@ -19,6 +19,7 @@ class MapurlController extends AdminController
$this->class_name = "Mapurl";
$this->class_path = $this->root . $this->class_name;
$this->title = lang("{$this->class_path}.title");
$this->action_form = getenv("mvc.default." . strtolower($this->class_name) . ".form") ?: "modal_form";
helper($this->class_path);
}
protected function getModel(): MapurlModel
@ -85,7 +86,7 @@ class MapurlController extends AdminController
public function create(): RedirectResponse|string
{
$this->init(__FUNCTION__);
return $this->create_procedure();
return $this->create_procedure($this->action_form);
}
//수정
public function modify_form(string $uid): RedirectResponse|string
@ -102,7 +103,7 @@ class MapurlController extends AdminController
public function modify(string $uid): RedirectResponse|string
{
$this->init(__FUNCTION__);
return $this->modify_procedure($uid);
return $this->modify_procedure($uid, $this->action_form);
}
//일괄처리작업
public function batcjob(): RedirectResponse

View File

@ -20,6 +20,7 @@ class UserController extends AdminController
$this->class_name = "User";
$this->class_path = $this->root . $this->class_name;
$this->title = lang("{$this->class_path}.title");
$this->action_form = getenv("mvc.default." . strtolower($this->class_name) . ".form") ?: "modal_form";
helper($this->class_path);
}
protected function getModel(): UserModel
@ -84,7 +85,7 @@ class UserController extends AdminController
public function create(): RedirectResponse|string
{
$this->init(__FUNCTION__);
return $this->create_procedure();
return $this->create_procedure($this->action_form);
}
//수정
public function modify_form(string $uid): RedirectResponse|string
@ -95,7 +96,7 @@ class UserController extends AdminController
public function modify(string $uid): RedirectResponse|string
{
$this->init(__FUNCTION__);
return $this->modify_procedure($uid);
return $this->modify_procedure($uid, $this->action_form);
}
//일괄작업
public function batcjob(): RedirectResponse

View File

@ -18,7 +18,6 @@ abstract class MVController extends CommonController
{
parent::initController($request, $response, $logger);
helper('common');
$this->action_form = getenv("mvc.default.action.form") ?? "modal_form";
}
abstract protected function getModel(): mixed;
//Field별 Form Rule용
@ -112,7 +111,7 @@ abstract class MVController extends CommonController
$this->formDatas = $this->getFormDatas();
$this->entity = $this->getModel()->create(formDatas: $this->formDatas);
}
final protected function create_procedure(): RedirectResponse|string
final protected function create_procedure(string $action_form = "default"): RedirectResponse|string
{
//Transaction Start
$this->getModel()->transStart();
@ -121,12 +120,12 @@ abstract class MVController extends CommonController
$this->getModel()->transCommit();
$this->message = "입력작업이 완료되었습니다.";
log_message("notice", __FUNCTION__ . $this->message);
switch ($this->action_form) {
switch ($action_form) {
case FORMS['MODAL']:
$result = view("templates/{$this->layout}/{$this->action_form}_close", data: ['viewDatas' => $this->getViewDatas()]);
$result = view("templates/{$this->layout}/{$action_form}_close", data: ['viewDatas' => $this->getViewDatas()]);
break;
case FORMS['IFRAM']:
$result = view("templates/{$this->layout}/{$this->action_form}_close", data: ['viewDatas' => $this->getViewDatas()]);
$result = view("templates/{$this->layout}/{$action_form}_close", data: ['viewDatas' => $this->getViewDatas()]);
break;
default:
$this->session->setFlashdata(SESSION_NAMES['RETURN_MSG'], $this->message);
@ -189,7 +188,7 @@ abstract class MVController extends CommonController
}
$this->entity = $this->getModel()->modify($this->entity, $this->formDatas);
}
final protected function modify_procedure(string $uid): RedirectResponse|string
final protected function modify_procedure(string $uid, string $action_form = "default"): RedirectResponse|string
{
//Transaction Start
$this->getModel()->transStart();
@ -198,12 +197,12 @@ abstract class MVController extends CommonController
$this->getModel()->transCommit();
$this->message = "수정작업이 완료되었습니다.";
log_message("notice", __FUNCTION__ . $this->message);
switch ($this->action_form) {
switch ($action_form) {
case FORMS['MODAL']:
$result = view("templates/{$this->layout}/{$this->action_form}_close", data: ['viewDatas' => $this->getViewDatas()]);
$result = view("templates/{$this->layout}/{$action_form}_close", data: ['viewDatas' => $this->getViewDatas()]);
break;
case FORMS['IFRAME']:
$result = view("templates/{$this->layout}/{$this->action_form}_close", data: ['viewDatas' => $this->getViewDatas()]);
$result = view("templates/{$this->layout}/{$action_form}_close", data: ['viewDatas' => $this->getViewDatas()]);
break;
default:
$this->session->setFlashdata(SESSION_NAMES['RETURN_MSG'], $this->message);
@ -356,7 +355,7 @@ abstract class MVController extends CommonController
);
}
$entitys = $this->getModel()->select($this->getModel()->getTable() . '.*')->findAll();
echo $this->getModel()->getLastQuery();
log_message("debug", $this->getModel()->getLastQuery());
return $entitys;
}
final protected function list_procedure(): string

View File

@ -103,7 +103,7 @@ function getFieldView_AccountHelper(string $field, AccountEntity $entity, array
break;
case 'updated_at':
case 'created_at':
$value = $value ? date("Y-m-d", strtotime($value)) : "";
// $value = $value ? date("Y-m-d", strtotime($value)) : "";
break;
default:
// if (in_array($field, $viewDatas['filter_fields']) && $value) {

View File

@ -10,7 +10,7 @@ return [
'ttl' => "TTL",
'proxiable' => "proxiable",
'fixed' => "CDN잠금",
'proxied' => "CDN기능",
'proxied' => "CDN사용여부",
'locked' => "서비스",
'updated_at' => "수정일",
'created_at' => "작성일",

View File

@ -40,9 +40,10 @@ class AccountSocket extends CloudflareSocket
public function getArrayByResult($result, array $formDatas = []): array
{
$formDatas[AccountModel::PK] = $result->id;
$formDatas[AccountModel::PARENT] = $this->_auth_entity->getPK();
$formDatas[AccountModel::TITLE] = $result->name;
$formDatas['type'] = $result->type;
$formDatas['status'] = 'use';
$formDatas['status'] = $this->_auth_entity->status;
$formDatas['updated_at'] = date("Y-m-d H:i:s");
$formDatas['created_at'] = $result->created_on;
return $formDatas;
@ -53,9 +54,11 @@ class AccountSocket extends CloudflareSocket
$entity_uids = [];
$results = $this->reload_procedure("accounts");
foreach ($results as $result) {
$formDatas = $this->getArrayByResult($result);
$entity = $this->getModel()->modify($this->getModel()->getEntity(), $formDatas);
$entity_uids[] = $entity->getPK();
foreach ($result as $item) {
$formDatas = $this->getArrayByResult($item);
$entity = $this->getModel()->modify($this->getModel()->getEntity(), $formDatas);
$entity_uids[] = $entity->getPK();
}
}
//부모키를 기준으로 CF에 존재하지 않는 데이터 삭제용
$this->getModel()->where(AccountModel::PARENT, $this->_auth_entity);

View File

@ -136,10 +136,13 @@ class RecordSocket extends CloudflareSocket
$entity_uids = [];
$results = $this->reload_procedure("zones/{$this->_zone_entity->getPK()}/dns_records");
//DB수정
dd($results);
foreach ($results as $result) {
$formDatas = $this->getArrayByResult($result);
$entity = $this->getModel()->modify($this->getModel()->getEntity(), $formDatas);
$entity_uids[] = $entity->getPK();
foreach ($result as $item) {
$formDatas = $this->getArrayByResult($item);
$entity = $this->getModel()->modify($this->getModel()->getEntity(), $formDatas);
$entity_uids[] = $entity->getPK();
}
}
//부모키를 기준으로 CF에 존재하지 않는 데이터 DB삭제
$this->getModel()->where(RecordModel::PARENT, $this->_zone_entity);

View File

@ -168,9 +168,11 @@ class ZoneSocket extends CloudflareSocket
$entity_uids = [];
$results = $this->reload_procedure('zones');
foreach ($results as $result) {
$formDatas = $this->getArrayByResult($result);
$entity = $this->getModel()->modify($this->getModel()->getEntity(), $formDatas);
$entity_uids[] = $entity->getPK();
foreach ($result as $item) {
$formDatas = $this->getArrayByResult($item);
$entity = $this->getModel()->modify($this->getModel()->getEntity(), $formDatas);
$entity_uids[] = $entity->getPK();
}
}
//부모키를 기준으로 CF에 존재하지 않는 데이터 삭제용
$this->getModel()->where(ZoneModel::PARENT, $this->_account_entity);

View File

@ -12,8 +12,10 @@ use App\Entities\Cloudflare\AuthEntity;
abstract class CloudflareSocket extends CommonLibrary
{
private static int $_request = 0;
private static int $_request_max = 100;
private static int $_request_max = 1000;
private static int $_request_perpage_max = 700;
private static int $_request_timewait = 60;
private $_authModel = null;
private $_accountModel = null;
private $_client = null;
@ -22,7 +24,9 @@ abstract class CloudflareSocket extends CommonLibrary
{
parent::__construct();
$this->_auth_entity = $auth_entity;
self::$_request_max = getenv("cfmgr.request.max");
self::$_request_max = getenv("cfmgr.request.max") ?: 1000;
self::$_request_perpage_max = getenv("cfmgr.request.perpage.max") ?: 700;
self::$_request_timewait = getenv("cfmgr.request.timewait") ?: 60;
}
abstract protected function getArrayByResult($result, array $formDatas = []): array;
final protected function getAuthModel(): AuthModel
@ -49,12 +53,13 @@ abstract class CloudflareSocket extends CommonLibrary
'X-Auth-Email' => $this->_auth_entity->getID(), // 인증 토큰 사용
'X-Auth-Key' => $this->_auth_entity->getAuthKey(), // 인증 토큰 사용
'Content-Type' => 'application/json',
]
],
'verify' => false // SSL 인증서 검증을 비활성화
]);
}
if (self::$_request >= self::$_request_max) {
log_message('warning', sprintf("--Cloudflare API Call %s초 대기 시작--", self::$_request_timewait));
sleep(intval(getenv("cf.mgr.request.time.wait")));
sleep(intval(self::$_request_timewait));
self::$_request = 0;
log_message('warning', sprintf("--Cloudflare API Call %s초 대기 종료--", self::$_request_timewait));
}
@ -65,7 +70,7 @@ abstract class CloudflareSocket extends CommonLibrary
final protected function reload_procedure($uri): array
{
$page = 1; //Page는 1부터 시작해야함
$perpage_max = getenv("cfmgr.request.perpage.max");
$perpage_max = self::$_request_perpage_max;
$results = [];
do {
$query = [

View File

@ -29,6 +29,10 @@ class AccountModel extends CommonModel
public function getFieldRule(string $action, string $field): string
{
switch ($field) {
case self::PK:
$rule = "required|trim|alpha_numeric";
$rule .= $action == "create" ? "|is_unique[{$this->table}.{$field}]" : "";
break;
case self::PARENT:
$rule = "required|numeric";
break;
@ -54,7 +58,7 @@ class AccountModel extends CommonModel
}
return $options;
}
public function getEntityByPK(int $uid): null|AccountEntity
public function getEntityByPK(string $uid): null|AccountEntity
{
$this->where($this->getPKField(), $uid);
return $this->getEntity();

View File

@ -30,8 +30,12 @@ class RecordModel extends CommonModel
public function getFieldRule(string $action, string $field): string
{
switch ($field) {
case self::PK:
$rule = "required|trim|alpha_numeric";
$rule .= $action == "create" ? "|is_unique[{$this->table}.{$field}]" : "";
break;
case self::PARENT:
$rule = "required|regex_match[/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/]";
$rule = "required|trim|alpha_numeric";
break;
case self::TITLE:
case "content":
@ -65,7 +69,7 @@ class RecordModel extends CommonModel
}
return $options;
}
public function getEntityByPK(int $uid): null|RecordEntity
public function getEntityByPK(string $uid): null|RecordEntity
{
$this->where(self::PK, $uid);
return $this->getEntity();
@ -112,7 +116,7 @@ class RecordModel extends CommonModel
parent::setList_WordFilter($word, $field);
$this->orLike('content', $word, 'both');
}
public function setList_OrderBy(string $order = "")
public function setList_OrderBy(string $order = ""): void
{
//Join을 해서 도메인부터 Sorting하기위함
$this->join(ZoneModel::TABLE, sprintf(
@ -122,7 +126,7 @@ class RecordModel extends CommonModel
ZoneModel::TABLE,
ZoneModel::PK
));
$this->orderBy(ZoneModel::TABLE . ".domain ASC");
$this->orderBy(ZoneModel::TABLE . "." . ZoneModel::TITLE . " ASC ," . self::TITLE . " ASC");
parent::setList_OrderBy($order);
}
}

View File

@ -29,8 +29,12 @@ class ZoneModel extends CommonModel
public function getFieldRule(string $action, string $field): string
{
switch ($field) {
case self::PK:
$rule = "required|trim|alpha_numeric";
$rule .= $action == "create" ? "|is_unique[{$this->table}.{$field}]" : "";
break;
case self::PARENT:
$rule = "required|regex_match[/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/]";
$rule = "required|trim|alpha_numeric";
break;
case self::TITLE:
case "plan":
@ -44,6 +48,9 @@ class ZoneModel extends CommonModel
case "ipv6":
$rule = "if_exist|in_list[on,off]";
break;
case "status":
$rule = "if_exist|in_list[active,pending,moved]";
break;
default:
$rule = parent::getFieldRule($action, $field);
break;
@ -60,7 +67,7 @@ class ZoneModel extends CommonModel
}
return $options;
}
public function getEntityByPK(int $uid): null|ZoneEntity
public function getEntityByPK(string $uid): null|ZoneEntity
{
$this->where(self::PK, $uid);
return $this->getEntity();
@ -119,7 +126,7 @@ class ZoneModel extends CommonModel
AccountModel::TABLE,
AccountModel::PK
));
$this->orderBy(AccountModel::TABLE . ".title ASC");
$this->orderBy(AccountModel::TABLE . "." . AccountModel::TITLE . " ASC ," . self::TITLE . " ASC");
parent::setList_OrderBy($order);
}
}

View File

@ -236,10 +236,8 @@ abstract class CommonModel extends Model
$this->where("{$field} <= '{$end} 23:59:59'");
}
}
public function setList_OrderBy(string $order = "")
public function setList_OrderBy(string $order = ""): void
{
if ($order) {
$this->orderBy($order);
}
$this->orderBy($order ?: "{$this->getPKField()} DESC");
}
}

View File

@ -29,4 +29,5 @@
<?php endforeach ?>
</tbody>
</table>
<div class="index_pagination"><?= $viewDatas['pagination'] ?></div>
<?= $this->endSection() ?>

View File

@ -41,6 +41,8 @@ nav.index_top nav.pageinfo {
/* Table 부분 */
table.index_table {
width: 100%;
/* table-layout: fixed; 고정 레이아웃 */
border-collapse: collapse; /* 테두리 결합 */
}
table.index_table thead th {
@ -58,6 +60,8 @@ table.index_table thead th {
div.index_bottom {
padding-top: 15px;
text-align: center;
word-wrap: break-word; /* 긴 단어 강제 줄바꿈 */
white-space: normal; /* 자동 줄바꿈 */
/* border: 1px solid red; */
}
@ -116,6 +120,8 @@ table.action_form {
margin-right: auto;
/* 자동 여백을 이용한 가로 가운데 정렬 */
/* border: 1px solid blue; */
/* table-layout: fixed; 고정 레이아웃 */
border-collapse: collapse; /* 테두리 결합 */
}
table.action_form th {
@ -125,6 +131,8 @@ table.action_form th {
table.action_form td {
text-align: center;
word-wrap: break-word; /* 긴 단어 강제 줄바꿈 */
white-space: normal; /* 자동 줄바꿈 */
}
/* create,modify,view 페이지용 */

3
public/test.php Normal file
View File

@ -0,0 +1,3 @@
<?php
echo "현재시간:" . date("Y-m-d H:i:s");
echo phpinfo();