داۋاملاشتۇرايلى ، رامكا ئاساسلىق ئىككى چوڭ مۇلازىمەت تەمىنلەيدۇ web
ۋە api
، بىز مۇشۇنىڭغا ئاساسان مۇلازىمەتنى ئىككى ئايرايلى ۋە بەزىبىر تەڭشەك فونكىسيەلەرنى يېزىپ چىقايلى .
<?php namespace System;
/**
* Implcms Main Class
*/
class Cms{
/**
* 启动CMS服务
*/
public function service(){
$this->register();
//如果有api参数则启动接口服务,否则启动网页服务
if(input("api")){
\Api::service();
}else{
\Web::service();
}
}
/**
* 初始化系统配置
*/
private function register(){
$this->registerAlias();
$this->registerOptions();
}
/**
* 注册类别名
*/
private function registerAlias(){
$alias = [
"Api"=>"System\Services\ApiService",
"Log"=>"System\Services\LogService",
"Web"=>"System\Services\WebService",
"Response"=>"System\Services\ResponseService",
"SystemException"=>"System\Exceptions\SystemException",
];
if(is_array($alias)){
foreach ($alias as $key => $value) {
class_alias($value,$key);
}
}
}
/**
* 注册PHP设置,错误处理函数和时区
*/
private function registerOptions(){
date_default_timezone_set('Asia/Shanghai');
set_exception_handler([new \SystemException,"exception"]);
set_error_handler([new \SystemException,"error"]);
}
}
ئۈسىتىدە بىز class_alias
فونكىسىيەسى ئارقىلىق بىز دائىم ئىشلىتىدغان كىلاسلارنىڭ ئىسمىنى قىسقارتىپ يېزىۋالدۇق . بۇندا قىسقارتقاندىن كىيىن بىز \Api
دىسەكلا System\Services\ApiService
نى ئىشلىتەلەيمىز . ئەمدى بىز بۇ كىلاسلارنى بىردىن يېزىپ چىقايلى .
System\Services\ApiService.php
<?php namespace System\Services;
/**
* 接口
*/
class ApiService
{
//接口所有参数
private $param;
//接口名称
private $api;
//接口所在的应用
private $app;
//接口所在的控制器
private $controller;
//接口方法
private $method;
public function __construct($param){
if(!isset($param['api'])){
throw new \Exception(t("接口好像有点问题,正确格式: app@controller.method")."\n\n".print_r($param,"r")."\n\n");
}
$apiSection = explode(".", $param["api"]);
if(count($apiSection) != 2){
throw new \Exception(t("接口好像有点问题,正确格式: app@controller.method")."\n\n".print_r($param,"r")."\n\n");
}
$appSection = explode("@", $apiSection[0]);
if(count($appSection) != 2){
throw new \Exception(t("接口好像有点问题,正确格式: app@controller.method")."\n\n".print_r($param,"r")."\n\n");
}
$this->param = $param;
$this->api = $param['api'];
$this->app = $appSection[0];
$this->controller = $appSection[1];
$this->method = $apiSection[1];
}
/**
* 接口服务,通过HTTP请求访问
*/
public static function service(){
$apiService = new self(input());
$data = $apiService->call();
return \Response::json($data);
}
/**
* 接口服务,系统内部调用
*/
public static function get($api,$param){
$param["api"] = $api;
$apiService = new self($param);
$data = $apiService->call();
return $data;
}
/**
* 执行函数
*/
private function call(){
//设置控制器
if($this->app === "system"){
$controllerName = "\\System\\Controllers\\".str2Class($this->controller)."Controller";
}else{
$controllerName = "\\Applications\\".str2Class($this->app)."\\Controllers\\".str2Class($this->controller)."Controller";
}
//如果接口所在的控制器不存在,那么看做是系统父级模型控制器
if(!class_exists($controllerName)){
$controllerName = "\\System\\Controllers\\ModelController";
}
//方法添加api前缀,也就是控制器内只有api开头的方法才能被对完访问
$method = str2Method("api-".$this->method);
$controller = new $controllerName($this->param);
if(method_exists($controller,$method)){
try {
$data = $controller->$method($this->param);
} catch (\Exception $e) {
\Log::error($e->getMessage());
throw new \Exception(t("调用接口出现异常:").$e->getMessage(),1);
}
}else{
throw new \Exception(t("方法没有找到")."\n\nClass: ".$controllerName."\nMethod: ".$method."\n\n",1);
}
return $data;
}
}
ئۈستدىكىسى بىزنىڭ مۇھىم كىلاسلاردىن بىرسى ، يەنە بىز مەلۇم بىر بۇيرۇقنى دىسەك بىزگە مۇشۇ بۇيرۇقنىڭ نەتىجىسىنى كۆرسىتىپ بىرىدىغان كىلاس .
مەسلەن : بىز بۇنىڭغا بىر كىلو گۆش ئېلىپ كەل دىسەك ئېلىپ كېلىدۇ ، ئىككى كىلو پەمىدۇر دېسەكمۇ ئېلىپ كېلىدۇ .
ئۇنداق بولسا بىز بۇ بۇيرۇقنى بىرلىككە ئەكىلىۋالايلى .
app@controller.method
يەنى قايسى ئەپ ، بۇ ئەپتىكى قايسى كونتىروللىغۇچ ۋە قايسى فونكىسىيە .
مەسلەن :
music@song.one
ماڭا بىر تال ناخشا بەرگىن . (ئەلۋەتتە مەن ھەرخىل شەرىتلەرنى سۇنسام بۇلىدۇ)
system@cms.clear-cache
سىستېمنىڭ غەملەكنى تازلىۋەتكىن .
movie@movie.attach
كىنوغا بىرتال مۇناسىۋەت قېتىۋەتكىن .( قانداق مۇناسىۋەلىكىنى سۇنىمىز ، مەسلەن ، ئابۇنىت ياقتۇردى ، ئابۇنىت نۇمۇرى قويدى ...)
ئەمدى LogService
نى يازايلى
System\Services\LogService.php
<?php namespace System\Services;
/**
* 日志服务
*/
class LogService
{
/**
* 消息日志
*/
public static function info($str){
self::write($str,"INFO");
}
/**
* 错误日志
*/
public static function error($str){
self::write($str,"ERROR");
}
/**
* 通知
*/
public static function notice($str){
self::write($str,"NOTICE");
}
/**
* 日志写在日志文件里
*/
private static function write($str,$type){
if(!is_string($str)){
$str = json_encode($str);
}
$log_str = date('Y-m-d H:i:s')." ".$type.": ".$str;
file_put_contents(base_dir('storage').'logs/implcms.log', $log_str.PHP_EOL , FILE_APPEND | LOCK_EX);
}
}
خاتىرە كىلاس بولسا بەزىبىر خاتالىق ئۇچۇرلىرى ، ئەسكەرتىش ئۇچۇرلىنى خاتىرلەيدىغان كىلاس ، مەسلەن بىز سىناق قىلغان چاغدا بەزى ئۇچۇرلارنى Log::info
ئارقىلىق ئۇرۇپ ئاندىن تېرمىنالدا tailf implcms.log
قىلىپ كۆرسەك بۇلىدۇ .
System\Services\WebService.php
<?php namespace System\Services;
/**
* 网页服务
*/
class WebService
{
/**
* 静态处理器
*/
public static function service(){
\Response::html("<h1>WebService</h1>");
}
}
بۇ كىلاس بولسا بىزگە توربەت مۇلازىمتى تەمىن ئېتىدۇ . تەپسىلاتىنى كىيىنكى سانلاردا داۋاملىق يازىمىز .
System\Services\ResponseService.php
<?php namespace System\Services;
/**
* 响应
*/
class ResponseService{
/**
* 输出HTML
*/
public static function html($html){
header('Content-Type: text/html; charset=utf-8');
echo $html;exit();
}
/**
* 输出Json
*/
public static function json($data){
header('Content-Type: application/json');
echo json_encode($data);exit();
}
/**
* 跳转
*/
public static function redirect($url){
if(!filter_var($url, FILTER_VALIDATE_URL)){
$url = url($url);
}
header("Location:".$url,true,301);exit();
}
}
بۇ كىلاس بولسا مەزمۇن چىقىرىشقا مەسئۇل بۇلىدۇ . مەسلەن : json
چىقىرىش ، توربەت html
چىقىرىش ۋە ياكى باشقا بىر ئادرىسقا ئاتلىتىش دېگەندەك
System\Exceptions\SystemException.php
<?php namespace System\Exceptions;
/**
* 错误处理
*/
class SystemException extends \Exception
{
public function exception($e){
\Log::info("\nError:".$e->getMessage()."\nFile:".$e->getFile()."[".$e->getLine()."]");
header("HTTP/1.0 500 Internal Server Error");
$error["exception"] = "SystemException";
$error["error"] = $e->getMessage();
$error["e"] = explode(PHP_EOL,$e."");
\Response::html('<pre><h2>'.$error["exception"].'</h2></pre><pre>'.$e.'</pre>');
}
public function error($errno, $errstr, $errfile, $errline){
switch ($errno) {
case E_USER_ERROR:
case E_USER_WARNING:
\Log::error($errstr."\n".$errline."\n".$errfile);
break;
default:
# code...
break;
}
}
}
خاتالىق مۇلازىمتى بولسا كود ئىجرا بولغاندا چىققان خاتالىقنى بىزنىڭ تىز سۈرەتتە تېپىشىمىغا ياردم بىرىدۇ .
ئۈستىدا بىر نەچچە ياردەمچى فونكىسىيەلەرنى ئىشلەتتتۇق . مەسلەن :
input
str2Class
str2Method
base_dir
url
ئەمدى بىز ياردەمچى فونكىسيەلەرنى يېزىپ چىقايلى .
system/helpers.php
<?php
/**
* 获取参数,支持GET,POST,Body(json)
*/
if (!function_exists('input')) {
function input($key = null){
$value = null;
$param = [];
if($key === null){
foreach ($_POST as $key => $value) {
$param[$key] = $value;
}
foreach ($_GET as $key => $value) {
$param[$key] = $value;
}
$rawpostdata = file_get_contents("php://input");
$rawpostdata = json_decode($rawpostdata,true);
if(is_array($rawpostdata)){
foreach ($rawpostdata as $key => $value) {
$param[$key] = $value;
}
}
$value = $param;
}else{
if(isset($_POST[$key])){
$value = $_POST[$key];
}else if(isset($_GET[$key])){
$value = $_GET[$key];
}else{
$rawpostdata = file_get_contents("php://input");
$rawpostdata = json_decode($rawpostdata,true);
if(isset($rawpostdata[$key])){
$value = $rawpostdata[$key];
}
}
}
if(empty($value)){
return null;
}
return $value;
}
}
/**
* 字符串转换成标准方法名称
*/
if (!function_exists('str2Method')) {
function str2Method($str){
$str = ucwords($str, "-");
$str = str_replace("-","",$str);
$str = lcfirst($str);
return $str;
}
}
/**
* 字符串转换成标准类名称
*/
if (!function_exists('str2Class')) {
function str2Class($str){
$str = ucwords($str, "-");
$str = str_replace("-","",$str);
$str = ucfirst($str);
return $str;
}
}
/**
* 获取系统各种目录
*/
if (!function_exists('base_dir')) {
function base_dir($module = null){
$base = dirname(__DIR__,1)."/";
switch ($module) {
case 'storage':
return $base."storage/";
break;
case 'system':
return $base."system/";
break;
case 'app':
return $base."applications/";
break;
case 'cache':
return $base."storage/cache/";
break;
case 'config':
return $base."storage/config/";
break;
case 'log':
return $base."storage/logs/";
break;
case 'tmp':
if(!is_dir($base."storage/tmp")){
mkdir($base."storage/tmp");
}
return $base."storage/tmp/";
break;
default:
$dir = $base.$module;
rtrim($dir, "/");
return $dir."/";
break;
}
}
}
/**
* URL生成器
*/
if (!function_exists('url')) {
function url($param = null){
$host = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]";
if(php_sapi_name() === 'cli'){
$host = config("cms.base_url");
}
switch ($param) {
case 'host':
return $host;
break;
case 'path':
return $host.strtok($_SERVER['REQUEST_URI'],"?");
break;
case '#':
return 'javascript:;';
break;
case null:
return $host.$_SERVER['REQUEST_URI'];
break;
case 'referer':
return isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:url();
break;
default:
return $host."/".$param;
break;
}
}
}
ئەمدى بىز بۇ فونكىسىيەنى قانداق ئىشلىتىمىز ؟ بىز يېزىۋالغان autoload.php
ھەممىزنىڭ ئىسىدە بولسا كېرەك ، بىز بۇ ھۆججەتنى ئېسىپ قويساقلار بولدى .
ئەمىسە گىتقا بىر نۇسقا يوللىۋېتەي .
كود ئادرىسى : ئادرىس