【ThinkPHP5】 学习笔记-转载

复制代码
project  应用部署目录
├─application           应用目录(可设置)
│  ├─common             公共模块目录(可更改),不肯直接通过浏览器访问,详细办法请通过继承或者其他。
│  ├─index              模块目录(可更改)
│  │  ├─config.php      模块配置文件
│  │  ├─common.php      模块函数文件
│  │  ├─controller      控制器目录
│  │  ├─model           模型目录
│  │  ├─view            视图目录
│  │  └─ ...            更多类库目录
│  ├─command.php        命令行工具配置文件
│  ├─common.php         应用公共(函数)文件
│  ├─config.php         应用(公共)配置文件
│  ├─database.php       数据库配置文件,可设置本项目的数据库情况。
│  ├─tags.php           应用行为扩展定义文件,相当于钩子。对框架进行拓展。改变框架执行流程。
│  └─route.php          路由配置文件,配置这个选项可以美化URL
├─extend                扩展类库目录(可定义),下载第三方的库使用的。不包含composer
├─public                WEB 部署目录(对外访问目录)
│  ├─static             静态资源存放目录(css,js,image)
│  ├─index.php          应用入口文件
│  ├─router.php         快速测试文件,可以用来在没安装apache的时候启动框架的web服务器。
│  └─.htaccess          用于 apache 的重写
├─runtime               应用的运行时目录(可写,可设置)。日志、缓存和编译文件等。
├─vendor                第三方类库目录(Composer),通过composer安装的文件都会出现在这里。
├─thinkphp              框架系统目录
│  ├─lang               语言包目录
│  ├─library            框架核心类库目录
│  │  ├─think           Think 类库包目录
│  │  └─traits          系统 Traits 目录
│  ├─tpl                系统模板目录
│  ├─.htaccess          用于 apache 的重写
│  ├─.travis.yml        CI 定义文件
│  ├─base.php           基础定义文件,定义一些常量。
│  ├─composer.json      composer 定义文件
│  ├─console.php        控制台入口文件
│  ├─convention.php     惯例配置文件,框架默认的配置文件
│  ├─helper.php         助手函数文件(可选)
│  ├─LICENSE.txt        授权说明文件
│  ├─phpunit.xml        单元测试配置文件
│  ├─README.md          README 文件
│  └─start.php          框架引导文件
├─build.php             自动生成定义文件(参考)
├─composer.json         composer 定义文件
├─LICENSE.txt           授权说明文件
├─README.md             README 文件
├─think                 命令行入口文件
复制代码

 

未提及到的个别目录:

public\robots:给搜索引擎使用的,可以设置哪些不给搜索引擎爬取等。比如前台希望能,而后台不希望给搜索引擎看到。配置这个文件即可。

\thinkphp\tpl\default_index.tpl:自动生成的控制器模板文件

\thinkphp\tpl\dispatch_jump.tpl:网站跳转成功或者失败而出现的文件。

\thinkphp\tpl\page_trace.tpl:调试时候显示的模板文件。

\thinkphp\tpl\think_exception.tpl:异常时候的模板文件

application\extend\:放第三方的类库的,如exmail,支付函数等等。

public\static\:拿来放第三方的静态资源的,比如jquery,编辑器等等。

application\admin\extra\:放extend里面的第三方类库对应的配置文件的。

 

 

————关于common模块的使用:由于common模块比较特殊,是不能直接访问的。但是common是可以给其他模块调用的。所以采用继承的方式进行使用。

以下为例,在index/Index/user方法使用common\Index控制下的a方法:

复制代码
<?php
namespace app\index\controller;
use app\common\controller\Index as commonIndex;  //声明使用common\Index控制器,并重命名为commonIndex,这时候其实是个类了。

class Index extends commonIndex //采用继承的方式
{
    public function user (){
        return $this->a();  //请注意:这里是$this,代表的就是extend的commonIndex这个类。
    }
}
复制代码

————以上只是一种方法,可以不用继承,而在用的时候先进行实例化,再进行->方法操作即可。效果相同。

 

TP框架的惯例配置:在ThinkPHP的convention.php里面。

 

 应用配置:

开发中不允许改变框架的任何文件,否则后期升级框架就会非常的麻烦。一旦升级就很多东西都没了。那么如何自定义配置呢?在application中配置config.php即可。

 

请注意:TP5.0.10的调试模式的开启和关闭是在config.php里面的。而且默认是关闭的。卧槽!

 

 加载模板采用return $this->fetch();如下

复制代码
<?php
namespace app\admin\controller;
use think\controller;
class Index extends Controller
{
    public function index(){
        return $this->fetch();
    }
}
复制代码

 ——请注意:这时候的fetch()是默认加载跟方法同名的index.html模板的,如果你想加载相同控制器下的login模板,直接写return $this->fetch('login');如果你想跨模块调用,可以直接一级级往上改变,比如return $this->fetch('index/index');

 

关于数据库的设置:

 

 

 模型层:用来操作数据库的,所以,一个模型文件通常对应一个数据表名字,并且与数据表的名字一致。比如:

这是我的数据表的名字:

这是我的操作的模型层的文件名:(前缀blog_在database.php文件里面设置过了。)

 

获取input进来的数据:通过input('post.')来获取所有。.后面加参数就是获取某个

复制代码
个function login()
    {
        //测试数据库连接
        //$data = db('admin')->where('admin_id',2)->find();
        //dump($data);
        if (request()->isPost()) {
            //halt($_POST);
            //将请求交给模型层进行处理。
            //$res = (new Admin())->login(input('post.'));
            dump(input('post.'));
        }
}
复制代码

 

get传参的演示:

前端:

<a href="{:url('admin/index/useredit',['admin_id'=>$user.admin_id,])}" class="edit btn btn-primary">编辑</a>

控制器:

$admin_id=input('admin_id',0);
dump($admin_id);

 

ajax异步发数据以及请求:

后台:

if (request()->isPost()){
    //通过ajax接收来自前端的admin_id,才能确定要操作的是哪一个。
    if(input('admin_id')){
        return input('admin_id');
    }

前端:

复制代码
$('.edit').click(function () {
    adminId = $(this).attr('idx');

    $.ajax({
        type: "POST",
        url: "{:url('admin/index/useredit')}",
        data: {
            admin_id:adminId,
        },
        dataType: "json",
        timeout:3000,
        success: function(data){
            if(data){
                alert(data);
            }
        }
    });
})
复制代码

 

将数据添加/插入数据库:

$data = [
    'admin_username' => input('post.admin_username'),
    'admin_password' => md5(input('post.admin_password')),
];
db('admin')->insert($data);

 

验证器:

这是5.0推荐的验证方式,为具体的验证场景或者数据表定义好验证器类,直接调用验证类的check方法即可完成验证,下面是一个例子:

我们定义一个\app\index\validate\User验证器类用于User的验证。

 

前端验证输入:

原先我是用JQ写的,如下:

复制代码
var adminusername = $('#adminusername').val();
var adminpassword = $('#adminpassword').val();
var captcha = $('#captcha').val();
if(adminusername == '' || adminpassword == ''){
    layer.alert('账号或密码不能为空!');
    return false;
}
if(captcha == ''){
    layer.alert('请输入验证码!');
    return false;
}                
复制代码

 

 

 

以下为实例,登录的例子代码:

目录结构如下:

前端登录界面的login.html

复制代码
<form action="login" method="post">
    <h2 class="text-center text-primary">后台管理</h2>
    <div class="form-group">
        <label for="adminusername">账号:</label>
        <input required type="text" id="adminusername" name="admin_username" class="form-control" placeholder="请输入用户名">
    </div>
    <div class="form-group">
        <label for="adminpassword">密码:</label>
        <input required type="password" id="adminpassword" name="admin_password" class="form-control" placeholder="请输入密码">
    </div>
    <div class="form-group">
        <label for="captcha">验证码</label>
        <input required type="text" id="captcha" name="captcha" class="form-control" placeholder="请输入验证码">
    </div>
    <div><img src="{:captcha_src()}" alt="captcha" onclick="this.src = this.src + '?' + Math.random()"/></div>
    <div>
        <input type="submit" class="btn btn-success form-control" value="登录">
    </div>
    <div class="text-center text-info">Copyright Linfeng © 2017 - 2027</div>
</form>
复制代码

控制器Login.php的代码:

复制代码
<?php

namespace app\admin\controller;

use think\controller;
use app\common\model\Admin;

class Login extends Controller
{
    function login()
    {
        //测试数据库连接
        //$data = db('admin')->where('admin_id',2)->find();
        //dump($data);
        if (request()->isPost()) {
            //将请求交给模型层进行处理,我们在模型层设置了验证以及返回的错误信息了。
            $res = (new Admin())->login(input('post.'));
            if ($res['valid']){
                //说明登录成功
                $this->success($res['msg'],'admin/index/index');exit;
            }else{
                //说明登录失败
                $this->error($res['msg']);exit;
            }
        }
        //加载模板
        return $this->fetch();
    }

}
复制代码

模型层common/Admin.php

复制代码
<?php

namespace app\common\model;

use think\Loader;
use think\Model;

class Admin extends Model
{
    protected $pk = 'admin_id';//主键
    protected $table = 'blog_admin';//请注意,必须得写完整的表名

    /*
     * 登录
     * */
    public function login($data)
    {
        //1、执行验证(账号密码是否输入、验证码是否输入和正确),放在了validate/Admin.php
        $validate = Loader::validate('Admin');
        if (!$validate->check($data)){
        //如果验证不成功,返回错误信息给控制器。
            return ['valid' => '0','msg' => $validate->getError()];
        }

        //2、比对用户名和密码是否正确
        $userinfo = $this->where('admin_username',$data['admin_username'])->where('admin_password',md5($data['admin_password']))->find();
        if (!$userinfo){
            //说明在数据库未匹配到该用户
            return [
                'valid' => '0',
                'msg' => '用户名或者密码错误',
            ];
        }

        //3、正确,将用户信息存入session中。
        session('admin.admin_id',$userinfo['admin_id']);
        session('admin.admin_username',$userinfo['admin_username']);
        return [
            'valid' => '1',
            'msg' => '登录成功!',
        ];
    }
}
复制代码

验证模块validate\Admin.php

复制代码
<?php

namespace app\admin\validate;

use think\Validate;

class Admin extends Validate
{
    protected $rule = [
        /*以下注释是因为前端做了处理,不然总是因为未输入而跳转,麻烦。*/
        /*'admin_username' => 'require',
        'admin_password' => 'require',
        'captcha' => 'require|captcha',*/
        'captcha' => 'require|captcha',
    ];
    protected $message = [
        /*'admin_username.require' => '请输入用户名',
        'admin_password.require' => '请输入密码',
        'captcha.require' => '请输入验证码',*/
        'captcha.captcha' => '验证码不正确',
    ];
}
复制代码

公共层Common.php

复制代码
<?php

namespace app\admin\controller;

use think\controller;
use think\Request;

class Common extends Controller
{
    public function __construct(Request $request = null)
    {
        parent::__construct($request);
        //执行登录验证,以下相当于$_SESSION['admin']['admin_id'],这个写法在TP框架中不能用了。
        if (!session('admin.admin_id')) {
            $this->redirect('admin/login/login');
        }
    }
}
复制代码

 

 

 

关于模型层的举例:

模型:

namespace app\index\model;
use think\Model;
class User extends Model//
{

}

控制器里面的调用方式:

复制代码
namespace app\index\controller;
use app\index\model\User;//使用
class Index {
      public function index()
      {
          $user = new User();//
      }
}
复制代码

 

 请求:可以使用 think\Request,即use think\Request; 

复制代码
$request = Request::instance();
        // 获取当前域名
        echo 'domain: ' . $request->domain() . '<br/>';
        // 获取当前入口文件
        echo 'file: ' . $request->baseFile() . '<br/>';
        // 获取当前URL地址 不含域名
        echo 'url: ' . $request->url() . '<br/>';
        // 获取包含域名的完整URL地址
        echo 'url with domain: ' . $request->url(true) . '<br/>'; // 获取当前URL地址 不含QUERY_STRING
        echo 'url without query: ' . $request->baseUrl() . '<br/>'; // 获取URL访问的ROOT地址
        echo 'root:' . $request->root() . '<br/>';
        // 获取URL访问的ROOT地址
        echo 'root with domain: ' . $request->root(true) . '<br/>'; // 获取URL地址中的PATH_INFO信息
        echo 'pathinfo: ' . $request->pathinfo() . '<br/>';
        // 获取URL地址中的PATH_INFO信息 不含后缀
        echo 'pathinfo: ' . $request->path() . '<br/>';
        // 获取URL地址中的后缀信息
        echo 'ext: ' . $request->ext() . '<br/>';
复制代码

 

可以通过Request对象完成全局输入变量的检测,获取和安全过滤,包括$_GET/$_POST等等

 

验证码:

后面加随机数,是因为每次的src都不一样,就会重新请求验证码类。

<div><img src="{:captcha_src()}" alt="captcha" onclick="this.src = this.src + '?' + Math.random()"></div>

同时,验证码提供了配置项,所以可以直接加在application下的config.php文件里面。

 

独立验证(专门建验证文件请查看上面的验证)

任何时候,都可以使用Validate类进行独立的验证操作,例如:

复制代码
$validate = new Validate([
    'name'  => 'require|max:25',
    'email' => 'email'
]);
$data = [
    'name'  => 'thinkphp',
    'email' => 'thinkphp@qq.com'
];
if (!$validate->check($data)) {
    dump($validate->getError());
}
复制代码

————请注意:上面的例子的$data经常会由其他地方传进来进行验证。如:

复制代码
public function pass($data)
{
    //1、执行验证
    $validate = new Validate(
        [
            //'admin_id' => 'require',
            'admin_password' => 'require',
            'new_password' => 'require',
            'confirm_password' => 'require|confirm:new_password',//本字段与new_password进行比对。
        ],
        [
            'admin_password.require' => '请输入原密码',
            'new_password.require' => '请输入新密码',
            'confirm_password.require' => '请输入确认密码',
            'confirm_password.confirm' => '两次密码必须一致',
        ]
    );

    if (!$validate->check($data)) {
        dump($validate->getError());
    }
    //2、原始密码是否正确
    //3、修改密码
}
复制代码

 

 

 

 模板继承:

1、在view模块下建立模板base.html,并在其主区域用标签{block name='main'} {/block}包含起来。

 

2、在view\index\index.html继承base.html,并替换(其实是填充,之前并没有内容){block name='main'} {/block}里面的内容。

 

————这里我们需要特别注意:需要在base.html上写一个{block name="script"}{/block},继承界面的JS写在这个区域的。如下:上面的JS是公用的,下面的是拿来放每个界面不同的JS的。

 

  

函数:在php文件中可以直接使用,在模板中使用需要加冒号: 

 

在模板中使用函数session:得加冒号:如下:

<strong class="font-bold">{:session('admin.admin_username')}</strong>

 ——上面的session('admin.admin_username')是TP框架定义的session函数。

 

在模板中生成地址,采用url函数,记得加冒号:

<li><a href="{:url('admin/index/userlist')}">用户列表</a></li>

 form表单填写地址,直接填写模块/控制器/方法名:

 <form action="{:url('admin/index/useredit')}" method="post">

————当然,action可以不写,会传到页面对应的方法上。{ }其实就是相当于在html界面的<?php ?>而已。

 

通过ajax传参:

复制代码
$('.edit').click(function () {
    adminId = $(this).attr('idx');

    $.ajax({
        type: "POST",
        url: "{:url('admin/index/useredit')}",
        data: {
            admin_id: adminId,
        },
        dataType: "json",
        timeout: 3000,
        success: function () {
            if (data) {
                alert(1);
            }
        }
    });
})
复制代码

 

 

 

volist的应用:

控制器代码:

function userlist(){
    $users = db('admin')->select();
    //在模板中分配变量
    $this->assign('users',$users);
    return $this->fetch();
}

前端代码:

复制代码
{volist name="users" id="vo"}
    <tr>
        <td>{$vo.admin_id}</td>
        <td>{$vo.admin_username}</td>
        <td>{$vo.admin_password}</td>
        <td><a title="">删除</a></td>
    </tr>
{/volist}
复制代码

 

 

 关于TP5中如何让左侧导航栏显示和隐藏的问题:

由于一个函数对应一个html界面,所以,我们可以在函数中直接给模板分配变量。这样就省去了采用cookie等方法记住所点击的界面了。如下:

控制器代码:

复制代码
function index(){
    //分配所在界面,以便于展开导航栏对应的模块。
    $this->assign('active_li','index');

    //加载模板
    return $this->fetch();
}
复制代码

请注意,我们向外分配的变量为当前的函数名(一个函数对应一个界面),然后展开导航条对应的模块,__FUNCTION__在php中是用于获取当前函数名的。上面可以改成:

复制代码
function index(){
    //分配所在界面的方法,以便于展开导航栏对应的模块。
    $this->assign('active_li',__FUNCTION__);

    //加载模板
    return $this->fetch();
}
复制代码

 

 

前端模板代码:

var activeLi = '{$active_li}';
$('.' + activeLi).addClass('active');

 

posted @ 2018-01-26 11:43  程镜  阅读(263)  评论(0编辑  收藏  举报