DolphinPHP 海豚PHP模块开发之接口改装

13 篇文章 0 订阅
6 篇文章 0 订阅

DophinPHP(海豚PHP)是一个基于ThinkPHP5.0.20开发的一套开源PHP快速开发框架,DophinPHP秉承极简、极速、极致的开发理念,为开发集成了基于数据-角色的权限管理机制,集成多种灵活快速构建工具,可方便快速扩展的模块、插件、钩子、数据包。统一了模块、插件、钩子、数据包之间的版本和依赖关系,进一步降低了代码和数据的冗余,以方便开发者快速构建自己的应用。

以上是官方介绍

海豚确实是非常好用的快速开发框架,模块化开发,插件扩展,自动构建器可以快速实现后台业务逻辑呈现而不必去纠结繁琐的html模板引擎样式等耗时间而不得不做的工作量,年初到现在一直在开发小程序后台和app的相关接口,最开始是直接使用home来做接口,接口需要做数据签名和验签,并且输出是json ,用来一段时间始终感觉不太方便,当一个模块后端,前台,接口都需要的时候就不太好规划目录,写在一起显得凌乱。为此我重新规划了一下接口的开发方式,其实也就是仿照admin.php的方式来做,下面就是具体的方法:

第一步

在public中复制admin.php 并修改为如下
 

<?php
	// +----------------------------------------------------------------------
	// | 海豚PHP框架 [ DolphinPHP ]
	// +----------------------------------------------------------------------
	// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
	// +----------------------------------------------------------------------
	// | 官方网站:http://dolphinphp.com
	// +----------------------------------------------------------------------
	// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
	// +----------------------------------------------------------------------
	// | 作者: 蔡伟明 <314013107@qq.com>
	// +----------------------------------------------------------------------

	// [ PHP版本检查 ]
	header("Content-type: text/html; charset=utf-8");
	if (version_compare(PHP_VERSION, '5.5', '<'))
	{
		die('PHP版本过低,最少需要PHP5.5,请升级PHP版本!');
	}

	// [ 应用入口文件 ]
	
	// 定义应用目录
	define('APP_PATH', __DIR__ . '/../application/');

	// 检查是否安装
	if (!is_file('../data/install.lock'))
	{
		define('BIND_MODULE', 'install');
	}

	// 定义入口为api
	define('ENTRANCE', 'api');

	// +----------------------------------------------------------------------
	// | 后台默认为关闭路由
	// | 如果需要开启路由功能,请注释下面三句
	// +----------------------------------------------------------------------
	// 加载框架基础文件
	require '../thinkphp/base.php';

	// 关闭路由
	\think\App::route(false);

	// 执行应用
	\think\App::run()->send();

	// +----------------------------------------------------------------------
	// | 默认为关闭路由
	// | 如果需要开启路由,请取消以下注释
	// +----------------------------------------------------------------------
	// 加载框架引导文件
	// require './thinkphp/start.php';

其实就是 修改了一下这里      define('ENTRANCE', 'api');  admin 改为了api后面会用到。

第二步 修改behavior

打开并修改 application/common/behavior/Config.php 文件

 

<?php
// +----------------------------------------------------------------------
// | 海豚PHP框架 [ DolphinPHP ]
// +----------------------------------------------------------------------
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
// +----------------------------------------------------------------------
// | 官方网站: http://dolphinphp.com
// +----------------------------------------------------------------------
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------

	namespace app\common\behavior;

	use app\admin\model\Config as ConfigModel;
	use app\admin\model\Module as ModuleModel;

	/**
	 * 初始化配置信息行为
	 * 将系统配置信息合并到本地配置
	 * @package app\common\behavior
	 * @author CaiWeiMing <314013107@qq.com>
	 */
	class Config
	{
		/**
		 * 执行行为 run方法是Behavior唯一的接口
		 * @access public
		 * @param mixed $params 行为参数
		 * @return void
		 */
		public function run(&$params)
		{
			// 如果是安装操作,直接返回
			if (defined('BIND_MODULE') && BIND_MODULE === 'install')
				return;

			// 获取当前模块名称
			$module = '';
			$dispatch = request()->dispatch();
			if (isset($dispatch['module']))
			{
				$module = $dispatch['module'][0];
			}

			// 获取入口目录
			$base_file = request()->baseFile();
			$base_dir = substr($base_file, 0, strripos($base_file, '/') + 1);
			define('PUBLIC_PATH', $base_dir);

			// 视图输出字符串内容替换
			$view_replace_str = [
				// 静态资源目录
				'__STATIC__'      => PUBLIC_PATH . 'static',
				// 文件上传目录
				'__UPLOADS__'     => PUBLIC_PATH . 'uploads',
				// JS插件目录
				'__LIBS__'        => PUBLIC_PATH . 'static/libs',
				// 后台CSS目录
				'__ADMIN_CSS__'   => PUBLIC_PATH . 'static/admin/css',
				// 后台JS目录
				'__ADMIN_JS__'    => PUBLIC_PATH . 'static/admin/js',
				// 后台IMG目录
				'__ADMIN_IMG__'   => PUBLIC_PATH . 'static/admin/img',
				// 前台CSS目录
				'__HOME_CSS__'    => PUBLIC_PATH . 'static/home/css',
				// 前台JS目录
				'__HOME_JS__'     => PUBLIC_PATH . 'static/home/js',
				// 前台IMG目录
				'__HOME_IMG__'    => PUBLIC_PATH . 'static/home/img',
				// 表单项扩展目录
				'__EXTEND_FORM__' => PUBLIC_PATH . 'extend/form'
			];
			config('view_replace_str', $view_replace_str);

			// 如果定义了入口为admin,则修改默认的访问控制器层
			if (defined('ENTRANCE') && ENTRANCE == 'admin')
			{
				define('ADMIN_FILE', substr($base_file, strripos($base_file, '/') + 1));

				if ($dispatch['type'] == 'module' && $module == '')
				{
					header("Location: " . $base_file . '/admin', true, 302);
					exit();
				}

				if ($module != '' && !in_array($module, config('module.default_controller_layer')))
				{
					// 修改默认访问控制器层
					config('url_controller_layer', 'admin');
					// 修改视图模板路径
					config('template.view_path', APP_PATH . $module . '/view/admin/');
				}

				// 插件静态资源目录
				config('view_replace_str.__PLUGINS__', '/plugins');
			} elseif (defined('ENTRANCE') && ENTRANCE == 'api')
			{
				config('default_return_type', 'json');


				define('API_FILE', substr($base_file, strripos($base_file, '/') + 1));

				if ($dispatch['type'] == 'module' && $module == '')
				{
					header("Location: " . $base_file . '/api', true, 302);
					exit();
				}

				if ($module != '' && !in_array($module, config('module.default_controller_layer')))
				{
					// 修改默认访问控制器层
					config('url_controller_layer', 'api');
				}

				// 插件静态资源目录
				config('view_replace_str.__PLUGINS__', '/plugins');
			} else
			{
				if ($dispatch['type'] == 'module' && $module == 'admin')
				{
					header("Location: " . $base_dir . ADMIN_FILE . '/admin', true, 302);
					exit();
				}
				if ($dispatch['type'] == 'module' && $module == 'api')
				{
					header("Location: " . $base_dir . API_FILE . '/api', true, 302);
					exit();
				}

				if ($module != '' && !in_array($module, config('module.default_controller_layer')))
				{
					// 修改默认访问控制器层
					config('url_controller_layer', 'home');
				}
			}

			// 定义模块资源目录
			config('view_replace_str.__MODULE_CSS__', PUBLIC_PATH . 'static/' . $module . '/css');
			config('view_replace_str.__MODULE_JS__', PUBLIC_PATH . 'static/' . $module . '/js');
			config('view_replace_str.__MODULE_IMG__', PUBLIC_PATH . 'static/' . $module . '/img');
			config('view_replace_str.__MODULE_LIBS__', PUBLIC_PATH . 'static/' . $module . '/libs');
			// 静态文件目录
			config('public_static_path', PUBLIC_PATH . 'static/');

			// 读取系统配置
			$system_config = cache('system_config');
			if (!$system_config)
			{
				$ConfigModel = new ConfigModel();
				$system_config = $ConfigModel->getConfig();
				// 所有模型配置
				$module_config = ModuleModel::where('config', 'neq', '')->column('config', 'name');
				foreach ($module_config as $module_name => $config)
				{
					$system_config[strtolower($module_name) . '_config'] = json_decode($config, true);
				}
				// 非开发模式,缓存系统配置
				if ($system_config['develop_mode'] == 0)
				{
					cache('system_config', $system_config);
				}
			}

			// 设置配置信息
			config($system_config);
		}
	}

这里多添加了一个判断是否为api 第一步中提到的 。是api就把请求路由改为当前模块下面的api目录,这也就达到了独立出api目录的方式,前提是请求的时候必须为 api.php/XXX/XXX/XXX 的请求方式。上面是把目录给区分开了,但是API还有很多基础工作需要做 比如数据合法性检查,输出json格式数据,Exception 输出为json 这写都是需要处理的。那就请您接着往下看(这人废话特别多!)。

第三步 创建API公共控制器,在公共控制器中可以做其他处理

<?php
	/**
	 * Created by PhpStorm.
	 * User: mybook-lhp
	 * Date: 18/7/2
	 * Time: 下午3:39
	 */

	namespace app\common\controller;

	use app\common\traits\apiinit;
	use think\Controller;

	class API extends Controller
	{
		use apiinit;

	 
	}

 第四步 数据输出

<?php
 
	namespace app\common\traits;

	use think\Cache;
	use think\Config;
	use think\Db;
	use think\exception\HttpResponseException;
	use think\Log;
	use think\Request;
	use think\Response;
	use think\response\Redirect;
	use think\Url;
	use think\View as ViewTemplate;

	trait apiinit
	{
		//数据集合!
		protected $_initialize = [];

		/**
		 * 存储数据到数据集
		 * @param mixed $name
		 * @param string $value
		 */
		protected function assign($name, $value = '')
		{
			$this->_initialize[$name] = $value;
			return $this;
		}

		/**
		 * 输出数据
		 * @param string $template
		 * @param array $vars
		 * @param array $replace
		 * @param array $config
		 * @return mixed|void
		 */
		protected function fetch($template = '', $vars = [], $replace = [], $config = [])
		{
			if ($template !== '')
			{
				$this->_initialize['template'] = $template;
			}


			$this->result($this->_initialize, 200, $msg = '', $type = 'json');
		}

		/**
		 * 操作错误跳转的快捷方法
		 * @param string $msg
		 */
		protected function error($msg = 'error', $url = null, $data = '', $wait = 3, array $header = [])
		{
			$this->result($data, 500, $msg, 'json');
		}

		/**
		 * 操作成功跳转的快捷方法
		 * @param string $msg
		 */
		protected function success($msg = 'success', $url = null, $data = '', $wait = 3, array $header = [])
		{

			$this->result($data, 200, $msg, 'json');
		}

		/**
		 * 返回封装后的 API 数据到客户端
		 * @access protected
		 * @param mixed $data 要返回的数据
		 * @param int $code 返回的 code
		 * @param mixed $msg 提示信息
		 * @param string $type 返回数据格式
		 * @param array $header 发送的 Header 信息
		 * @return void
		 * @throws HttpResponseException
		 */
		protected function result($data = [], $code = 200, $msg = 'success', $type = 'json', array $header = [])
		{
			Log::result(json_encode(['titile' => '日志', 'msg' => $msg, '']));
			$result = [
				'code' => $code,
				'msg'  => $msg,
				'time' => Request::instance()->server('REQUEST_TIME'),
				'data' => $data,
			];

			if (Config::get('app_debug'))
			{
				$result['debug'] = static::getLog();
			}

			//$type = $type ?: Config::get('default_return_type');
			$response = Response::create($result, $type)->header($header);

			throw new HttpResponseException($response);
		}

		static public function getLog()
		{
			return	$Log_sql = \think\Log::getLog();
		}

	}

此文件是将系统中的几个方法处理为json输出,方便接口调用和判断数据状态

 

第五步 Exception 处理  

修改配置文件 config.php   别照抄,看清楚哦!

 

<?php

	$Config = [
		//........
	];
	if (defined('ENTRANCE') && ENTRANCE == 'api')
	{
		// +----------------------------------------------------------------------
		// | 异常及错误设置
		// +----------------------------------------------------------------------

		// 异常页面的模板文件
		$Config['exception_tmpl'] = THINK_PATH . 'tpl' . DS . 'think_exception.tpl';

		// 错误显示信息,非调试模式有效
		$Config['error_message'] = '页面错误!请稍后再试~';
		// 显示错误信息
		$Config['show_error_msg'] = false;
		// 异常处理handle类 留空使用 \think\exception\Handle
		$Config['exception_handle'] = 'app\common\exce\JsonHandle';

	}

	return $Config;

以下为Exception处理 上面的配置文件中 exception_handle 指向JsonException.php

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------

	namespace app\common\exce;

	use Exception;
	use think\App;
	use think\Config;
	use think\console\Output;
	use think\exception\Handle;
	use think\exception\HttpException;
	use think\exception\HttpResponseException;
	use think\Lang;
	use think\Log;
	use think\Response;

	class JsonHandle extends Handle
	{
		protected $render;
		protected $ignoreReport = [
			'\\think\\exception\\HttpException',
		];

		public function setRender($render)
		{
			$this->render = $render;
		}

		/**
		 * Report or log an exception.
		 *
		 * @param  \Exception $exception
		 * @return void
		 */
		public function report(Exception $exception)
		{
			if (!$this->isIgnoreReport($exception))
			{
				// 收集异常数据
				if (App::$debug)
				{
					$data = [
						'file'    => $exception->getFile(),
						'line'    => $exception->getLine(),
						'message' => $this->getMessage($exception),
						'code'    => $this->getCode($exception),
					];
					$log = "[{$data['code']}]{$data['message']}[{$data['file']}:{$data['line']}]";
				} else
				{
					$data = [
						'code'    => $this->getCode($exception),
						'message' => $this->getMessage($exception),
					];
					$log = "[{$data['code']}]{$data['message']}";
				}

				if (Config::get('record_trace'))
				{
					$log .= "\r\n" . $exception->getTraceAsString();
				}

				Log::record($log, 'error');
			}
		}

		protected function isIgnoreReport(Exception $exception)
		{
			foreach ($this->ignoreReport as $class)
			{
				if ($exception instanceof $class)
				{
					return true;
				}
			}
			return false;
		}

		/**
		 * Render an exception into an HTTP response.
		 *
		 * @param  \Exception $e
		 * @return Response
		 */
		public function render(Exception $e)
		{
			if ($this->render && $this->render instanceof \Closure)
			{
				$result = call_user_func_array($this->render, [$e]);
				if ($result)
				{
					return $result;
				}
			}

			if ($e instanceof HttpException)
			{
				return $this->renderHttpException($e);
			} else
			{
				return $this->convertExceptionToResponse($e);
			}
		}

		/**
		 * @param Output $output
		 * @param Exception $e
		 */
		public function renderForConsole(Output $output, Exception $e)
		{
			if (App::$debug)
			{
				$output->setVerbosity(Output::VERBOSITY_DEBUG);
			}
			$output->renderException($e);
		}

		/**
		 * @param HttpException $e
		 * @return Response
		 */
		protected function renderHttpException(HttpException $e)
		{
			$status = $e->getStatusCode();
			$template = Config::get('http_exception_template');
			if (!App::$debug && !empty($template[$status]))
			{
				return Response::create($template[$status], 'view', $status)->assign(['e' => $e]);
			} else
			{
				return $this->convertExceptionToResponse($e);
			}
		}

		/**
		 * @param Exception $exception
		 * @return Response
		 */
		protected function convertExceptionToResponse(Exception $exception)
		{
			// 收集异常数据
			if (App::$debug)
			{
				// 调试模式,获取详细的错误信息
				$data = [
					'name'    => get_class($exception),
					'file'    => $exception->getFile(),
					'line'    => $exception->getLine(),
					'message' => $this->getMessage($exception),
					'trace'   => $exception->getTrace(),
					'code'    => $this->getCode($exception),
					'source'  => $this->getSourceCode($exception),
					'datas'   => $this->getExtendData($exception),
					'tables'  => [
						'GET Data'              => $_GET,
						'POST Data'             => $_POST,
						'Files'                 => $_FILES,
						'Cookies'               => $_COOKIE,
						'Session'               => isset($_SESSION) ? $_SESSION : [],
						'Server/Request Data'   => $_SERVER,
						'Environment Variables' => $_ENV,
						'ThinkPHP Constants'    => $this->getConst(),
					],
				];
			} else
			{
				// 部署模式仅显示 Code 和 Message
				$data = [
					'code'    => $this->getCode($exception),
					'message' => $this->getMessage($exception),
				];

				if (!Config::get('show_error_msg'))
				{
					// 不显示详细错误信息
					$data['message'] = Config::get('error_message');
				}
			}


			$data['echo'] = ob_get_clean();
			$response = Response::create($data, 'json');
			if ($exception instanceof HttpException)
			{
				$statusCode = $exception->getStatusCode();
				$response->header($exception->getHeaders());
			}

			if (!isset($statusCode))
			{
				$statusCode = 500;
			}
			$response->code($statusCode);
			return $response;
		}

		/**
		 * 获取错误编码
		 * ErrorException则使用错误级别作为错误编码
		 * @param  \Exception $exception
		 * @return integer                错误编码
		 */
		protected function getCode(Exception $exception)
		{
			$code = $exception->getCode();
			if (!$code && $exception instanceof ErrorException)
			{
				$code = $exception->getSeverity();
			}
			return $code;
		}

		/**
		 * 获取错误信息
		 * ErrorException则使用错误级别作为错误编码
		 * @param  \Exception $exception
		 * @return string                错误信息
		 */
		protected function getMessage(Exception $exception)
		{
			$message = $exception->getMessage();
			if (IS_CLI)
			{
				return $message;
			}

			if (strpos($message, ':'))
			{
				$name = strstr($message, ':', true);
				$message = Lang::has($name) ? Lang::get($name) . strstr($message, ':') : $message;
			} elseif (strpos($message, ','))
			{
				$name = strstr($message, ',', true);
				$message = Lang::has($name) ? Lang::get($name) . ':' . substr(strstr($message, ','), 1) : $message;
			} elseif (Lang::has($message))
			{
				$message = Lang::get($message);
			}
			return $message;
		}

		/**
		 * 获取出错文件内容
		 * 获取错误的前9行和后9行
		 * @param  \Exception $exception
		 * @return array                 错误文件内容
		 */
		protected function getSourceCode(Exception $exception)
		{
			// 读取前9行和后9行
			$line = $exception->getLine();
			$first = ($line - 9 > 0) ? $line - 9 : 1;

			try
			{
				$contents = file($exception->getFile());
				$source = [
					'first'  => $first,
					'source' => array_slice($contents, $first - 1, 19),
				];
			} catch (Exception $e)
			{
				$source = [];
			}
			return $source;
		}

		/**
		 * 获取异常扩展信息
		 * 用于非调试模式html返回类型显示
		 * @param  \Exception $exception
		 * @return array                 异常类定义的扩展数据
		 */
		protected function getExtendData(Exception $exception)
		{
			$data = [];
			if ($exception instanceof \think\Exception)
			{
				$data = $exception->getData();
			}
			return $data;
		}

		/**
		 * 获取常量列表
		 * @return array 常量列表
		 */
		private static function getConst()
		{
			return get_defined_constants(true)['user'];
		}
	}

 

下载地址 https://download.csdn.net/download/dragonlhp/10566382

自此完整的api模块开发就完成了,其中存在问题,各位可以留言或自行解决!

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DophinPHP海豚PHP)是一个基于ThinkPHP5.0.3开发的开源PHP快速开发框架,秉承极简、极速、极致的开发理念,为开发集成了基于数据-角色的权限管理机制,集成多种灵活快速构建工具,可方便快速扩展的模块、插件、钩子、数据包。统一了模块、插件、钩子、数据包之间的版本和依赖关系,进一步降低了代码和数据的沉余,以方便开发者快速构建自己的应用。 ZBuilder构建类 DolphinPHP内置了强大的快速构建器,可以帮助开发者快速构建表单页面、数据表格和侧栏,以便让开发者专注于业务逻辑,而不用把过多的精力放在制作各种页面上,今后DolphinPHP将推出更多不同的构建器。 【表单构建】 表单构建器目前内置了多达30几种表单项类型,比如:单行文本、多行文本、百度编辑器、markdown编辑器、单选、多选、开关、联动、取色器、图标选择器、图片裁剪等等,只需几行代码,即可实现复杂且人性化的功能。 【数据表格】 为了让开发者专注于业务本身,DolphinPHP提供了一系列针对构建数据表格的方法,可以帮助开发者快速构建数据表格,集成快速编辑、模糊搜索、字段排序、字段搜索。 【侧栏构建】 DolphinPHP为大家提供了侧栏构建器,方便开发者把一些常用的设置,提示等放置在右侧,增强用户体验。 注意:软件需在php5.5以上的环境中才能正常运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值