1160
一、登录所用到组件1、视图模板:安装:composer require topthink/think-view2、验证码:安装:composer require topthink/think-captcha3、session:需要开启session:打开app下的middeware.php文件,内部有个全局中间件 ,最后一行去掉注释即可。准备基本完毕,手动开启教程。二、前台搭建(layui框架)2.1、你得先获取layui,去layui官网下载或者百度搜一下layui 的cdn2.2、引入,我是放在tp6>public>static文件夹下。如图2-1.图2-1 layui所在文件夹图2.3:登录界面:界面图如2-2;图2-2:登录界面图代码如下所示:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/layui/css/layui.css"></head><body><div class="layui-container"> <div class="layui-row"> <div class="layui-col-md4 layui-col-md-offset4" style="margin-top: 100px; box-shadow: 2px 2px 5px #ccc"> <div style="height: 80px; text-align: center; font-size:30px; ">后台登录</div> <form class="layui-form layui-form-pane" action=""> <div class="layui-form-item" pane> <label class="layui-form-label">用户名</label> <div class="layui-input-block"> <input type="text" name="name" required lay-verify="required" placeholder="请输入标题" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <label class="layui-form-label">密码</label> <div class="layui-input-block"> <input type="password" name="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item" pane> <label class="layui-form-label">验证码</label> <div class="layui-input-inline"> <input type="text" name="yzm" style="width:60%" required lay-verify="required" placeholder="请输入验证码" autocomplete="off" class="layui-input"> <div style="display: inline" class="layui-form-mid layui-word-aux"><img id='captcha' style="display: inline" src="{:captcha_src()}" alt="captcha" /></div> </div> </div> <div class="layui-form-item"> <div class="layui-input-block"> <input type="button" class="layui-btn" lay-submit lay-filter="formDemo" value="立即提交"></input> <button type="reset" class="layui-btn layui-btn-primary">重置</button> </div> </div> </form> </div> </div> <script src="/static/layui/layui.all.js"></script><script> //只需要引入layui.all.js就ok //这里我们需要用到form表单,jquery的ajax提交,layui的弹弹窗 //所以需要引用,下面数组就是引入的组件。 layui.use(['form', 'jquery', 'layer'], function(){ var form = layui.form; var $ = layui.jquery; //上两行就是引用form 和$ ,下面需要用到 //监听表单提交,获取表单信息:submit(formDemo)数据对应这个lay-filter="formDemo" form.on('submit(formDemo)', function(data){ //从表单中获取相应数据 var name = data.field.name; var password = data.field.password; var yzm = data.field.yzm; $.ajax({ url:"userLogin",//请求地址,当前在admin/user/userLogin下,提交给当前方法即可 data: {//发送给服务器的数据 'name':name, 'password':password, 'yzm':yzm }, type:"Post",//提交方式 dataType:"json", success:function(data){//成功回调 if(data.status==0){//登录失败,status后台自定义状态码 layer.msg(data.msg);//layer自带的弹窗,msg后台自定义消息, \\emm 就是最开始layui.use中引用的layer,不然这里没法使用。 }else{//登录成功 msg后台自定义消息 layer.msg(data.msg); //行吧,这里是自定义跳转,登录成功过后直接跳到主页 window.location.href = "{:url('admin/index/index')}" } return false; }, error:function(data){ console.log('==错误信息=='); return false; } }); return false; }); //提交数据结束 // 验证码刷新,,通过jquery获取图片dom,并实现点击功能。 $("#captcha").click(function(event){ // jqery中获取id是上面这样的,如果是获取class就是 $(".captcha") // 当然我这里不涉及类名。 console.log('我被点击了');控制台输出这鬼东西被点击了没有 console.log(event); //给当前图片的src换一个新的url,后面带上一个随机数。 //虽然我还不知道原理, //但是这样就能让验证码刷新, //请求tp6这个captcha_src()方法,如果不加后面那串估计后台认为 //什么也不给你请求个锤子,原来那个给你 this.src = "{:captcha_src()}?"+Math.random(); console.log(this.src);//我打印了一下值得变化,事实上只有后面随机数变了 }) });</script> </body></html>前台代码基本上是这样:验证码哪一行有毛病,我不想解决。三、后台逻辑实现。需要用到一张数据表:我这是admin表,包含了以下字段如图3-1图3-1 数据库设计表其实登录 不需要group_id last_login_time 等字段。这里我是有其他功能要实现。如果我开心过两天发张博客。我没用模型,你也可以用模型:这里我建立一个模型吧:admin模型如下:创建模型命令php think make:mode admin@UserModel我这里开启了多应用模式,admin是我的应用,如果你没有使用多应用模式,把admin@去掉,当然,你也可以手动创建哈。得到以下模型::图3-2图3-2 模型位置图:UserModel模型代码:123456789101112131415161718192021222324252627282930<?phpdeclare (strict_types = 1);namespace app\admin\model;use think\Model; class UserModel extends Model{ //绑定主键 protected $pk = 'id'; //绑定表 表名 protected $table='msg_admin'; //开启自动时间戳 protected $autoWriteTimestamp =true; // 设置字段信息。。虽然可以不用,但文档说可以减少一次查询,还是用吧 protected $schema = [ 'id' => 'int', 'name' => 'string', 'password' => 'string', 'status' => 'tinyint', 'group_id' => 'int', 'create_time' => 'datetime', 'update_time' => 'datetime', 'last_login_time' => 'datetime', ]; // 模型初始化 protected static function init() { //TODO:初始化内容 }}对:在这之前你去要配置一下ENV变量,能链接数据库::自己去配置吧。3-2:登录逻辑及代码::第一步:检查session是否存在用户,存在直接跳到后台,否则就执行下一步第二步:检查是不是post请求,如果是执行登录操作:不是渲染视图,将登录界面返回给用户;第三步:登录中:获取用户传入数据,检查是否为空,(验证数据:我没写验证,懒);根据用户用户名查找用户信息,匹配密码,写入session,完成登录代码如下:::1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677<?phpnamespace app\admin\controller;use app\BaseController;use think\facade\Db;use think\Request;use app\validate\UserValidate;use think\facade\View;use think\facade\session; class User extends BaseController{ protected $request; /** * 检查用户登录 * 有登录提交时,进入登录功能,没有登录请求返回页面 * 获取用户信息 校验 查询数据库 * @param Request $request * @return string|\think\response\Json * @throws \Exception */ public function userLogin(Request $request){ if(!empty(session('adminAccount')) ){ //如果用户已经登录,跳转到后台首页 return redirect((string)url('index/index')); } if($request->isPost()){ $name= $request->param('name'); $password = $request->param('password'); $yzm = $request->param('yzm'); //判断是否没有数据 if(empty($name)&&empty($password)||empty($yzm)){ return json(['status'=>0,'msg'=>'未提交数据']); } //数据不为空,查询用户是否存在 $adminInfo = Db::name('msg_admin')->where('name','=',$name)->find(); //halt($adminInfo); if(!empty($adminInfo) && $adminInfo['status']!=1){ return json(['statsu'=>0,'msg'=>'用户不存在']); } if(!captcha_check($yzm)){ return json(['status'=>0,'msg'=>'验证码不正确']); } //md5加密密码::password_salt是一个自定义密码加密具体 //具体是在common.php中实现,具体如下::: /** <?php // 应用公共文件 //通用密码加密 function password_salt($str){ $salt='sttr'; return md5($str.$salt); } */ // if($adminInfo['password']!=password_salt($password)){ //这里数据库信息是手动添加,所以没有使用加密。 if($adminInfo['password']!=$password){ return json(['status'=>0,'msg'=>'密码不正确']); } //将用户存入session中 session('adminAccount',$adminInfo); return json(['status'=>1,'msg'=>'登录成功']); }else{ return View::fetch(); } } //退出登录 public function loginOut(){ session::clear(); //重定向到登录界面》》》》 return redirect('userLogin'); }}这就是登录逻辑了:::这里我还有一个问题:就是进入后台首页后,通过tp51,tp5方法,通过模板语法无法获取session,不知小伙伴们有没有解决方法,有的话告诉我一声。谢谢。我的解决办法是:在首页index.html和index控制器中:index控制器中:::123456789101112<?phpdeclare (strict_types = 1);namespace app\admin\controller;use think\facade\View;class Index{ public function index() { View::assign('user',session('adminAccount')); return View::fetch(); }}我将他送个session的值给了user,前台从user中取出::T_T前台代码::123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/layui/css/layui.css"></head><body><div class="layui-layout layui-layout-admin"> <div class="layui-header"> <div class="layui-logo">XXX后台管理系统</div> <!-- 头部区域(可配合layui已有的水平导航) --> <ul class="layui-nav layui-layout-left"> <li class="layui-nav-item"><a href="">主页</a></li> <li class="layui-nav-item"><a href="">商品管理</a></li> <li class="layui-nav-item"><a href="">用户管理</a></li> <li class="layui-nav-item"> <a href="javascript:;">其它</a> <dl class="layui-nav-child"> <dd><a href="">邮件管理</a></dd> <dd><a href="">消息管理</a></dd> <dd><a href="">授权管理</a></dd> </dl> </li> </ul> <ul class="layui-nav layui-layout-right"> <li class="layui-nav-item"> <a href="javascript:;"> <img src="" class="layui-nav-img"> {$user.name} <!-- 具体看这里,取出session的值::::: --> </a> <dl class="layui-nav-child"> <dd><a href="">个人资料</a></dd> <dd><a href="">安全设置</a></dd> </dl> </li> <li class="layui-nav-item"><a href="{:url('user/loginOut')}">安全退出</a></li> </ul> </div> <div class="layui-side layui-bg-black"> <div class="layui-side-scroll"> <!-- 左侧导航区域(可配合layui已有的垂直导航) --> <ul class="layui-nav layui-nav-tree" lay-filter="test"> <li class="layui-nav-item layui-nav-itemed"> <a class="" href="javascript:;">商品管理</a> <dl class="layui-nav-child"> <dd><a href="javascript:;">商品列表</a></dd> <dd><a href="javascript:;">添加商品</a></dd> </dl> </li> <li class="layui-nav-item"> <a href="javascript:;">订单管理</a> <dl class="layui-nav-child"> <dd><a href="javascript:;">订单列表</a></dd> <dd><a href="javascript:;">待审核</a></dd> <dd><a href="javascript:;">配送中</a></dd> <dd><a href="javascript:;">完成订单</a></dd> </dl> </li> <li class="layui-nav-item"><a href="">其他功能</a></li> </ul> </div> </div> <div class="layui-body"> <!-- 内容主体区域 --> </div> <div class="layui-footer"> <!-- 底部固定区域 --> © layui.com - 底部固定区域 </div></div><script src="/static/layui/lay/modules/jquery.js"></script><script src="/static/layui/layui.all.js"></script><script> //JavaScript代码区域 layui.use('element', function(){ var element = layui.element; });</script></body></html>后台主页界面图3-3图3-3 后台主页界面图具体内容就这样,有问题呢百度,还是有问题还是百度。以上就是Thinkphp6 + layui 实现后台登录(验证码刷新)的详细内容
0
0 1403天前
1254
基于Thinkphp3.2的QQ第三方认证登录扩展类基于Thinkphp3.2的qq第三方认证登录扩展类,其实以下类也是我从TP官网收集整理得来的,稍微做了一下修改和完善。这里我将文件放存在“/Application/Common/Lib/Qqconnect.class.php”。(其实这个文件路径根据自己喜好来放)实例化1$Qqconnect = new \Common\Lib\Qqconnect();在__construct方法中你可以直接写你的app_id、app_key和回调地址也可以根据自己的喜好,改一下代码传参或者写到配置文件。调用方法:1. 在qq的登录按钮的方法中调用getAuthCode方法12$qqobj=new \Org\Util\Qqconnect();$qqobj->getAuthCode();2.在回调地址的方法中调用getUsrInfo方法12$qqobj=new \Org\Util\Qqconnect();$result=$qqobj->getUsrInfo();3.getAuthCode方法中的参数scope根据自身需要添加值get_user_info,list_album,upload_pic,do_like。Qqconnect.class.php123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183<?php// +----------------------------------------------------------------------// | Copyright (c) 2015.// +----------------------------------------------------------------------// | Author: qiandutianxia <852997402@qq.com>// +----------------------------------------------------------------------namespace Common\Lib;/** * qq第三方登录认证 */class Qqconnect { private static $data; //APP ID private $app_id=""; //APP KEY private $app_key=""; //回调地址 private $callBackUrl=""; //Authorization Code private $code=""; //access Token private $accessToken=""; private $openid=""; public function __construct(){ $this->app_id=""; $this->app_key=""; $this->callBackUrl=""; //你的回调地址 //检查用户数据 if(empty($_SESSION['QC_userData'])){ self::$data = array(); }else{ self::$data = $_SESSION['QC_userData']; } } //获取Authorization Code public function getAuthCode(){ $url="https://graph.qq.com/oauth2.0/authorize"; $param['response_type']="code"; $param['client_id']=$this->app_id; $param['redirect_uri']=$this->callBackUrl; //生成唯一随机串防CSRF攻击 $state = md5(uniqid(rand(), TRUE)); $_SESSION['state']=$state; $param['state']=$state; $param['scope']="get_user_info"; $param =http_build_query($param,'','&'); $url=$url."?".$param; header("Location:".$url); } //通过Authorization Code获取Access Token private function _getAccessToken(){ $this->code=$_GET['code']; $url="https://graph.qq.com/oauth2.0/token"; $param['grant_type']="authorization_code"; $param['client_id']=$this->app_id; $param['client_secret']=$this->app_key; $param['code']=$this->code; $param['redirect_uri']=$this->callBackUrl; $param =http_build_query($param,'','&'); $url=$url."?".$param; return $this->getUrl($url); } //获取openid public function _setOpenID(){ $rzt=$this->_getAccessToken(); parse_str($rzt,$data); $this->accessToken=$data['access_token']; $url="https://graph.qq.com/oauth2.0/me"; $param['access_token']=$this->accessToken; $param =http_build_query($param,'','&'); $url=$url."?".$param; $response=$this->getUrl($url); //--------检测错误是否发生 if(strpos($response, "callback") !== false){ $lpos = strpos($response, "("); $rpos = strrpos($response, ")"); $response = substr($response, $lpos + 1, $rpos - $lpos -1); } $user = json_decode($response); if(isset($user->error)){ exit("错误代码:100007"); } return $user->openid; } //获取信息 public function getUserInfo(){ if($_GET['state'] != $_SESSION['state']){ exit("错误代码:300001"); } $openid=$this->_setOpenID(); if(empty($openid)){ return false; } session('openid',$openid); $url="https://graph.qq.com/user/get_user_info"; $param['access_token']=$this->accessToken; $param['oauth_consumer_key']=$this->app_id; $param['openid']=$openid; $param =http_build_query($param,'','&'); $url=$url."?".$param; $rzt=$this->getUrl($url); return $rzt; } public function getOpenId(){ if($_GET['state'] != $_SESSION['state']){ exit("错误代码:300001"); } $rzt=$this->_getAccessToken(); parse_str($rzt,$data); $this->accessToken=$data['access_token']; $url="https://graph.qq.com/oauth2.0/me"; $param['access_token']=$this->accessToken; $param =http_build_query($param,'','&'); $url=$url."?".$param; $response=$this->getUrl($url); //--------检测错误是否发生 if(strpos($response, "callback") !== false){ $lpos = strpos($response, "("); $rpos = strrpos($response, ")"); $response = substr($response, $lpos + 1, $rpos - $lpos -1); } $info = object_array(json_decode($response)); $qq['access_token'] = $this->accessToken; $qq['openid'] = $info['openid']; session('qq',$qq); return $info['openid']; } public function getInfo($openid='',$accessToken=''){ $url="https://graph.qq.com/user/get_user_info"; $param['oauth_consumer_key']=$this->app_id; $param['access_token']=$accessToken; $param['openid']=$openid; $param =http_build_query($param,'','&'); $url=$url."?".$param; $rzt=$this->getUrl($url); $info = object_array(json_decode($rzt)); return $info; } //CURL GET private function getUrl($url){ $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 5); if (!empty($options)){ curl_setopt_array($ch, $options); } $data = curl_exec($ch); curl_close($ch); return $data; } //CURL POST private function postUrl($url,$post_data){ $ch = curl_init(); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); ob_start(); curl_exec($ch); $result = ob_get_contents(); ob_end_clean(); return $result; }}下面是控制器中的代码LoginController.class.php该文件主要包含两个方式点击QQ登陆的时候访问的地址1234public function qq_login(){ $Qqconnect = new \Common\Lib\Qqconnect(); $Qqconnect->getAuthCode(); }回调访问地址123456789101112131415161718192021public function callback(){ $Qqconnect = new \Common\Lib\Qqconnect(); $openid = $Qqconnect->getOpenId(); $qq = session('qq'); $Member = M('Member'); $map = array(); $map['openid'] = $openid; $userInfo = $Member->where($map)->find(); if(!empty($userInfo)){ $this->success('登陆成功!',U('Member/index')); }else{ $Qqconnect = new \Common\Lib\Qqconnect(); $userInfo = $Qqconnect->getInfo($qq['openid'],$qq['access_token']); print_r($userInfo); exit; }以上只是简单的示例,大家可以参考一下再进行修改和完善。如有不明白的地方可以留言讨论。推荐教程:《PHP视频教程》以上就是以Thinkphp3.2为基础的QQ第三方认证登录扩展类的详细内容
0
0 1403天前
967
Thinkphp 框架扩展之类库扩展操作详解这篇文章主要介绍了Thinkphp 框架扩展之类库扩展操作,结合实例形式分析了Thinkphp 类库扩展的相关原理、实现方法与操作注意事项,需要的朋友可以参考下本文实例讲述了Thinkphp 框架扩展之类库扩展操作。分享给大家供大家参考,具体如下:库类扩展ThinkPHP的类库主要包括公共类库和应用类库,都是基于命名空间进行定义和扩展的。只要按照规范定义,都可以实现自动加载。公共库类公共类库通常是指ThinkPHP/Library目录下面的类库,例如:Think目录:系统核心类库Org目录:第三方公共类库这些目录下面的类库都可以自动加载,你只要把相应的类库放入目录中,然后添加或者修改命名空间定义。 你可以在Org/Util/目录下面添加一个Image.class.php 文件,然后添加命名空间如下:123namespace Org\Util;class Image {}这样,就可以用下面的方式直接实例化Image类了:1$image = new \Org\Util\Image;除了这些目录之外,你完全可以在ThinkPHP/Library目录下面添加自己的类库目录,例如,我们添加一个Com目录用于企业类库扩展:Com\Sina\App类(位于Com/Sina/App.class.php )123namespace Com\Sina;class App {}Com\Sina\Rank类(位于Com/Sina/Rank.class.php)123namespace Com\Sina;class Rank {}公共类库除了在系统的Library目录之外,还可以自定义其他的命名空间,我们只需要注册一个新的命名空间,在应用或者模块配置文件中添加下面的设置参数:123'AUTOLOAD_NAMESPACE' => array( 'Lib' => APP_PATH.'Lib',)我们在应用目录下面创建了一个Lib目录用于放置公共的Lib扩展,如果我们要把上面两个类库放到Lib\Sina目录下面,只需要调整为:Lib\Sina\App类(位于Lib/Sina/App.class.php )123namespace Lib\Sina;class App {}Lib\Sina\Rank类(位于Lib/Sina/Rank.class.php)123namespace Lib\Sina;class Rank {}如果你的类库没有采用命名空间的话,需要使用import方法先加载类库文件,然后再进行实例化,例如: 我们定义了一个Counter类(位于Com/Sina/Util/Counter.class.php):12class Counter {}在使用的时候,需要按下面方式调用:12import('Com.Sina.Util.Couter');$object = new \Counter();应用类库应用类库通常是在应用或者模块目录下面的类库,应用类库的命名空间一般就是模块的名称为根命名空间,例如: Home\Model\UserModel类(位于Application\Home\Model)namespace Home\Model;use Think\Model;class UserModel extends Model{}Common\Util\Pay类(位于Application\Common\Util)123namespace Common\Util;class Pay {}Admin\Api\UserApi类(位于Application\Admin\Api)1234namespace Admin\Api;use Think\Model;class UserApi extends Model{}记住一个原则,命名空间的路径和实际的文件路径对应的话 就可以实现直接实例化的时候自动加载。推荐教程:《PHP视频教程》以上就是Thinkphp 框架扩展之类库扩展操作解析的详细内容
0
0 1403天前
1072
路由目录说明
├─app
│ ├─adminapi 后台模块
│ │ ├─route
│ │ │ ├─agent.php 分销管理
│ │ │ ├─app.php 应用模块
│ │ │ ├─chat.php 客服管理
│ │ │ ├─cms.php 文章管理
│ │ │ ├─common.php 文件下载,导出
│ │ │ ├─export.php 导出excel
│ │ │ ├─file.php 附件
│ │ │ ├─finance.php 财务模块
│ │ │ ├─freight.php 商户管理
│ │ │ ├─marketing.php 优惠券,砍价,拼团,秒杀
│ │ │ ├─merchant.php 门店
│ │ │ ├─notify.php 消息管理
│ │ │ ├─order.php 订单
│ │ │ ├─product.php 商品
│ │ │ ├─route.php 登录
│ │ │ ├─setting.php 设置
│ │ │ ├─system.php 系统
│ │ │ ├─user.php 会员
│ │ │ ├─widget.php 小组件
0
0 1414天前
1194
驱动说明从之前的3.0,3.1版本中文件上传,sms短信发送,小票打印机书文件存放还是书写都比较随意,因此pro版本和3.2版本中修改成多驱动形式;文件目录结构├─crmeb CREMB核心类库
│ ├─services
│ │ ├─printer 打印机
│ │ ├─sms 短信
│ │ ├─template 模板消息
│ │ ├─upload 文件上传
Template 使用方式//以微信公众号小程序模板消息为驱动方式
$template = new Template('wechat');
$res=$template->to('送达人openid')->color('字体颜色')->url('跳转路径')->send('模板id编号',array [发送数据]);
if($res === false){
dump($res->getError());
}else{
dump('ok');
}
增加驱动说明这里以文件上传为例进行增加金山云文件上传,创建的文件名必须首字母大写第一步,增加金山云上传驱动文件类 crmeb\services\upload\storage\Jinshan.php<?php
namespace crmeb\services\upload\storage;
use crmeb\basic\BaseUpload;
class Jinshan extends BaseUpload
{
//实例化类
protected function initialize(array $config)
{
parent::initialize($config); // TODO: Change the autogenerated stub
}
// 实例化上传
protected function app()
{
// TODO: Implement app() method.
}
//上传文件
public function move(string $file = 'file')
{
// TODO: Implement move() method.
}
//上传流文件
public function stream(string $fileContent, string $key = null)
{
// TODO: Implement stream() method.
}
//删除文件
public function delete(string $filePath)
{
// TODO: Implement delete() method.
}
//获取上传密钥
public function getTempKeys()
{
// TODO: Implement getTempKeys() method.
}
}
增加上传配置 config/upload.php 每一个驱动都能增加单独的上传配置return [
//默认上传模式
'default' => 'local',
//上传文件大小
'filesize' => 2097152,
//上传文件后缀类型
'fileExt' => ['jpg', 'jpeg', 'png', 'gif', 'pem', 'mp3', 'wma', 'wav', 'amr', 'mp4', 'key'],
//上传文件类型
'fileMime' => ['image/jpeg', 'image/gif', 'image/png', 'text/plain', 'audio/mpeg'],
//驱动模式
'stores' => [
//本地上传配置
'local' => [],
//七牛云上传配置
'qiniu' => [],
//oss上传配置
'oss' => [],
//cos上传配置
'cos' => [],
//金山云上传配置
'jinshan'=>[
'filesize'=>2097152,
'fileExt'=>['jpg'],
'fileMime'=>['image/jpeg'],
],
]
];
实例调用$upload = new Upload('jinshan');
//validate 参数为数组如果不填写默认读取jinshan云的配置进行上传验证
$res = $upload->to('上传路径')->validate()->move();
if($res !== false){
//返回类型为对象
dump($res);
//可调用getUploadInfo来获取保存在附件表的详细信息
dump($upload->getUploadInfo());
//可调用getFileInfo来获取上传后返回的对象
dump($upload->getFileInfo());
}else{
//上传失败调用getError 获取错误信息
dump($upload->getError());
}
0
0 1414天前
1336
form-buider 说明参考ui框架:iview2.xjs表单生成器生成:form-creategithub : https://github.com/xaboy/form-builder参考文档: http://www.form-create.com添加产品表单$field = [
Form::select('cate_id','产品分类')->setOptions(function(){
$list = CategoryModel::getTierList();
foreach ($list as $menu){
$menus[] = ['value'=>$menu['id'],'label'=>$menu['html'].$menu['cate_name'],'disabled'=>$menu['pid']== 0];//,'disabled'=>$menu['pid']== 0];
}
return $menus;
})->filterable(1)->multiple(1),
Form::input('store_name','产品名称')->col(Form::col(8)),
Form::input('store_info','产品简介')->type('textarea'),
Form::input('keyword','产品关键字')->placeholder('多个用英文状态下的逗号隔开'),
Form::input('unit_name','产品单位','件'),
Form::frameImageOne('image','产品主图片(305*305px)',Url::build('admin/widget.images/index',array('fodder'=>'image')))->icon('image')->width('100%')->height('550px'),
Form::frameImages('slider_image','产品轮播图(640*640px)',Url::build('admin/widget.images/index',array('fodder'=>'slider_image')))->maxLength(5)->icon('images')->width('100%')->height('550px')->spin(0),
Form::number('price','产品售价')->min(0)->col(8),
Form::number('ot_price','产品市场价')->min(0)->col(8),
Form::number('give_integral','赠送积分')->min(0)->precision(0)->col(8),
Form::number('postage','邮费')->min(0)->col(Form::col(8)),
Form::number('sales','销量')->min(0)->precision(0)->col(8),
Form::number('ficti','虚拟销量')->min(0)->precision(0)->col(8),
Form::number('stock','库存')->min(0)->precision(0)->col(8),
Form::number('cost','产品成本价')->min(0)->col(8),
Form::number('sort','排序')->col(8),
Form::radio('is_show','产品状态',0)->options([['label'=>'上架','value'=>1],['label'=>'下架','value'=>0]])->col(8),
Form::radio('is_hot','热卖单品',0)->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8),
Form::radio('is_benefit','促销单品',0)->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8),
Form::radio('is_best','精品推荐',0)->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8),
Form::radio('is_new','首发新品',0)->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8),
Form::radio('is_postage','是否包邮',0)->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8)
];
return $this->makePostForm('添加商品', $field, Url::buildUrl('save' ), 'POST');
编辑产品表单$product = ProductModel::get($id);
$form = Form::create(Url::build('update',array('id'=>$id)),[
Form::select('cate_id','产品分类',explode(',',$product->getData('cate_id')))->setOptions(function(){
$list = CategoryModel::getTierList();
foreach ($list as $menu){
$menus[] = ['value'=>$menu['id'],'label'=>$menu['html'].$menu['cate_name'],'disabled'=>$menu['pid']== 0];//,'disabled'=>$menu['pid']== 0];
}
return $menus;
})->filterable(1)->multiple(1),
Form::input('store_name','产品名称',$product->getData('store_name')),
Form::input('store_info','产品简介',$product->getData('store_info'))->type('textarea'),
Form::input('keyword','产品关键字',$product->getData('keyword'))->placeholder('多个用英文状态下的逗号隔开'),
Form::input('unit_name','产品单位',$product->getData('unit_name')),
Form::frameImageOne('image','产品主图片(305*305px)',Url::build('admin/widget.images/index',array('fodder'=>'image')),$product->getData('image'))->icon('image')->width('100%')->height('550px'),
Form::frameImages('slider_image','产品轮播图(640*640px)',Url::build('admin/widget.images/index',array('fodder'=>'slider_image')),json_decode($product->getData('slider_image'),1))->maxLength(5)->icon('images'),
Form::number('price','产品售价',$product->getData('price'))->min(0)->precision(2)->col(8),
Form::number('ot_price','产品市场价',$product->getData('ot_price'))->min(0)->col(8),
Form::number('give_integral','赠送积分',$product->getData('give_integral'))->min(0)->precision(0)->col(8),
Form::number('postage','邮费',$product->getData('postage'))->min(0)->col(8),
Form::number('sales','销量',$product->getData('sales'))->min(0)->precision(0)->col(8),
Form::number('ficti','虚拟销量',$product->getData('ficti'))->min(0)->precision(0)->col(8),
Form::number('stock','库存',ProductModel::getStock($id)>0?ProductModel::getStock($id):$product->getData('stock'))->min(0)->precision(0)->col(8),
Form::number('cost','产品成本价',$product->getData('cost'))->min(0)->col(8),
Form::number('sort','排序',$product->getData('sort'))->col(8),
Form::radio('is_show','产品状态',$product->getData('is_show'))->options([['label'=>'上架','value'=>1],['label'=>'下架','value'=>0]])->col(8),
Form::radio('is_hot','热卖单品',$product->getData('is_hot'))->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8),
Form::radio('is_benefit','促销单品',$product->getData('is_benefit'))->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8),
Form::radio('is_best','精品推荐',$product->getData('is_best'))->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8),
Form::radio('is_new','首发新品',$product->getData('is_new'))->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8),
Form::radio('is_postage','是否包邮',$product->getData('is_postage'))->options([['label'=>'是','value'=>1],['label'=>'否','value'=>0]])->col(8)
]);
return $this->makePostForm('编辑商品', $field, Url::buildUrl('edit' ), 'PUT');
AJAX请求返回namespace \FormBuilder\Json**Json::succ(msg,data = [])**表单提交成功**Json::fail(errorMsg,data = [])**表单提交失败**Json::uploadSucc(filePath,msg)**文件/图片上传成功,上传成功后返回文件地址**Json::uploadFail(errorMsg)**文件/图片上传失败Form 表单生成类namespace \FormBuilder\Form**components(array $components = [])**批量添加组件**formRow(Row $row)**设置表单Row规则**formStyle(FormStyle $formStyle)**设置表单样式**setAction($action)**设置提交地址**getConfig($key='')**设置配置文件**setMethod($method)**设置提交方式**setMethod($method)**设置提交方式**append(FormComponentDriver $component)**追加组件**prepend(FormComponentDriver $component)**开头插入组件**getRules()**获得表单规则**view()**获取表单视图**script()**获取表单生成器所需全部js**formScript()**获取生成表单的js代码,可用js变量接受生成函数create,执行create(el,callback)即可生成表单**getScript()**获取表单生成器所需js**create($action, array $components = [])**生成表单快捷方法**setTitle($title)**设置titleFormStyle表单样式Form::style * @method $this inline(Boolean $bool) 是否开启行内表单模式
* @method $this labelPosition(String $labelPosition) 表单域标签的位置,可选值为 left、right、top
* @method $this labelWidth(Number $labelWidth) 表单域标签的宽度,所有的 FormItem 都会继承 Form 组件的 label-width 的值
* @method $this showMessage(Boolean $bool) 是否显示校验错误信息
* @method $this autocomplete($bool = false) 原生的 autocomplete 属性,可选值为 true = off 或 false = on
Row栅格规则Form::row * @method $this gutter(Number $gutter) 栅格间距,单位 px,左右平分
* @method $this type(String $type) 栅格的顺序,在flex布局模式下有效
* @method $this align(String $align) flex 布局下的垂直对齐方式,可选值为top、middle、bottom
* @method $this justify(String $justify) flex 布局下的水平排列方式,可选值为start、end、center、space-around、space-between
* @method $this className(String $className) 自定义的class名称
参考:view row栅格布局Col栅格规则Form::col * @method $this span(Number $span) 栅格的占位格数,可选值为0~24的整数,为 0 时,相当于display:none
* @method $this order(Number $order) 栅格的顺序,在flex布局模式下有效
* @method $this offset(Number $offset) 栅格左侧的间隔格数,间隔内不可以有栅格
* @method $this push(Number $push) 栅格向右移动格数
* @method $this pull(Number $pull) 栅格向左移动格数
* @method $this labelWidth(Number $labelWidth) 表单域标签的的宽度,默认150px
* @method $this className(String $className) 自定义的class名称
* @method $this xs(Number|Col $span) <768px 响应式栅格,可为栅格数或一个包含其他属性的对象
* @method $this sm(Number|Col $span) ≥768px 响应式栅格,可为栅格数或一个包含其他属性的对象
* @method $this md(Number|Col $span) ≥992px 响应式栅格,可为栅格数或一个包含其他属性的对象
* @method $this lg(Number|Col $span) ≥1200px 响应式栅格,可为栅格数或一个包含其他属性的对象
参考:view col栅格布局select,checkbox,radio组件配置options专用方法**option($value, $label, $disabled = false)**单独设置选项**options(array $options, $disabled = false)**批量设置选项**setOptions($options, $disabled = false)**批量设置选项 支持匿名函数以下组件公共方法**col($span)**配置col栅格规则,传入0-24的数字或Col类,默认为24**value($value)**设置组件的值**validateAs(array $validate)**添加验证规则**validate()**设置验证规则规则说明组件namespace \FormBuilder\Form多级联动组件Form::cascader多级联动组件,value为array类型Form::city省市二级联动,value为array类型Form::cityArea省市区三级联动,value为array类型 方法 返回值 方法名(参数) 注释
* @method $this type(String $type) 数据类型, 支持 city_area(省市区三级联动), city (省市二级联动), other (自定义)
* @method $this disabled(Boolean $bool) 是否禁用选择器
* @method $this clearable(Boolean $bool) 是否支持清除
* @method $this placeholder(String $placeholder) 占位文本
* @method $this trigger(String $trigger) 次级菜单展开方式,可选值为 click 或 hover
* @method $this changeOnSelect(Boolean $bool) 当此项为 true 时,点选每级菜单选项值都会发生变化, 默认为 false
* @method $this size(String $size) 输入框大小,可选值为large和small或者不填
* @method $this filterable(Boolean $bool) 是否支持搜索
* @method $this notFoundText(String $text) 当搜索列表为空时显示的内容
* @method $this transfer(Boolean $bool) /是否将弹层放置于 body 内,在 Tabs、带有 fixed 的 Table 列内使用时,建议添加此属性,它将不受父级样式影响,从而达到更好的效果
* @method $this required($message = null, $trigger = 'change') 设为必选
* @method $this data(array $data) 设置多级联动可选项的数据
* 例如: {
* "value":"北京市", "label":"北京市", "children":[{
* "value":"东城区", "label":"东城区"
* }]
* }
* @method $this jsData($var) 设置data为js变量
* @method string getType($var) 获取组件类型
复选框组件Form::checkbox * @method $this size(String $size) 多选框组的尺寸,可选值为 large、small、default 或者不设置
* @method $this required($message = null, $trigger = 'change') 设为必选
颜色选择组件Form::color * @method $this disabled(Boolean $bool) 是否禁用
* @method $this alpha(Boolean $bool) 是否支持透明度选择, 默认为false
* @method $this hue(Boolean $bool) 是否支持色彩选择, 默认为true
* @method $this recommend(Boolean $bool) 是否显示推荐的颜色预设, 默认为false
* @method $this size(String $size) 尺寸,可选值为large、small、default或者不设置
* @method $this format(String $format) 颜色的格式,可选值为 hsl、hsv、hex、rgb String 开启 alpha 时为 rgb,其它为 hex
* @method $this required($message = null, $trigger = 'change') 设为必选
* @method $this colors($colors) 自定义颜色预设
日期选择组件Form::date日期选择Form::dateRange日期区间选择,value为array类型Form::dateTime日期+时间选择Form::dateTimeRange日期+时间 区间选择,value为array类型Form::year年份选择Form::month月份选择 * @method $this type(String $type) 显示类型,可选值为 date、daterange、datetime、datetimerange、year、month
* @method $this format(String $format) 展示的日期格式, 默认为yyyy-MM-dd HH:mm:ss
* @method $this placement(String $placement) 日期选择器出现的位置,可选值为top, top-start, top-end, bottom, bottom-start, bottom-end, left, left-start, left-end, right, right-start, right-end, 默认为bottom-start
* @method $this placeholder(String $placeholder) 占位文本
* @method $this confirm(Boolean $bool) 是否显示底部控制栏,开启后,选择完日期,选择器不会主动关闭,需用户确认后才可关闭, 默认为false
* @method $this size(String $size) 尺寸,可选值为large、small、default或者不设置
* @method $this disabled(Boolean $bool) 是否禁用选择器
* @method $this clearable(Boolean $bool) 是否显示清除按钮
* @method $this readonly(Boolean $bool) 完全只读,开启后不会弹出选择器,只在没有设置 open 属性下生效
* @method $this editable(Boolean $bool) 文本框是否可以输入, 默认为false
* @method $this transfer(Boolean $bool) 是否将弹层放置于 body 内,在 Tabs、带有 fixed 的 Table 列内使用时,建议添加此属性,它将不受父级样式影响,从而达到更好的效果, 默认为false
* @method $this splitPanels(Boolean $bool) 开启后,左右面板不联动,仅在 daterange 和 datetimerange 下可用。
* @method $this showWeekNumbers(Boolean $bool) 开启后,可以显示星期数。
frame组件Form::frameframe组件Form::frameInputsframe组件,input类型,value为array类型Form::frameFilesframe组件,file类型,value为array类型Form::frameImagesframe组件,image类型,value为array类型Form::frameInputOneframe组件,input类型,value为string|number类型Form::frameFileOneframe组件,file类型,value为string|number类型Form::frameImageOneframe组件,image类型,value为string|number类型 * @method $this type(String $type) frame类型, 有input, file, image, 默认为input
* @method $this src(String $src) iframe地址
* @method $this maxLength(int $length) value的最大数量, 默认无限制
* @method $this icon(String $icon) 打开弹出框的按钮图标
* @method $this height(String $height) 弹出框高度
* @method $this width(String $width) 弹出框宽度
* @method $this spin(Boolean $bool) 是否显示加载动画, 默认为 true
* @method $this frameTitle(String $title) 弹出框标题
* @method $this handleIcon(Boolean $bool) 操作按钮的图标, 设置为false将不显示, 设置为true为默认的预览图标, 类型为file时默认为false, image类型默认为true
* @method $this allowRemove(Boolean $bool) 是否可删除, 设置为false是不显示删除按钮
hidden组件Form::hiddenhidden组件数字输入框组件Form::number * @method $this max(float $max) 最大值
* @method $this min(float $min) 最小值
* @method $this step(float $step) 每次改变的步伐,可以是小数
* @method $this size(String $size) 输入框尺寸,可选值为large、small、default或者不填
* @method $this disabled(Boolean $bool) 设置禁用状态,默认为false
* @method $this placeholder(String $placeholder) 占位文本
* @method $this readonly(Boolean $bool) 是否设置为只读,默认为false
* @method $this editable(Boolean $bool) 是否可编辑,默认为true
* @method $this precision(int $precision) 数值精度
input输入框组件Form::inputinput输入框其他type: text类型Form::text,password类型Form::password,textarea类型Form::textarea,url类型Form::url,email类型Form::email,date类型Form::idate * @method $this type(String $type) 输入框类型,可选值为 text、password、textarea、url、email、date;
* @method $this size(String $size) 输入框尺寸,可选值为large、small、default或者不设置;
* @method $this placeholder(String $placeholder) 占位文本
* @method $this clearable(Boolean $bool) 是否显示清空按钮, 默认为false
* @method $this disabled(Boolean $bool) 设置输入框为禁用状态, 默认为false
* @method $this readonly(Boolean $bool) 设置输入框为只读, 默认为false
* @method $this maxlength(int $length) 最大输入长度
* @method $this icon(String $icon) 输入框尾部图标,仅在 text 类型下有效
* @method $this rows(int $rows) 文本域默认行数,仅在 textarea 类型下有效, 默认为2
* @method $this number(Boolean $bool) 将用户的输入转换为 Number 类型, 默认为false
* @method $this autofocus(Boolean $bool) 自动获取焦点, 默认为false
* @method $this autocomplete(Boolean $bool) 原生的自动完成功能, 默认为false
* @method $this spellcheck(Boolean $bool) 原生的 spellcheck 属性, 默认为false
* @method $this wrap(String $warp) 原生的 wrap 属性,可选值为 hard 和 soft, 默认为soft
* @method $this autoSize($minRows, $maxRows) 自适应内容高度,仅在 textarea 类型下有效
单选框组件Form::radio * @method $this size(String $size) 单选框的尺寸,可选值为 large、small、default 或者不设置
* @method $this vertical(Boolean $bool) 是否垂直排列,按钮样式下无效
* @method $this button() 使用按钮样式
* @method $this required($message = null, $trigger = 'change') 设为必选
评分组件Form::rate * @method $this count(int $star) star 总数, 默认为 5
* @method $this allowHalf(Boolean $bool) 是否允许半选, 默认为 false
* @method $this disabled(Boolean $bool) 是否只读,无法进行交互, 默认为
* @method $this showText(Boolean $bool) 是否显示提示文字, 默认为 false
* @method $this clearable(Boolean $bool) 是否可以取消选择, 默认为 false
select选择框组件Form::select选择框Form::selectMultipleselect选择框,多选,value为array类型Form::selectOneselect选择框,单选 * @method $this multiple(Boolean $bool) 是否支持多选, 默认为false
* @method $this disabled(Boolean $bool) 是否禁用, 默认为false
* @method $this clearable(Boolean $bool) 是否可以清空选项,只在单选时有效, 默认为false
* @method $this filterable(Boolean $bool) 是否支持搜索, 默认为false
* @method $this size(String $size) 选择框大小,可选值为large、small、default或者不填
* @method $this placeholder(String $placeholder) 占位文本
* @method $this transfer(String $transfer) 是否将弹层放置于 body 内,在 Tabs、带有 fixed 的 Table 列内使用时,建议添加此属性,它将不受父级样式影响,从而达到更好的效果, 默认为false
* @method $this placement(String $placement) 弹窗的展开方向,可选值为 bottom 和 top, 默认为bottom
* @method $this notFoundText(String $text) 当下拉列表为空时显示的内容, 默认为 无匹配数据
* @method $this required($message = null, $trigger = 'change') 设为必选
滑块组件Form::slider滑块组件Form::sliderRange滑块组件,区间选择, * @method $this min(float $min) 最小值, 默认 0
* @method $this max(float $max) 最大值, 默认 100
* @method $this step(float $step) 步长,取值建议能被(max - min)整除, 默认 1
* @method $this disabled(Boolean $bool) 是否禁用滑块, 默认 false
* @method $this range(Boolean $bool) 是否开启双滑块模式, 默认
* @method $this showInput(Boolean $bool) 是否显示数字输入框,仅在单滑块模式下有效, 默认 false
* @method $this showStops(Boolean $bool) 是否显示间断点,建议在 step 不密集时使用, 默认 false
* @method $this showTip(String $tip) 提示的显示控制,可选值为 hover(悬停,默认)、always(总是可见)、never(不可见)
* @method $this inputSize(String $size) 数字输入框的尺寸,可选值为large、small、default或者不填,仅在开启 show-input 时有效
开关组件组件Form::switches * @method $this size(String $size) 开关的尺寸,可选值为large、small、default或者不写。建议开关如果使用了2个汉字的文字,使用 large。
* @method $this disabled(Boolean $bool) 禁用开关, 默认为false
* @method $this trueValue(String $value) 选中时的值,默认为1
* @method $this falseValue(String $value) 没有选中时的值,默认为0
* @method $this openStr(String $open) 自定义显示打开时的内容
* @method $this closeStr(String $close) 自定义显示关闭时的内容
时间选择组件Form::timePicker时间选择组件Form::time时间选择Form::timeRange时间区间选择,value为array类型 * @method $this type(String $type) 显示类型,可选值为 time、timerange
* @method $this format(String $format) 展示的时间格式, 默认为HH:mm:ss
* @method $this placement(String $placement) 时间选择器出现的位置,可选值为top, top-start, top-end, bottom, bottom-start, bottom-end, left, left-start, left-end, right, right-start, right-end, 默认为bottom-start
* @method $this placeholder(String $placeholder) 占位文本
* @method $this confirm(Boolean $bool) 是否显示底部控制栏, 默认为false
* @method $this size(String $size) 尺寸,可选值为large、small、default或者不设置
* @method $this disabled(Boolean $bool) 是否禁用选择器
* @method $this clearable(Boolean $bool) 是否显示清除按钮
* @method $this readonly(Boolean $bool) 完全只读,开启后不会弹出选择器,只在没有设置 open 属性下生效
* @method $this editable(Boolean $bool) 文本框是否可以输入, 默认为false
* @method $this transfer(Boolean $bool) 是否将弹层放置于 body 内,在 Tabs、带有 fixed 的 Table 列内使用时,建议添加此属性,它将不受父级样式影响,从而达到更好的效果, 默认为false
* @method $this steps($h, $i = 0, $s = 0) 下拉列表的时间间隔,数组的三项分别对应小时、分钟、秒, 例如设置为 [1, 15] 时,分钟会显示:00、15、30、45。
上传组件Form::upload上传组件Form::uploadImages多图上传组件,value为array类型Form::uploadFiles多文件上传组件,value为array类型Form::uploadImageOne单图上传组件Form::uploadFileOne单文件上传组件 * @method $this uploadType(String $uploadType) 上传文件类型,可选值为 image(图片上传),file(文件上传)
* @method $this action(String $action) 上传的地址
* @method $this multiple(Boolean $bool) 是否支持多选文件
* @method $this name(String $name) 上传的文件字段名
* @method $this accept(String $accept) 接受上传的文件类型
* @method $this maxSize(int $size) 文件大小限制,单位 kb
* @method $this withCredentials(Boolean $bool) 支持发送 cookie 凭证信息, 默认为false
* @method $this maxLength(Int $length) 最大上传文件数, 0为无限
* @method $this headers(array $headers) 设置上传的请求头部
* @method $this format(array $format) 支持的文件类型,与 accept 不同的是,format 是识别文件的后缀名,accept 为 input 标签原生的 accept 属性,会在选择文件时过滤,可以两者结合使用
* @method $this data(array $data) 上传时附带的额外参数
* @method $this required($message = null, $trigger = 'change') 设为必选
树型组件Form::tree树型组件Form::treeSelected选中类型,value为array类型,当type=selected并且multiple=false,值为String或Number类型Form::treeChecked选择类型,value为array类型 * @method $this type(String $type) 类型,可选值为 checked、selected
* @method $this multiple(Boolean $bool) 是否支持多选,当`type=selected`并且`multiple=false`,默认为false,值为String或Number类型,其他情况为Array类型
* @method $this showCheckbox(Boolean $bool) 是否显示多选框,默认为false
* @method $this emptyText(String $emptyText) 没有数据时的提示,默认为'暂无数据'
* @method $this data(array $treeData) 设置可选的data,**id必须唯一**
* @method $this jsData($var) 设置data为js变量
树型组件data数据类 TreeDataForm::treeData树型组件data * @method $this id(String $id) Id,必须唯一
* @method $this title(String $title) 标题
* @method $this expand(Boolean $bool) 是否展开直子节点,默认为false
* @method $this disabled(Boolean $bool) 禁掉响应,默认为false
* @method $this disableCheckbox(Boolean $bool) 禁掉 checkbox
* @method $this selected(Boolean $bool) 是否选中子节点
* @method $this checked(Boolean $bool) 是否勾选(如果勾选,子节点也会全部勾选)
* @method $this children(array $children) 批量设置子集
* @method $this child(TreeData $child) 设置子集
所有组件生成效果
0
0 1414天前
1352
系统常用函数目录 /app/common.php/**
* 抛出异常处理
*
* @param string $msg 异常消息
* @param integer $code 异常代码 默认为0
* @param string $exception 异常类
*
* @throws Exception
*/
exception($msg, $code = 0, $exception = '')
// 过滤掉emoji表情
filter_emoji($str)
/**
* 上传路径转化,默认路径
* @param $path
* @param int $type
* @param bool $force
* @return string
*/
make_path($path, int $type = 2, bool $force = false)
/**
* 敏感词过滤
*
* @param string
* @return string
*/
sensitive_words_filter($str)
/**
* CURL 检测远程文件是否在
* @param $url
* @return bool
*/
curl_file_exist($url)
/**
* 设置附加路径
* @param $url
* @return bool
*/
set_file_url($image, $siteUrl = '')
/**
* 修改 https 和 http
* @param $url $url 域名
* @param int $type 0 返回https 1 返回 http
* @return string
*/
set_http_type($url, $type = 0)
/**
* 身份证验证
* @param $card
* @return bool
*/
check_card($card)
/**
* 匿名处理处理用户昵称
* @param $name
* @return string
*/
anonymity($name)
/**
* 分级排序
* @param $data
* @param int $pid
* @param string $field
* @param string $pk
* @param string $html
* @param int $level
* @param bool $clear
* @return array
*/
sort_list_tier($data, $pid = 0, $field = 'pid', $pk = 'id', $html = '|-----', $level = 1, $clear = true)
/**
* 时间戳人性化转化
* @param $time
* @return string
*/
time_tran($time)
/**
* url转换路径
* @param $url
* @return string
*/
url_to_path($url)
/**
* 路径转url路径
* @param $path
* @return string
*/
path_to_url($path)
/**
* 获取图片转为base64
* @param string $avatar
* @return bool|string
*/
image_to_base64($avatar = '', $timeout = 9)
/**
* 文件调试
* @param $content
*/
debug_file($content, string $fileName = 'error', string $ext = 'txt')
/**
* sql 参数过滤
* @param string $str
* @return mixed
*/
sql_filter(string $str)
/**
* 是否能成为推广人
* @param float $price
* @return bool
*/
is_brokerage_statu(float $price)
0
0 1414天前
1051
事件'task_2'=>[],//定时任务: 2秒钟执行
'task_6'=>[],//定时任务: 6秒钟执行
'task_10'=>[],//定时任务: 10秒钟执行
'task_30'=>[],//定时任务: 30秒钟执行
'task_60'=>[],//定时任务: 60秒钟执行
'task_180'=>[],//定时任务: 180秒钟执行
'task_300'=>[],//定时任务: 300秒钟执行
'StoreProductOrderDeliveryAfter' => [], // 送货
'StoreProductOrderDeliveryGoodsAfter' => [], //发货
'StoreProductOrderRefundNAfter' => [], // 订单状态不退款
'StoreProductOrderOffline' => [], // 线下付款成功后
'StoreProductOrderEditAfter' => [], // 修改订单金额
'StoreProductOrderDistributionAfter' => [], // 修改配送信息
'StoreProductOrderOver' => [], // 订单全部产品评价完
'StoreOrderRegressionAllAfter' => [], // 回退所有
'AdminVisit' => [], //添加管理员访问记录
'SystemAdminLoginAfter' => [], //添加管理员最后登录时间和ip
'StoreProductSetCartAfter' => [], // 用户加入购物车成功之后
'StoreProductUserOperationConfirmAfter' => [], // 用户点赞产品
'StoreProductUserOperationCancelAfter' => [], // 用户取消点赞产品
'WechatMaterialAfter' => [], // 微信公众号 图片/声音 转media 存入数据库
'WechatMessageBefore' => [], // 微信消息前置操作
'WechatEventUnsubscribeBefore' => [], //用户取消关注公众号前置操作
'WechatOauthAfter' => [], //微信授权成功后
'InitLogin' => [], // UserSubscribe 微信授权成功后 ebapi模块 Basic控制器
'UserLevelAfter' => [], // 检查是否能成为会员
'OrderCreated' => [], //用户订单创建成功
'OrderPaySuccess' => [], //用户订单支付成功
'OrderCreateAgain' => [], //用户再次下单
'UserOrderRemoved' => [], //用户删除订单
'UserOrderTake' => [], //用户确认收货
'UserCommented' => [], //用户评价商品
'RechargeSuccess' => [], //用户充值成功后
'ImportNowMoney' => [], //用户佣金转成余额成功后
事件订阅文件目录 /app/event.php'subscribe' => [
crmeb\subscribes\SystemSubscribe::class,//后台系统事件订阅类
crmeb\subscribes\OrderSubscribe::class,//订单事件订阅类
crmeb\subscribes\ProductSubscribe::class,//产品事件订阅类
crmeb\subscribes\UserSubscribe::class,//用户事件订阅类
crmeb\subscribes\MaterialSubscribe::class,//素材事件订阅类
crmeb\subscribes\MessageSubscribe::class,//消息事件订阅类
crmeb\subscribes\TaskSubscribe::class,//定时任务事件订阅类
],
0
0 1414天前
1306
路由API路由配置文件 /app/api/route/route.php无需登录授权接口//账号密码登录
Route::post('login', 'AuthController/login')->name('login')
->middleware(\app\http\middleware\AllowOriginMiddleware::class);
// 获取发短信的key
Route::get('verify_code', 'AuthController/verifyCode')->name('verifyCode')
->middleware(\app\http\middleware\AllowOriginMiddleware::class);
//手机号登录
Route::post('login/mobile', 'AuthController/mobile')->name('loginMobile')
->middleware(\app\http\middleware\AllowOriginMiddleware::class);
//图片验证码
Route::get('sms_captcha', 'AuthController/captcha')->name('captcha')
->middleware(\app\http\middleware\AllowOriginMiddleware::class);
//验证码发送
Route::post('register/verify', 'AuthController/verify')->name('registerVerify')
->middleware(\app\http\middleware\AllowOriginMiddleware::class);
//手机号注册
Route::post('register', 'AuthController/register')->name('register')
->middleware(\app\http\middleware\AllowOriginMiddleware::class);
//手机号修改密码
Route::post('register/reset', 'AuthController/reset')->name('registerReset')
->middleware(\app\http\middleware\AllowOriginMiddleware::class);
Route::any('wechat/serve', 'wechat.WechatController/serve');//公众号服务
Route::any('wechat/notify', 'wechat.WechatController/notify');//公众号支付回调
Route::any('routine/notify', 'wechat.AuthController/notify');//小程序支付回调
//管理员订单操作类
Route::group(function () {
Route::get('admin/order/statistics', 'admin.StoreOrderController/statistics')->name('adminOrderStatistics');//订单数据统计
Route::get('admin/order/data', 'admin.StoreOrderController/data')->name('adminOrderData');//订单每月统计数据
Route::get('admin/order/list', 'admin.StoreOrderController/lst')->name('adminOrderList');//订单列表
Route::get('admin/order/detail/:orderId', 'admin.StoreOrderController/detail')->name('adminOrderDetail');//订单详情
Route::get('admin/order/delivery/gain/:orderId', 'admin.StoreOrderController/delivery_gain')->name('adminOrderDeliveryGain');//订单发货获取订单信息
Route::post('admin/order/delivery/keep', 'admin.StoreOrderController/delivery_keep')->name('adminOrderDeliveryKeep');//订单发货
Route::post('admin/order/price', 'admin.StoreOrderController/price')->name('adminOrderPrice');//订单改价
Route::post('admin/order/remark', 'admin.StoreOrderController/remark')->name('adminOrderRemark');//订单备注
Route::get('admin/order/time', 'admin.StoreOrderController/time')->name('adminOrderTime');//订单交易额时间统计
Route::post('admin/order/offline', 'admin.StoreOrderController/offline')->name('adminOrderOffline');//订单支付
Route::post('admin/order/refund', 'admin.StoreOrderController/refund')->name('adminOrderRefund');//订单退款
Route::post('order/order_verific', 'admin.StoreOrderController/order_verific')->name('order');//订单核销
})->middleware(\app\http\middleware\AllowOriginMiddleware::class)->middleware(\app\api\middleware\AuthTokenMiddleware::class, true)->middleware(\app\api\middleware\CustomerMiddleware::class);
//会员授权接口
Route::group(function () {
Route::get('logout', 'AuthController/logout')->name('logout');// 退出登录
Route::post('switch_h5', 'AuthController/switch_h5')->name('switch_h5');// 切换账号
Route::post('binding', 'AuthController/binding_phone')->name('bindingPhone');// 绑定手机号
//商品类
Route::get('product/code/:id', 'store.StoreProductController/code')->name('productCode');//商品分享二维码 推广员
//公共类
Route::post('upload/image', 'PublicController/upload_image')->name('uploadImage');//图片上传
//用户类 客服聊天记录
Route::get('user/service/list', 'user.StoreService/lst')->name('userServiceList');//客服列表
Route::get('user/service/record/:toUid', 'user.StoreService/record')->name('userServiceRecord');//客服聊天记录
//用户类 用户coupons/order
Route::get('user', 'user.UserController/user')->name('user');//个人中心
Route::post('user/spread', 'user.UserController/spread')->name('userSpread');//静默绑定授权
Route::post('user/edit', 'user.UserController/edit')->name('userEdit');//用户修改信息
Route::get('user/balance', 'user.UserController/balance')->name('userBalance');//用户资金统计
Route::get('userinfo', 'user.UserController/userinfo')->name('userinfo');// 用户信息
//用户类 地址
Route::get('address/detail/:id', 'user.UserController/address')->name('address');//获取单个地址
Route::get('address/list', 'user.UserController/address_list')->name('addressList');//地址列表
Route::post('address/default/set', 'user.UserController/address_default_set')->name('addressDefaultSet');//设置默认地址
Route::get('address/default', 'user.UserController/address_default')->name('addressDefault');//获取默认地址
Route::post('address/edit', 'user.UserController/address_edit')->name('addressEdit');//修改 添加 地址
Route::post('address/del', 'user.UserController/address_del')->name('addressDel');//删除地址
//用户类 收藏
Route::get('collect/user', 'user.UserController/collect_user')->name('collectUser');//收藏商品列表
Route::post('collect/add', 'user.UserController/collect_add')->name('collectAdd');//添加收藏
Route::post('collect/del', 'user.UserController/collect_del')->name('collectDel');//取消收藏
Route::post('collect/all', 'user.UserController/collect_all')->name('collectAll');//批量添加收藏
Route::get('brokerage_rank', 'user.UserController/brokerage_rank')->name('brokerageRank');//佣金排行
Route::get('rank', 'user.UserController/rank')->name('rank');//推广人排行
//用戶类 分享
Route::post('user/share', 'PublicController/user_share')->name('user_share');//记录用户分享
//用户类 点赞
// Route::post('like/add', 'user.UserController/like_add')->name('likeAdd');//添加点赞
// Route::post('like/del', 'user.UserController/like_del')->name('likeDel');//取消点赞
//用户类 签到
Route::get('sign/config', 'user.UserController/sign_config')->name('signConfig');//签到配置
Route::get('sign/list', 'user.UserController/sign_list')->name('signList');//签到列表
Route::get('sign/month', 'user.UserController/sign_month')->name('signIntegral');//签到列表(年月)
Route::post('sign/user', 'user.UserController/sign_user')->name('signUser');//签到用户信息
Route::post('sign/integral', 'user.UserController/sign_integral')->name('signIntegral');//签到
//优惠券类
Route::post('coupon/receive', 'store.StoreCouponsController/receive')->name('couponReceive'); //领取优惠券
Route::post('coupon/receive/batch', 'store.StoreCouponsController/receive_batch')->name('couponReceiveBatch'); //批量领取优惠券
Route::get('coupons/user/:types', 'store.StoreCouponsController/user')->name('couponsUser');//用户已领取优惠券
Route::get('coupons/order/:price', 'store.StoreCouponsController/order')->name('couponsOrder');//优惠券 订单列表
//购物车类
Route::get('cart/list', 'store.StoreCartController/lst')->name('cartList'); //购物车列表
Route::post('cart/add', 'store.StoreCartController/add')->name('cartAdd'); //购物车添加
Route::post('cart/del', 'store.StoreCartController/del')->name('cartDel'); //购物车删除
Route::post('order/cancel', 'order.StoreOrderController/cancel')->name('orderCancel'); //订单取消
Route::post('cart/num', 'store.StoreCartController/num')->name('cartNum'); //购物车 修改商品数量
Route::get('cart/count', 'store.StoreCartController/count')->name('cartCount'); //购物车 获取数量
//订单类
Route::post('order/confirm', 'order.StoreOrderController/confirm')->name('orderConfirm'); //订单确认
Route::post('order/computed/:key', 'order.StoreOrderController/computedOrder')->name('computedOrder'); //计算订单金额
Route::post('order/create/:key', 'order.StoreOrderController/create')->name('orderCreate'); //订单创建
Route::get('order/data', 'order.StoreOrderController/data')->name('orderData'); //订单统计数据
Route::get('order/list', 'order.StoreOrderController/lst')->name('orderList'); //订单列表
Route::get('order/detail/:uni', 'order.StoreOrderController/detail')->name('orderDetail'); //订单详情
Route::get('order/refund/reason', 'order.StoreOrderController/refund_reason')->name('orderRefundReason'); //订单退款理由
Route::post('order/refund/verify', 'order.StoreOrderController/refund_verify')->name('orderRefundVerify'); //订单退款审核
Route::post('order/take', 'order.StoreOrderController/take')->name('orderTake'); //订单收货
Route::get('order/express/:uni', 'order.StoreOrderController/express')->name('orderExpress'); //订单查看物流
Route::post('order/del', 'order.StoreOrderController/del')->name('orderDel'); //订单删除
Route::post('order/again', 'order.StoreOrderController/again')->name('orderAgain'); //订单 再次下单
Route::post('order/pay', 'order.StoreOrderController/pay')->name('orderPay'); //订单支付
Route::post('order/product', 'order.StoreOrderController/product')->name('orderProduct'); //订单商品信息
Route::post('order/comment', 'order.StoreOrderController/comment')->name('orderComment'); //订单评价
//活动---砍价
Route::get('bargain/detail/:id', 'activity.StoreBargainController/detail')->name('bargainDetail');//砍价商品详情
Route::post('bargain/start', 'activity.StoreBargainController/start')->name('bargainStart');//砍价开启
Route::post('bargain/start/user', 'activity.StoreBargainController/start_user')->name('bargainStartUser');//砍价 开启砍价用户信息
Route::post('bargain/share', 'activity.StoreBargainController/share')->name('bargainShare');//砍价 观看/分享/参与次数
Route::post('bargain/help', 'activity.StoreBargainController/help')->name('bargainHelp');//砍价 帮助好友砍价
Route::post('bargain/help/price', 'activity.StoreBargainController/help_price')->name('bargainHelpPrice');//砍价 砍掉金额
Route::post('bargain/help/count', 'activity.StoreBargainController/help_count')->name('bargainHelpCount');//砍价 砍价帮总人数、剩余金额、进度条、已经砍掉的价格
Route::post('bargain/help/list', 'activity.StoreBargainController/help_list')->name('bargainHelpList');//砍价 砍价帮
Route::post('bargain/poster', 'activity.StoreBargainController/poster')->name('bargainPoster');//砍价海报
Route::get('bargain/user/list', 'activity.StoreBargainController/user_list')->name('bargainUserList');//砍价列表(已参与)
Route::post('bargain/user/cancel', 'activity.StoreBargainController/user_cancel')->name('bargainUserCancel');//砍价取消
//活动---拼团
Route::get('combination/pink/:id', 'activity.StoreCombinationController/pink')->name('combinationPink');//拼团开团
Route::post('combination/remove', 'activity.StoreCombinationController/remove')->name('combinationRemove');//拼团 取消开团
Route::post('combination/poster', 'activity.StoreCombinationController/poster')->name('combinationPoster');//拼团海报
//账单类
Route::get('commission', 'user.UserBillController/commission')->name('commission');//推广数据 昨天的佣金 累计提现金额 当前佣金
Route::post('spread/people', 'user.UserBillController/spread_people')->name('spreadPeople');//推荐用户
Route::post('spread/order', 'user.UserBillController/spread_order')->name('spreadOrder');//推广订单
Route::get('spread/commission/:type', 'user.UserBillController/spread_commission')->name('spreadCommission');//推广佣金明细
Route::get('spread/count/:type', 'user.UserBillController/spread_count')->name('spreadCount');//推广 佣金 3/提现 4 总和
Route::get('spread/banner', 'user.UserBillController/spread_banner')->name('spreadBanner');//推广分销二维码海报生成
Route::get('integral/list', 'user.UserBillController/integral_list')->name('integralList');//积分记录
//提现类
Route::get('extract/bank', 'user.UserExtractController/bank')->name('extractBank');//提现银行/提现最低金额
Route::post('extract/cash', 'user.UserExtractController/cash')->name('extractCash');//提现申请
//充值类
Route::post('recharge/routine', 'user.UserRechargeController/routine')->name('rechargeRoutine');//小程序充值
Route::post('recharge/wechat', 'user.UserRechargeController/wechat')->name('rechargeWechat');//公众号充值
Route::get('recharge/index', 'user.UserRechargeController/index')->name('rechargeQuota');//充值余额选择
//会员等级类
Route::get('menu/user', 'PublicController/menu_user')->name('menuUser');//个人中心菜单
Route::get('user/level/detection', 'user.UserLevelController/detection')->name('userLevelDetection');//检测用户是否可以成为会员
Route::get('user/level/grade', 'user.UserLevelController/grade')->name('userLevelGrade');//会员等级列表
Route::get('user/level/task/:id', 'user.UserLevelController/task')->name('userLevelTask');//获取等级任务
//首页获取未支付订单
Route::get('order/nopay', 'order.StoreOrderController/get_noPay')->name('getNoPay');//获取未支付订单
Route::get('seckill/code/:id', 'activity.StoreSeckillController/code')->name('seckillCode');//秒杀商品海报
Route::get('combination/code/:id', 'activity.StoreCombinationController/code')->name('combinationCode');//拼团商品海报
})->middleware(\app\http\middleware\AllowOriginMiddleware::class)->middleware(\app\api\middleware\AuthTokenMiddleware::class, true);
//未授权接口
Route::group(function () {
//公共类
Route::get('index', 'PublicController/index')->name('index');//首页
Route::get('search/keyword', 'PublicController/search')->name('searchKeyword');//热门搜索关键字获取
//商品分类类
Route::get('category', 'store.CategoryController/category')->name('category');
//商品类
Route::post('image_base64', 'PublicController/get_image_base64')->name('getImageBase64');// 获取图片base64
Route::get('product/detail/:id/[:type]', 'store.StoreProductController/detail')->name('detail');//商品详情
Route::get('groom/list/:type', 'store.StoreProductController/groom_list')->name('groomList');//获取首页推荐不同类型商品的轮播图和商品
Route::get('products', 'store.StoreProductController/lst')->name('products');//商品列表
Route::get('product/hot', 'store.StoreProductController/product_hot')->name('productHot');//为你推荐
Route::get('reply/list/:id', 'store.StoreProductController/reply_list')->name('replyList');//商品评价列表
Route::get('reply/config/:id', 'store.StoreProductController/reply_config')->name('replyConfig');//商品评价数量和好评度
//文章分类类
Route::get('article/category/list', 'publics.ArticleCategoryController/lst')->name('articleCategoryList');//文章分类列表
//文章类
Route::get('article/list/:cid', 'publics.ArticleController/lst')->name('articleList');//文章列表
Route::get('article/details/:id', 'publics.ArticleController/details')->name('articleDetails');//文章详情
Route::get('article/hot/list', 'publics.ArticleController/hot')->name('articleHotList');//文章 热门
Route::get('article/banner/list', 'publics.ArticleController/banner')->name('articleBannerList');//文章 banner
//活动---秒杀
Route::get('seckill/index', 'activity.StoreSeckillController/index')->name('seckillIndex');//秒杀商品时间区间
Route::get('seckill/list/:time', 'activity.StoreSeckillController/lst')->name('seckillList');//秒杀商品列表
Route::get('seckill/detail/:id/[:time]', 'activity.StoreSeckillController/detail')->name('seckillDetail');//秒杀商品详情
//活动---砍价
Route::get('bargain/config', 'activity.StoreBargainController/config')->name('bargainConfig');//砍价商品列表配置
Route::get('bargain/list', 'activity.StoreBargainController/lst')->name('bargainList');//砍价商品列表
//活动---拼团
Route::get('combination/list', 'activity.StoreCombinationController/lst')->name('combinationList');//拼团商品列表
Route::get('combination/detail/:id', 'activity.StoreCombinationController/detail')->name('combinationDetail');//拼团商品详情
//用户类
Route::get('user/activity', 'user.UserController/activity')->name('userActivity');//活动状态
//微信
Route::get('wechat/config', 'wechat.WechatController/config')->name('wechatConfig');//微信 sdk 配置
Route::get('wechat/auth', 'wechat.WechatController/auth')->name('wechatAuth');//微信授权
//小程序登陆
Route::post('wechat/mp_auth', 'wechat.AuthController/mp_auth')->name('mpAuth');//小程序登陆
Route::get('wechat/get_logo', 'wechat.AuthController/get_logo')->name('getLogo');//小程序登陆授权展示logo
Route::post('wechat/set_form_id', 'wechat.AuthController/set_form_id')->name('setFormId');//小程序登陆收集form id
Route::get('wechat/teml_ids', 'wechat.AuthController/teml_ids')->name('wechatTemlIds');//小程序订阅消息
Route::get('wechat/live', 'wechat.AuthController/live')->name('wechatLive');//小程序直播列表
//物流公司
Route::get('logistics', 'PublicController/logistics')->name('logistics');//物流公司列表
//分享配置
Route::get('share', 'PublicController/share')->name('share');//分享配置
//优惠券
Route::get('coupons', 'store.StoreCouponsController/lst')->name('couponsList'); //可领取优惠券列表
//短信购买异步通知
Route::post('sms/pay/notify', 'PublicController/sms_pay_notify')->name('smsPayNotify'); //短信购买异步通知
//获取关注微信公众号海报
Route::get('wechat/follow', 'wechat.WechatController/follow')->name('Follow');
//门店列表
Route::get('store_list', 'PublicController/store_list')->name('storeList');
//获取城市列表
Route::get('city_list', 'PublicController/city_list')->name('cityList');
//拼团数据
Route::get('pink', 'PublicController/pink')->name('pinkData');
//用户访问
Route::post('user/set_visit', 'user.UserController/set_visit')->name('setVisit');// 添加用户访问记录
})->middleware(\app\http\middleware\AllowOriginMiddleware::class)->middleware(\app\api\middleware\AuthTokenMiddleware::class, false);
0
0 1414天前
1082
CRMEB-Pro遵循PSR-2命名规范和PSR-4自动加载规范,并且注意如下规范:目录和文件目录使用小写+下划线;.类库、函数文件统一以.php为后缀;类的文件名均以命名空间定义,并且命名空间的路径和类库文件所在路径一致;类文件采用驼峰法命名(首字母大写),其它文件采用小写+下划线命名;类名和类文件名保持一致,统一采用驼峰法命名(首字母大写);函数和类、属性命名类的命名采用驼峰法(首字母大写),例如User、UserType,默认不需要添加后缀,例如UserController应该直接命名为User;函数的命名使用小写字母和下划线(小写字母开头)的方式,例如get_client_ip;控制器内方法命名使用小写字母和下划线(小写字母开头)的方式,例如get_client_ip;方法的命名使用驼峰法(首字母小写),例如getUserName;属性的命名使用驼峰法(首字母小写),例如tableName、instance;特例:以双下划线__打头的函数或方法作为魔术方法,例如__call和__autoload;函数和方法的区别:函数是单独存在的,也就是面向过程部分定义的;而方法是依赖于类存在的,也就是面向对象中定义的常量和配置常量以大写字母和下划线命名,例如APP_PATH;配置参数以小写字母和下划线命名,例如url_route_on和url_convert;环境变量定义使用大写字母和下划线命名,例如APP_DEBUG;数据表和字段数据表和字段采用小写加下划线方式命名,并注意字段名不要以下划线开头,例如think_user表和user_name字段,不建议使用驼峰和中文作为数据表及字段命名。系统编码UTF-8 LF请理解并尽量遵循以上命名规范,可以减少在开发过程中出现不必要的错误。
0
0 1414天前
931
963
二次开发 什么是二次开发? 二次开发,简单的说就是在现有的软件上进行定制修改,功能的扩展,然后达到自己想要的功能和效果,一般来说都不会改变原有系统的内核。 为什么要二次开发? 随着信息化技术的不断发展,IT行业涌现出了一系列优秀的开源作品,其作者或是个人,或是项目小组,或是软件公司。选择和应用这些优秀的开源软件,并在此基础上进行符合业务需求的二次开发,将给企业节省信息化成本(时间成本及开发成本)的同时,更能带来技术上的保障。这就是我们常听的:站在巨人的肩膀上,你将看的更远。所以国内很多公司需要二次开发的人才。 怎么做二次开发? 第一,你要有这个开源产品的所用语言的语言基础,能看懂代码是最基本的。 第二,你要对这个开源产品的功能和使用要有比较熟悉,因为你熟悉了,你才知道一个需求下来,你要改什么,什么是系统自带的,大概要怎么改。 第三,你要熟悉这个开源产品的数据结构,代码结构,系统的框架结构,核心是哪里,附属功能是在哪里。简单点说,就是数据库,代码逻辑,文件目录的熟悉。 第四,根据你的需求,然后利用开源产品的内核,进行系统的扩展和修改,以达到你的需求介绍PHP的开源产品的二次开发的基本要求: 第一, 基本要求:HTML(必须要非常熟悉),PHP(能看懂代码,能写一些小系统,如:留言板,小型CMS),Mysql(至少会一种数据库),Javascript(能看懂,能改现成的一些代码),Div+Css(能进行界面的调整,明白CSS是怎么使用的) 第二, 熟悉开源产品的使用,比如 Dedecms,你要知道怎么登录,怎么新建栏目,怎么添加文章,模板标签的使用方法,模型的概念和使用方法等等一些功能 第三, 要熟悉这个开源产品的数据库结构,还要理解里面核心文件的内容,比如:数据库类怎么使用,常用的安全过滤是怎么做的,模板引擎又是怎么使用的等等一些核心内容。还要知道这个开源产品的目录结构,就是说,你要知道哪是放模板的,哪里是做控制的,哪里是放样式的,等等 第四, 熟悉你的需求,对需求进行解读,然后确定如何对这个开源产品进行修改和扩展 经过二次开发后,你能获取到的是什么呢? 你能完成你的需求,你能积累经验,这里的经验有你自己的,也有别人的。所谓别人的,就是在你做这个二次开发的时候,你能吸收到这个系统的精华,然后融入到你自己的思想里,你还能总结项目架构的经验。有句话说的好,就是:聪明的人会把别人的失败的经验当作自己的经验,而傻的人就是自己无数次体验失败后才作为自己的经验。二次开发不仅仅是开发,而更重要的是吸取精华,总结经验,理顺思路,少走弯路,提升自己。 站在巨人的肩膀上,你将看的更远!!! ◆DedeCMS二次开发 为了让更多人了解二次开发,并更方便的了解DedeCMS的二次开发,下面将会简单的介绍关于DedeCMS二次开发的一些基础和大纲 DedeCMS二次开发必备基础: · 非常熟悉HTML · 熟悉DIV+CSS的布局 · 扎实的PHP基础,熟悉结构化编程,了解OOP,并能看懂和使用 · 熟悉MYSQL,掌握SQL语言 DedeCMS二次开发学习过程 · 理解CMS是什么 · 熟悉DedeCMS的功能(如:栏目的分类,文档管理,模型的使用,系统的设置等常用的功能) · 掌握DedeCMS的模板标签使用及原理 · DedeCMS目录结构分析 熟悉每个文件夹里面主要装什么文件,这样在二次开发的时候知道在哪个文件夹下的什么文件修改 目录结构摘要: ./a 生成文件存放路径 ./data 缓存文件及数据中心 /admin 管理后台数据 /backupdata 备份数据 /cache 缓存文件 /enums 级别联动数据,JS,枚举类型的缓存文件 /js 常用的JS /mark 水印相关文件 /module 模块安装文件 /rss Rss相关 /sessions Session 存放路径 /textdata 文本数据 /tplcache 模板缓存 /uploadtmp 上传文件缓存位置 /ziptmp zip包解压缓存位置 …… DedeCMS文件结构分析 熟悉每个文件的基本功能,方便做修改,知道每个文件的大概作用之后,可以方便的对文件进行修改 文件结构摘要: common.inc.php 数据库配置文件 config.cache.bak.php 后台系统配置备份 config.cache.inc.php 后台系统配置文件缓存 downmix.data.php 采集混淆缓存文件 mysql_error_track.inc MYSQL错误��志 safequestions.php 安全问题 sitemap.html 站点地图 sys_pay.cache.php 支付网关配置 template.rand.php 随机模板设置 …… · DedeCMS数据库结构分析,至少要熟悉每个表的作用 熟悉每个表的作用,了解几个核心表的设计及字段的含义,方便拿到新的需求之后,能快速的判断是否加字段,还是新建表来处理。同时也能理解DedeCMS的数据库设计思想,把有用的设计思路加到自己的系统中。 · DedeCMS的流程控制,及一些核心文件的解析 熟悉一些登陆,注册,文档管理,权限控制,分类管理,模型设置等一些常用流程控制。对几个核心文件进行解剖,了解其编程技巧及安全机制 · DedeCMS插件的开发(****式插件和内嵌式插件) 熟悉两种插件的编写,插件的导入导出,插件搭配模型的使用 ◆Ecshop二次开发 EcShop二次开发学习方法 近年来,随着互联网的发展,电子商务也跟着一起成长,B2B,C2C,B2C的电子商务模式也不断的成熟。这时催生出了众多电子商务相关的PHP开源产品。B2C方面有Ecshop,Zencart,Magento等国内外知名产品。 下面我们就来简单介绍一下学习Ecshop二次开发的过程和要注意的一些东西: Ecshop二次开发必备基础: · 非常熟悉HTML · 熟悉DIV+CSS的布局 · 扎实的PHP基础,熟悉结构化编程,了解OOP,并能看懂和使用 · 熟悉Smarty模板引擎 · 熟悉MYSQL,掌握SQL语言 Ecshop二次开发学习过程 · 熟悉电子商务基本概念 · 熟悉EcShop 的基本功能使用(商品类型,商品分类,商品属性设置,促销活动使用等) · 掌握Ecshop的数据库结构和数据库设计思想 · 熟悉ER的模式,实体与关系的建立 熟悉每个表的作用,了解几个核心表的设计及字段的含义,方便拿到新的需求之后,能快速的判断是否加字段,还是新建表来处理。同时也能理解Ecshop的数据库设计思想,把有用的设计思路加到自己的系统中 · 文件结构分析及代码分析 熟悉一些登陆,注册,文档管理,权限控制,分类管理,商品类型等一些常用流程控制。对几个核心文件进行解剖,了解其编程技巧及安全机制 · Ecshop文件结构分析: \includes\cls_captcha.php: 验证码图片类 \includes\cls_ecshop.php: 基础类 \includes\cls_ecshop.php(56): 密码编译方法; \includes\cls_rss.php: RSS 类 \includes\cls_smtp.php: SMTP 邮件类 \includes\inc_constant.php: 常量 \includes\init.php: 前台公用文件 \includes\lib_common.php: 公用函数库 \includes\lib_goodscat.php: 前台公用函数库 \includes\lib_insert.php: 动态内容函数库 \includes\lib_main.php: 前台公用函数库 \includes\lib_payment.php: 支付接口函数库 \includes\iconv\cls_iconv.php: 字符集转换类 \includes\ip\cls_ip.php: IP 归属地查询类 \includes\modules\integrates\discuz.php: 会员数据处理类 \includes\modules\integrates\ecshop.php: 会员数据处理类 Ecshop模板更换 熟悉Smarty的精简版的使用,嵌入自己的界面,EcShop模板的跟换技巧 Ecshop二次开发实例 中英文切换的功能,秒杀功能,京东商城模板的制作等 学习目的: 1,会使用Ecshop进行二次开发 2,会换普通的模板及一些功能的修改 3,吸取里面的开发经验 掌握基础知识-》模仿里面的一些写法-》修改里面的模式(形成自己的开发模式) 掌握Ecshop里面的编程技巧及系统设计技巧 ◆缓存技术分析 常见的PHP缓存技术分析[概念版] 在大部份情况下我们的网站都会使用数据库作为站点数据存储的容器。当你执行一个SQL查询时,典型的处理过程是:连接数据库->准备SQL查询->发送查询到数据库->取得数据库返回结果->关闭数据库连接。但数据库中有些数据是完全静态的或不太经常变动的,缓存系统会通过把SQL查询的结果缓存到一个更快的存储系统中存储,从而避免频繁操作数据库而很大程度上提高了程序执行时间,而且缓存查询结果也允许你后期处理。 普遍使用的缓存技术 数据缓存:这里所说的数据缓存是指数据库查询缓存,每次访问页面的时候,都会先检测相应的缓存数据是否存在,如果不存在,就连接数据库,得到数据,并把查询结果序列化后保存到文件 中,以后同样的查询结果就直接从缓存文件中获得。 页面缓存: 每次访问页面的时候,都会先检测相应的缓存页面文件是否存在,如果不存在,就连接数据库,得到数据,显示页面并同时生成缓存页面文件,这样下次访问的时候页面文件就发挥作用了。(模板引擎和网上常见的一些缓存类通常有此功能) 内存缓存: 在里就不介绍了,不是本文所要讨论的,只简单提一下: Memcached是高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。 dbcached 是一款基于 Memcached 和 NMDB 的分布式 key-value 数据库内存缓存系统。 以上的缓存技术虽然能很好的解决频繁查询数据库的问题,但其缺点在在于数据无时效性,下面我给出我在项目中常用的方法: 时间触发缓存: 检查文件是否存在并且时间戳小于设置的过期时间,如果文件修改的时间戳比当前时间戳减去过期时间戳大,那么就用缓存,否则更新缓存。 设定时间内不去判断数据是否要更新,过了设定时间再更新缓存。以上只适合对时效性要求不高的情况下使用 ,否则请看下面。 内容触发缓存: 当插入数据或更新数据时,强制更新缓存。 在这里我们可以看到,当有大量数据频繁需要更新时,最后都要涉及磁盘读写操作。怎么解决呢?我在日常项目中,通常并不缓存所有内容,而是缓存一部分不经常变的内容来解决。但在大负荷的情况下,最好要用共享内存做缓存系统。 到这里PHP缓存也许有点解决方案了,但其缺点是,因为每次请求仍然要经过PHP解析,在大负荷的情况下效率问题还是比效严重,在这种情况下,也许会用到静态缓存。 静态缓存 这里所说的静态缓存是指HTML缓存,HTML缓存一般是无需判断数据是否要更新的,因为通常在使用HTML的场合一般是不经常变动内容的页面。数据更新的时候把HTML也强制更新一下就可以了。 其实一个缓存系统涉及的问题是比较多的,我在这里只介绍一下我平时的缓存思路,并没有介绍利用软件来实现缓存和写出具体代码。 如果您有什么好的解决方案也请在下面提出,让我们一起互相探讨。 ◆PHP使用函数调用命令 php中使用exec,system等函数调用系统命令 php的内置函数exec,system都可以调用系统命令(shell命令),当然还有passthru,escapeshellcmd等函数。 在很多时候利用php的exec,system等函数调用系统命令可以帮助我们更好更快的完成工作。比如前二天笔者在批量处理.rar文件时exec就帮我了大忙了。 今天整理一下常用的调用系统函数发出来和大家分享经验。 注意:要想使用这二个函数php.ini中的安全模式必须关闭,要不然为了安全起见php是不让调用系统命令的。 先看一下php手册对这二个函数的解释: exec --- 执行外部程式 语法 : string exec ( string command [, array &output [, int &return_var]] ) 说明 : exec( )执行给予的命令command,不过它并不会输出任何东西,它简单的从命令的结果中传回最后一行,如果你需要去执行一个命令,并且从命令去取得所有资料时,可以使用passthru( )这个函数。 如果有给予参数array,则指定的数组将会被命令所输出的每一行填满,注意 : 如果数组先前已经包含了一些元素的话,exec( )将会把它附加在数组的后面,如果你不想要此函数附加元素的话,你可以在传递此数组给exec( )之前呼叫unset( )。 如果有给予参数array和return_var,则传回执行的状态命令将会写到这个变量。 注意 : 如果你允许来自使用者输入的资料,可以传递到此函数,那么你应该使用escapeshellcmd( )来确定此使用者无法哄骗(trick)系统来执行武断的(arbitrary)命令。 注意 : 如果你使用此函数来启动一个程式,而且希望在背景里(background)执行的时候离开它,你必须确定此程式的输出是转向(redirected)到一个文件或是一些输出的资料流,否则PHP将会悬挂(hang)直到程式执行结束。 system --- 执行外部程式并且显示输出 语法 : string system ( string command [, int &return_var] ) 说明 : system( )执行给予的命令command,并且输出结果。如果有给予参数return_var,则执行命令的状态码将会写到这个变量。 注意 : 如果你允许来自使用者输入的资料,可以传递到此函数,那么你应该使用escapeshellcmd( )来确定此使用者无法哄骗(trick)系统来执行武断的(arbitrary)命令。 注意 : 如果你使用此函数来启动一个程式,而且希望在背景里(background)执行的时候离开它,你必须确定此程式的输出是转向(redirected)到一个文件或是一些输出的资料流,否则PHP将会悬挂(hang)直到程式执行结束。 如果PHP是运作成伺服器模组,在输出每一行后,system( )会试着自动地清除web伺服器的输出缓冲。 成功则传回命令的最后一行,失败则传回false。 如果你需要去执行一个命令,并且从命令去取得所有资料时,可以使用passthru( )这个函数。 这二个都是用来调用系统shell命令, 不同点: exec可以把执行的结果全部返回到output函数里(数组),output函数里(数组),status是执行的状态 0为成功 1为失败 systerm不需要提供output函数,他是直接把结果返回出来,同样output函数,他是直接把结果返回出来,同样return_var是执行的状态码 0为成功 1为失败 ◆关于开源 开源最大的成功来源于Web 开源运动广受欢迎,并且在软件开发史上写下了浓重一笔。但是它影响最深远的地方在哪呢?有史以来,最成功的开源“项目”又是什么呢? 事实上,总体来看,Web不就是开源运动最大的成功么? 可能最有名的例子就是隐藏域众多网站背后的LAMP,也就是Linux、Apache、MySQL和PHP。但当你仔细考虑后,你会发现更多。 下面列出了Web得以运转的一些开源项目。 Web browsers-网络浏览器 在网络浏览器市场中,虽然微软的封闭源码软件IE浏览器仍然占有很大的份额,但其它功能相似的开源项目已经流行起来,并在不断壮大。像Mozilla公司的Firefox浏览器(它是开源的,还有Flock、PaleMoon)。还有增长迅速的基于Webkit的浏览器,像Safari,但最著名的是Chrome浏览器。 如果把手机网络也算到这里面,其中Webkit主宰着iPhone、Android和Blackberry手机中的浏览器。 Web server software-Web服务器软件 迄今为止,Apache是使用范围最广的网络服务器软件,它是开源的,但是一个叫做Nginx的轻量级服务器软件在最近几年开始流行起来。事实上,三大顶级网络服务器软件中有两个是开源的(排名第二的微软的IIS是例外,但其距离第一相差甚远)。 另外,大量服务器端底层软件也是开源的。例如,很多大流量网站使用Varnish作为与网站访问者之间的缓存层,而使用Memcached作为与网站数据库之间的缓存层。这只是众多例子中的两个。 Scripting languages and web frameworks-脚本语言和Web框架 网络上使用的大部分编程和脚本语言都是开源的,比如PHP、Perl、Python、Ruby等。 但是,很少有网站完完全全是从零开始。毫不夸张的说,有成百上千的开源内容管理系统(CMS)和网络框架来协助开发人员,例如WordPress、Drupal、Ruby on Rails、Django、Joomla、DedeCMS、Ecshop等。 Databases-数据库 开源软件MySQL是目前为止最流行的网站数据库,但还有其它功能相似的开源软件,比如PostgreSQL,更不用说近来出现的众多“非关系型(NoSQL)”数据库。 既然我们说到了底层软件,那就不得不提一下每次我们使用互联网或因特网上的任何东西时都要依靠的基础系统: DNS-域名解析系统 Web(就此而言是整个因特网)离开了域名解析系统就一无是处。大家都知道,域名解析系统可以让用户使用像example.com之类的域名,而不是IP地址。BIND几乎是DNS服务器(亦称名称服务器)软件的实际标准,并且,你现在可能已经猜到了,它是开源的。 Server operating systems-服务器操作系统 所有网站都必须在服务器上运行,而那也是开源的统治领域。虽然Windows统治着桌面领域,但是网站赖以运行的服务器大部分采用开源的Linux操作系统,其他比较流行的选择是freeBSD和OpenBSD。 开源的诱惑 由于在许多情况下,开源软件能够提供与商业的封闭源码软件相同的性能,并且又是免费的,所以开源软件如此流行并不奇怪。免费是一个难以挑战的价格。 假如Web不是运行在所有这些免费软件上,那么它很可能需要一段艰苦的过程,才能让人们广泛接受。 注意我们并没说过Web中没有任何封闭源码软件,而那显然是存在的。但是,从统计数据看,Web开源统治领域中真正的例外是微软的基于Windows系列系统。 除了那个,你通常需要深入研究才能发现更多私有封闭源码技术,像路由器和类似设备上的操作系统。但那是因特网,而不是Web。
0
0 1414天前
1381
二次开发,简单的说就是在现有的软件上进行定制修改,功能的扩展,然后达到自己想要的功能,一般来说都不会改变原有系统的内核。中文名二次开发外文名custom/tailor-made software development性 质现有的软件上进行定制修改语言基础语言基础分 类计算机学二次开发工具族表、用户定义特征等目录1 简介2 如何进行二次开发3 基本要求4 PRO/ENGINEER二次开发▪ 工具▪ 程序模式5 Ecshop二次开发▪ 必备基础:▪ 文件结构分析6 DedeCMS二次开发▪ 必备基础:▪ 文件结构分析7 常见的PHP缓存技术分析▪ 数据缓存▪ 页面缓存▪ 内存缓存▪ 时间触发缓存▪ 内容触发缓存▪ 静态缓存简介编辑一般的来说,一些大公司如IBM开发了一个大型的软件系统平台,根据不同的客户的需要,一些其它的中小公司为客户根据需求在该平台上进行第二次有针对性的开发。是否提供相应的接口,有的软件公司只提供软件,但也有小公司连代码一起出售,如是后者,就更方便进行二次开发。比如售票系统,车站里面弄好了,提供几个储存过程给银行,银行就可以代理售票了,这也是一种,还有一种如我们利用delphi,C#等操作word等。 [1] 如何进行二次开发编辑第一,你要有这个开源产品的所用语言的语言基础,能看懂代码是最基本的。第二,你要对这个开源产品的功能和使用要有比较熟悉,因为你熟悉了,你才知道一个需求下来,你要改什么,什么是系统自带的,大概要怎么改。第三,你要熟悉这个开源产品的数据结构,代码结构,系统的框架结构,核心是哪里,附属功能是在哪里。简单点说,就是数据库,代码逻辑,文件目录的熟悉。第四,根据你的需求,然后利用开源产品的内核,进行系统的扩展和修改,以达到你的需求。基本要求编辑第一,你要有这个开源产品的所用语言的语言基础。 [2] 二次开发第二,你要对这个开源产品的功能和使用要有比较熟悉,因为你熟悉了,你才知道一个需求下来,你要改什么,什么是系统自带的,大概要怎么改。第三,你要熟悉这个开源产品的数据结构,代码结构,系统的框架结构,核心是哪里,附属功能是在哪里。简单点说,就是数据库,代码逻辑,文件目录的熟悉。如果是用接口式的二次开发,则需要你对这个接口比较熟悉,一般来说会有相应的文档。第四,根据你的需求,然后利用开源产品的内核,进行系统的扩展和修改,以达到你的需求。第五,对其提供的SDK中的API函数有一定了解,以利于你对SDK中个函数的使用更加灵活方便。PRO/ENGINEER二次开发编辑PRO/ENGINEER在提供强大的设计、分析、制造功能的同时,也为用户提供了多种二次开发工具。工具常用的二次开发工具有:族表(Family Table)、用户定义特征(UDF)、Pro/Program、J-link、Pro/toolkit等。 [3] 1)族表(Family Table) 通过族表可以方便的管理具有相同或相近结构的零件,特别适用于标准零件的管理。族表通过建立通用零件为父零件,然后在其基础上对各参数加以控制生成派生零件。整个族表通过电子表格来管理,所以又被称为表格驱动。2)用户定义特征(UDF) 用户定义特征是将若干个系统特征融合为一个自定义特征,使用时作为一个整体出现。系统将UDF特征以gph文件保存。UDF适用特定产品中的特定结构,有利于设计者根据产品特征快速生成几何模型。3)Pro/ENGINEER软件对于每个模型都有一个主要设计步骤和参数列表―Pro/Program。它是由类似BASIC的高级语言构成的,用户可以根据设计需要来编辑该模型的Program,使其作为一个程序来工作。通过运行该程序,系统通过人机交互的方法来控制系统参数、特征出现与否和特征的具体尺寸等。相关书籍4)J-link是PRO/ENGINEER中自带的基于JAVA语言的二次开发工具。用户通过JAVA编程实现在软件PRO/ENGINEER中添加功能。5)Pro/Toolkit同J-link一样也是Pro/E自带的二次开发工具,在Pro/Toolkit中,PTC向用户提供了大型的C语言函数库,函数采用面向对象的风格,通过调用这些底层函数,用户能方便而又安全地访问Pro/ENGINEER的数据库及内部应用程序,进行二次开发,扩展一些特定功能。6)基于VB API的二次开发过程,Pro/E Wildfire 4.0开始可以采用Visual Basic API,通过 Visual Basic NET应用程序和应用程序 (如 Microsoft Word、Excel 或 Access) 中的 Visual Basic 宏来进行二次开发。7)pro/web.link 这种方法使用的语言是javascript,以网页的形式来访问proe 模型一般情况下,采用比较多的是Pro/Toolkit,进行二次开发。程序模式同步模式(Synchronous Mode)和异步模式(Asynchronous Mode)。同步模式下,Pro/E根据注册文件中的信息启动应用程序,Pro/Toolkit应用程序和Pro/E产生各自的进程,程序的控制权在两个进程之间切换。该应用程序不能够独立于Pro/E而运行。在异步模式下,Pro/Toolkit应用程序和Pro/E能够进行各自的操作,在通信方面,异步模式使用远程调用(Remote Procedure Calls,RPC)方式,程序(含有独立主函数)能独立于Pro/E启动。由于异步模式采用远程调用,程序运行速度相比同步模式慢很多,整合性也不好,所以一般基于Pro/E的Toolkit开发采用同步模式。在同步模式下又有两种开发方式:动态链接库(DLL Mode)和多进程(Multiprocess 或Spawned Mode)。前者为的动态连接库文件,无自身主程序函数,直接连接于Pro/E进行程序调用。后者为.exe文件,有独立的主程序和Pro/E进行相连接。一般为了调试方便,开发程序时可以采用多进程模式,在程序完成时,采用动态连接库提高程序运行效率Ecshop二次开发编辑ECShop是一款B2C独立网店系统,适合企业及个人快速构建个性化网上商店。系统是基于PHP语言及MYSQL数据库构架开发的跨平台开源程序。目前最新版本为2.7.3。系统在实际使用过程中用户会有各种不同的需求,往往需要进行二次开发,针对这些需求 php服务中心专门建立ecshop二次开发部门,来解决用户以上问题,同时 php服务中心齐永东齐老师总结二次开发经验录制了大量ecshop二次开发视频并提供免费下载。 [3] 必备基础:非常熟悉HTML熟悉DIV+CSS的布局扎实的PHP基础,熟悉结构化编程,了解OOP,并能看懂和使用熟悉Smarty模板引擎熟悉MYSQL,掌握SQL语言文件结构分析\includes\cls_captcha.php: 验证码图片类\includes\cls_ecshop.php: 基础类\includes\cls_ecshop.php(56): 密码编译方法;\includes\cls_rss.php: RSS 类\includes\cls_smtp.php: SMTP 邮件类\includes\inc_constant.php: 常量\includes\init.php: 前台公用文件\includes\lib_common.php: 公用函数库\includes\lib_goodscat.php: 前台公用函数库\includes\lib_insert.php: 动态内容函数库\includes\lib_main.php: 前台公用函数库\includes\lib_payment.php: 支付接口函数库\includes\iconv\cls_iconv.php: 字符集转换类\includes\ip\cls_ip.php: IP 归属地查询类\includes\modules\integrates\discuz.php: 会员数据处理类\includes\modules\integrates\ecshop.php: 会员数据处理类DedeCMS二次开发编辑必备基础:非常熟悉HTML [4] 熟悉DIV+CSS的布局扎实的PHP基础,熟悉结构化编程,了解OOP,并能看懂和使用熟悉MYSQL,掌握SQL语言文件结构分析熟悉每个文件的基本功能,方便做修改,知道每个文件的大概作用之后,可以方便的对文件进行修改文件结构摘要:common.inc.php 数据库配置文件config.cache.bak.php 后台系统配置备份config.cache.inc.php 后台系统配置文件缓存downmix.data.php 采集混淆缓存文件mysql_error_track.inc MYSQL错误日志safequestions.php 安全问题sitemap.html 站点地图sys_pay.cache.php 支付网关配置template.rand.php 随机模板设置……· DedeCMS数据库结构分析,至少要熟悉每个表的作用熟悉每个表的作用,了解几个核心表的设计及字段的含义,方便拿到新的需求之后,能快速的判断是否加字段,还是新建表来处理。同时也能理解DedeCMS的数据库设计思想,把有用的设计思路加到自己的系统中。· DedeCMS的流程控制,及一些核心文件的解析熟悉一些登陆,注册,文档管理,权限控制,分类管理,模型设置等一些常用流程控制。对几个核心文件进行解剖,了解其编程技巧及安全机制· DedeCMS插件的开发(插件和内嵌式插件)熟悉两种插件的编写,插件的导入导出,插件搭配模型的使用常见的PHP缓存技术分析编辑在大部份情况下我们的网站都会使用数据库作为站点数据存储的容器。当你执行一个SQL查询时,典型的处理过程是:连接数据库->准备SQL查询->发送查询到数据库->取得数据库返回结果->关闭数据库连接。但数据库中有些数据是完全静态的或不太经常变动的,缓存系统会通过把SQL查询的结果缓存到一个更快的存储系统中储,从而避免频繁操作数据库而很大程度上提高了程序执行时间,而且缓存查询结果也允许你后期处理。 [4] 数据缓存这里所说的数据缓存是指数据库查询缓存,每次访问页面的时候,都会先检测相应的缓存数据是否存在,如果不存在,就连接数据库,得到数据,并把查询结果序列化后保存到文件中,以后同样的查询结果就直接从缓存文件中获得。页面缓存每次访问页面的时候,都会先检测相应的缓存页面文件是否存在,如果不存在,就连接数据库,得到数据,显示页面并同时生成缓存页面文件,这样下次访问的时候页面文件就发挥作用了。(模板引擎和网上常见的一些缓存类通常有此功能)内存缓存Memcached是高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。dbcached 是一款基于Memcached 和 NMDB 的分布式 key-value 数据库内存缓存系统。以上的缓存技术虽然能很好的解决频繁查询数据库的问题,但其缺点在在于数据无时效性,下面介绍项目中常用的方法:时间触发缓存检查文件是否存在并且时间戳小于设置的过期时间,如果文件修改的时间戳比当前时间戳减去过期时间戳大,那么就用缓存,否则更新缓存。设定时间内不去判断数据是否要更新,过了设定时间再更新缓存。以上只适合对时效性要求不高的情况下使用 ,否则请看下面。内容触发缓存当插入数据或更新数据时,强制更新缓存。在这里我们可以看到,当有大量数据频繁需要更新时,最后都要涉及磁盘读写操作。怎么解决呢?我在日常项目中,通常并不缓存所有内容,而是缓存一部分不经常变的内容来解决。但在大负荷的情况下,最好要用共享内存做缓存系统。其缺点是,因为每次请求仍然要经过PHP解析,在大负荷的情况下效率问题还是比效严重,在这种情况下,也许会用到静态缓存。静态缓存这里所说的静态缓存是指HTML缓存,HTML缓存一般是无需判断数据是否要更新的,因为通常在使用HTML的场合一般是不经常变动内容的页面。数据更新的时候把HTML也强制更新一下就可以了。
0
0 1414天前