168
133
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1116
【一】部门列表展示分析:123①控制器DeptController.class.php②方法showList(不要使用list方法,因为list是关键词)③模板文件:showList.html下面按步骤编写①创建方法showList来展示模板12345class DeptController extends Controller{ public function showList(){ $this->display(); }}②将模板文件showList.html复制到View/Dept下(因为控制器为Dept,方法为showList,所以要一一对应)③修改静态资源路径④修该showList方法,获取部门数据。并传递到模板123456public function showList(){ $model = M('dept');//模型实例化 $data = $model->order('sort asc')->select();//条件查询,升序排列 $this->assign('data',$data);//变量分配传递到模板 $this->display(); }⑤模板遍历读取数据12345678910111213141516171819<table border="1" cellspacing="0"> <tr> <td>id</td><td>部门</td><td>所属部门</td><td>排序</td><td>备注</td><td>编辑数据</td><td>删除数据</td> </tr> <volist name='data' id='vol'> <tr> <td class="num">{$vol.id}</td> <td class="name">{$vol.name}</td> <td class="procress"> <if condition="$vol.pid == 0"> 顶级部门 <else/> 二级部门 </if> </td> <td class="node">{$vol.sort}</td> <td class="time">{$vol.remark}</td> <td><a href="javascript:;">编辑</a></td> <td><a href="javascript:;">删除</a></td> </tr> </volist></table>注意:1. 模板的if判断,必须加空格<if condition="$vol.pid == 0">顶级部门</if>2.<else />加/【二】部门编辑分析:控制器:DeptController.class.php方法:edit(展示模板】处理提交)模板:edit.html下面按步骤编写代码(1)编写edit方法,实现模板展示1234public function edit(){//展示模板 $this->display();}(2)修改编辑按钮,跳页时带上id1<td><a href="__CONTROLLER__/edit/id/{$vol.id}">编辑</a></td>(3)复制模板文件edit.html到指定位置,Admin/View/Dept/edit.html;修改静态资源路径(4)修改edit方法,展示原来数据12345id:<input type="text" name="id" readonly="readonly" value="{$data.id}"><br/>部门:<input type="text" name="name" value="{$data.name}"><br/>所属部门:<select> <option value="0">顶级部门</option> <volist name="info" id="vol"> <option value="{$vol.id}">{$vol.name}</option> </volist></select><br/>排序:<input type="text" name="sort" value="{$data.sort}"><br/>备注:<input type="text" name="id" value="{$data.remark}"><br/>(5)处理表单提交页面隐藏域:因为系统限制不能执行批量修改,所以修改时必须指定主键。所以必须添加一个隐藏域,来传递id12345678910111213<form action="" method="post"> id:<input type="hidden" name="id" value="{$data.id}"><br/> <!-- 或者$Think.get.id --> 部门:<input type="text" name="name" value="{$data.name}"><br/> 所属部门: <select name="pid"> <option value="0">顶级部门</option> <volist name="info" id="vol"> <option value="{$vol.id}">{$vol.name}</option> </volist> </select><br/> 排序:<input type="text" name="sort" value="{$data.sort}"><br/> 备注:<input type="text" name="remark" value="{$data.remark}"><br/> <button>提交</button></form>jquery提交:12345<script type="text/javascript"> $(document).ready(function(){ $('button').on('click',function(){ $('form').submit();//提交表单 }) })</script>(6)数据的保存,修改edit方法后的代码1public function edit(){//展示模板或者post请求 if (IS_POST){ $post = I('post.'); // dump($post);die; $model = M('dept'); //保存操作 $result = $model->save($post); if ($result !== false) { $this->success('修改成功',U('showList'),3); }else{ $this->error('修改失败'); } }else{ //接收id $id=I('get.id'); //实例化模型 $model = M('dept'); //查询指定记录 $data = $model->find($id); // 查询全部的部门信息(不包含当前级),同于下拉。因为包含自己所在级别会在递归时陷入死循环? $info = $model->where('id != '.$id)->select(); //变量分配 $this->assign('data',$data); $this->assign('info',$info); //展示模板 $this->display(); } }【三】部门删除分析控制器:DeptController.class.php方法:del模板:删除不需要模板文件,因为删除就是个处理数据过程。和登出一样说明:有单个删除,也有批量删除。而编辑只能单个编辑,不能批量编辑。(1)修改模板,添加复选框1234567891011121314151617181920212223<table border="1" cellspacing="0"> <tr> </td>><td>id</td><td>部门</td> <td>所属部门</td><td>排序</td><td>备注</td><td>编辑数据</td><td><a href="javascript:;" class="del">删除</a</td> </tr> <volist name='data' id='vol'> <tr> <td class="num">{$vol.id}</td> <td class="name">{$vol.name}</td> <td class="procress"> <if condition="$vol.pid == 0"> 顶级部门 <else/> 二级部门 </if> </td> <td class="node">{$vol.sort}</td> <td class="time">{$vol.remark}</td> <td><a href="__CONTROLLER__/edit/id/{$vol.id}">编辑</a></td> <td><input type="checkbox" class="deptid" value="{$vol.id}"></td> </tr> </volist></table>(2)点击删除按钮,实现删除①点击删除,获取复选框的值(jquery实现)。之后到php删除方法12345678910<script type="text/javascript"> $(document).ready(function(){ $('.del').on('click',function(){ var id = ''; $.each($('input:checkbox:checked'),function(){ id += $(this).val()+','; }); // 去掉最后的,通过截取字符串获取 id = id.substring(0,id.length-1); //带着参数跳转到del方法 window.location.href = '__CONTROLLER__/del/id/'+id;//删除方法和展示方法的控制器是同级,所以用模板常量__CONTROLLER__ }) })</script>②编写del方法,实现删除//真删除---批量和单个删除123456789public function del(){ //接收参数 $id = I('get.id'); //模型实例化 $model = M('dept'); //删除 $result = $model->delete($id); //判断结果,删除成功或失败都会跳转到列表页,所以不用加入跳转链接 if ($result) { $this->success('删除成功'); }else{ $this->error('删除失败'); } }以上就是ThinkPHP部门管理功能的全部内容。相关参考:thinkphp教程以上就是部门管理功能的实现的详细内容
0
0 1396天前
1003
ThinkPHP6 Workerman 基本使用WorkermanWorkerman是一款纯PHP开发的开源高性能的PHP socket 服务器框架。被广泛的用于手机app、手游服务端、网络游戏服务器、聊天室服务器、硬件通讯服务器、智能家居、车联网、物联网等领域的开发。 支持TCP长连接,支持Websocket、HTTP等协议,支持自定义协议。基于workerman开发者可以更专注于业务逻辑开发,不必再为PHP Socket底层开发而烦恼。安装首先通过 composer 安装1composer require topthink/think-worker使用使用Workerman作为HttpServer在命令行启动服务端1php think worker然后就可以通过浏览器直接访问当前应用1http://localhost:2346linux下面可以支持下面指令1php think worker [start|stop|reload|restart|status]workerman的参数可以在应用配置目录下的worker.php里面配置。由于onWorkerStart运行的时候没有HTTP_HOST,因此最好在应用配置文件中设置app_hostSocketServer在命令行启动服务端(需要2.0.5+版本)1php think worker:server默认会在0.0.0.0:2345开启一个websocket服务。如果需要自定义参数,可以在config/worker_server.php中进行配置,包括:并且支持workerman所有的参数(包括全局静态参数)。也支持使用闭包方式定义相关事件回调。12345678return [ 'socket' => 'http://127.0.0.1:8000', 'name' => 'thinkphp', 'count' => 4, 'onMessage' => function($connection, $data) { $connection->send(json_encode($data)); },];也支持使用自定义类作为Worker服务入口文件类。例如,我们可以创建一个服务类(必须要继承 think\worker\Server),然后设置属性和添加回调方法1234567891011<?phpnamespace app\http;use think\worker\Server;class Worker extends Server{ protected $socket = 'http://0.0.0.0:2346'; public function onMessage($connection,$data) { $connection->send(json_encode($data)); }}支持workerman所有的回调方法定义(回调方法必须是public类型)然后在worker_server.php中增加配置参数:123return [ 'worker_class' => 'app\http\Worker',];定义该参数后,其它配置参数均不再有效。在命令行启动服务端1php think worker:server然后在浏览器里面访问1http://localhost:2346如果在Linux下面,同样支持reload|restart|stop|status 操作1php think worker:server reload推荐教程:《PHP》以上就是在 ThinkPHP6 中使用 Workerman的详细内容
0
0 1396天前
1017
安装ThinkPHP怎么安装,我就不细说了,官方文档-安装ThinkPHP说的很全了,可以通过Composer、Git或者直接去ThinkPHP官网下载zip包,我安装的版本是5.0.24测试运行下载安装完毕后,如果项目是下载目录是你本地服务器的项目根目录下,可以直接在浏览器输入地址http://localhost/thinkphp5/public/,就可以进入到ThinkPHP5的默认欢迎页,如下图所示,这就说明ThinkPHP5已经安装成功除了上面的这个方式的地址运行,我们也可以通过Apache或者Nginx配置虚拟主机实现项目的访问,有兴趣的可以网上查看具体教程,然后配置虚拟主机进行访问。下面进入正题,我们来逐步分析ThinkPHP5的执行流程……入口文件(public\index.php)打开public\index.php文件后,我们可以看到,入口文件原始代码如下12345// [ 应用入口文件 ]// 定义应用目录define('APP_PATH', __DIR__ . '/../application/');// 加载框架引导文件require __DIR__ . '/../thinkphp/start.php';入口文件代码很简洁,就两行代码,作用分别为12define('APP_PATH', __DIR__ . '/../application/');定义应用目录的常量APP_PATHrequire __DIR__ . '/../thinkphp/start.php';加载框架引导文件除了上面的这两个作用外,我们还可以额外在入口文件中,定义我们自己的常量,例如添加一行代码define('PUBLIC_PATH', __DIR__ .'/../public');定义public目录的常量以及一些预处理等加载框架引导文件(thinkphp\start.php)同样的,进入thinkphp\start.php文件后,我们可以知道,代码并不多123456namespace think;// ThinkPHP 引导文件// 1. 加载基础文件require __DIR__ . '/base.php';// 2. 执行应用App::run()->send();从这简短的两行代码,我们可以看到,主要左右有两个12require __DIR__ . '/base.php';加载基础文件App::run()->send();执行应用下面两个大点,将具体介绍这两个左右都做了什么加载基础文件(thinkphp\base.php)我们继续打开thinkphp\base.php文件,发现这个文件终于不再像前两个文件那样,只有两行代码了……12345678910111213141516171819202122232425262728293031323334353637383940414243444546define('THINK_VERSION', '5.0.24');define('THINK_START_TIME', microtime(true));define('THINK_START_MEM', memory_get_usage());define('EXT', '.php');define('DS', DIRECTORY_SEPARATOR);defined('THINK_PATH') or define('THINK_PATH', __DIR__ . DS);define('LIB_PATH', THINK_PATH . 'library' . DS);define('CORE_PATH', LIB_PATH . 'think' . DS);define('TRAIT_PATH', LIB_PATH . 'traits' . DS);defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']) . DS);defined('ROOT_PATH') or define('ROOT_PATH', dirname(realpath(APP_PATH)) . DS);defined('EXTEND_PATH') or define('EXTEND_PATH', ROOT_PATH . 'extend' . DS);defined('VENDOR_PATH') or define('VENDOR_PATH', ROOT_PATH . 'vendor' . DS);defined('RUNTIME_PATH') or define('RUNTIME_PATH', ROOT_PATH . 'runtime' . DS);defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH . 'log' . DS);defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH . 'cache' . DS);defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH . 'temp' . DS);defined('CONF_PATH') or define('CONF_PATH', APP_PATH); // 配置文件目录defined('CONF_EXT') or define('CONF_EXT', EXT); // 配置文件后缀defined('ENV_PREFIX') or define('ENV_PREFIX', 'PHP_'); // 环境变量的配置前缀// 环境常量define('IS_CLI', PHP_SAPI == 'cli' ? true : false);define('IS_WIN', strpos(PHP_OS, 'WIN') !== false);// 载入Loader类require CORE_PATH . 'Loader.php';// 加载环境变量配置文件if (is_file(ROOT_PATH . '.env')) { $env = parse_ini_file(ROOT_PATH . '.env', true); foreach ($env as $key => $val) { $name = ENV_PREFIX . strtoupper($key); if (is_array($val)) { foreach ($val as $k => $v) { $item = $name . '_' . strtoupper($k); putenv("$item=$v"); } } else { putenv("$name=$val"); } }}// 注册自动加载\think\Loader::register();// 注册错误和异常处理机制\think\Error::register();// 加载惯例配置文件\think\Config::set(include THINK_PATH . 'convention' . EXT);仔细一看,发现代码虽然有六十多行,但是,代码的作用却显而易见,作用主要有以下六点使用define('', '')函数定义了很多个系统常量,外加两个环境常量引入loader类(thinkphp\library\think\loader.php),供后续使用加载环境变量配置文件(环境变量配置文件名为.env,这个文件不一定存在,都是在实际开发过程中根据需要加上去的)调用\think\Loader::register()注册自动加载机制注册系统自动加载Composer自动加载支持注册命名空间定义加载类库映射文件,存在于runtime缓存目录下classmap.php自动加载extend目录调用\think\Error::register()注册异常和错误处理机制加载惯例配置文件(thinkphp\convention.php)执行应用(thinkphp\library\think\App.php)下的run方法为了方便,这个run方法的代码虽然有点长,但是我还是选择把整个方法贴出来,别打我哈12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879/** * 执行应用程序 * @access public * @param Request $request 请求对象 * @return Response * @throws Exception */public static function run(Request $request = null){ $request = is_null($request) ? Request::instance() : $request; try { $config = self::initCommon(); // 模块/控制器绑定 if (defined('BIND_MODULE')) { BIND_MODULE && Route::bind(BIND_MODULE); } elseif ($config['auto_bind_module']) { // 入口自动绑定 $name = pathinfo($request->baseFile(), PATHINFO_FILENAME); if ($name && 'index' != $name && is_dir(APP_PATH . $name)) { Route::bind($name); } } $request->filter($config['default_filter']); // 默认语言 Lang::range($config['default_lang']); // 开启多语言机制 检测当前语言 $config['lang_switch_on'] && Lang::detect(); $request->langset(Lang::range()); // 加载系统语言包 Lang::load([ THINK_PATH . 'lang' . DS . $request->langset() . EXT, APP_PATH . 'lang' . DS . $request->langset() . EXT, ]); // 监听 app_dispatch Hook::listen('app_dispatch', self::$dispatch); // 获取应用调度信息 $dispatch = self::$dispatch; // 未设置调度信息则进行 URL 路由检测 if (empty($dispatch)) { $dispatch = self::routeCheck($request, $config); } // 记录当前调度信息 $request->dispatch($dispatch); // 记录路由和请求信息 if (self::$debug) { Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info'); Log::record('[ HEADER ] ' . var_export($request->header(), true), 'info'); Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info'); } // 监听 app_begin Hook::listen('app_begin', $dispatch); // 请求缓存检查 $request->cache( $config['request_cache'], $config['request_cache_expire'], $config['request_cache_except'] ); $data = self::exec($dispatch, $config); } catch (HttpResponseException $exception) { $data = $exception->getResponse(); } // 清空类的实例化 Loader::clearInstance(); // 输出数据到客户端 if ($data instanceof Response) { $response = $data; } elseif (!is_null($data)) { // 默认自动识别响应输出类型 $type = $request->isAjax() ? Config::get('default_ajax_return') : Config::get('default_return_type'); $response = Response::create($data, $type); } else { $response = Response::create(); } // 监听 app_end Hook::listen('app_end', $response); return $response;}这大概90行的代码,具体做了什么呢,结合注释分析,主要有以下几步的功能第一步:处理变量$request,保证有效有用不为null第二步:self::initCommon()调用当前控制器中的initCommon()方法,负责初始化应用,并返回配置信息Loader::addNamespace(self::$namespace, APP_PATH);注册命名空间self::init()调用本类的init()方法初始化应用加载各种配置文件加载行为扩展文件加载公共文件加载语言包应用调试模式相关处理加载额外文件,通过配置项extra_file_list的值去加载相关文件date_default_timezone_set($config['default_timezone']);设置系统时区调用Hook::listen('app_init');监听app_init标签的行为第三步:判断是否进行模块或者控制器的绑定第四步:系统语言设置和加载第五步:self::routeCheck($request, $config)加载当前控制器的routeCheck()方法进行路由检测先进行路由地址配置检测,先读取缓存路由,不存在再导入路由文件配置无路由配置,直接解析模块/控制器/操作返回module模块信息(模块名、控制器名和操作方法名)第六步:开启调试模式下,记录路由和请求信息的日志第七步:self::exec($dispatch, $config)调用控制器中的exec()方法执行调用分发根据用户请求类型进行分发处理,这里是module模块类型调用self::module()执行模块,进行模块部署和初始化,获取和设置当前控制器名和操作名第八步:清空类的实例化,并输出相应格式的数据到客户端,即用户看到的输出界面推荐教程:《PHP》《ThinkPHP教程》以上就是分析 ThinkPHP5 加载流程的详细内容
0
0 1396天前
1089
空控制器在ThinkPHP6的手册中只占据了一个很小很小的篇幅,以至于空控制器是什么,甚至这个词语,可能很多程序员并没有听过、没有用过,那么这次给大家用实际例子说一说ThinkPHP6的空控制器。我们在ThinkPHP6的官方手册中搜索“空控制器”关键字,就可以找到空控制器的章节内容。我们先看看空控制器的官方定义:空控制器的概念是指当系统找不到指定的控制器名称的时候,系统会尝试定位当前应用下的空控制器( Error )类,利用这个机制我们可以用来定制错误页面和进行URL的优化。也就是说我们可以用空控制器来定制我们的错误页面。手册中是以单应用举例,但是实际情况我们项目大部分都是多应用,所以接下来我们以多应用举例。假设我们项目域名www.xiangmu.com,我们有index和demo两个应用,两个应用下分别有各自的index控制器和index方法。1、找不到方法。如果我们在浏览器中随便输入www.xiangmu.com/index/index/a,这个地址会访问到index应用下index控制器中的a方法,但是我们a方法并不存在,如果能拒绝这种无效的请求呢?那我们本节的空控制器就登场了。我们在index控制中加入下面方法:123public function __call($method, $args){ return 'error request!';}只要访问index控制中找不到的方法,都会走到__call这里。那么既然已经走到了__call(),对于不存在的页面,我们是不是可以做个404.html,用call()去渲染这个模板呢。2、找不到控制器。上面是找不到方法,如果找不到控制器怎么办?我在浏览器中随便输入控制器,www.xiangmu.com/index/a/a,实际上我们没有a控制器也没有a方法,如果能拒绝这种无效的请求呢?那用下面的Error.php控制器就可以解决,加入当前访问的是index应用,我们就把Error.php放在index应用下。同理我们也可以设置404等错误页面哦。1234567891011<?phpnamespace app\index\controller; use app\BaseController; class Error extends BaseController{ public function __call($method, $args){ return 'error request!'; }}以上就是关于空控制器的相关讲解,赶快去试试吧!以上就是说一说ThinkPHP6的空控制器的详细内容
0
0 1396天前