精华内容
下载资源
问答
  • Thinkphp6(tp6) 更新笔记
    2022-03-03 16:27:34

    composer create-project topthink/think tp
    cd tp
    composer require topthink/think-multi-app
    composer require topthink/think-view    //如果你需要使用think-template模板引擎,只需要安装think-view模板引擎驱动。

    composer require topthink/think-captcha   //验证码

    php think make:model Profile

    插入:
    Db::table('user')->insert(["username"=>"xx","passwd"=>2,"email"=>222]);
    查询:
    Db::table('user')->select();   //->find();
    改:
    Db::name("user")->where('id',1)->update([]);
    Db::name("user")->delete(1);
    Db::name("user")->where('id',1)->delete();
    halt($u); //类似于dd;
    ---------------------------------
    通过模型:
    新建一个模型文件并从think\Model下继承Model;
    protected $name = 'user'; //指定数据表名;
    使用时引入:use app\common\model\User;
    使用:$user = new User;        $user->username = "xxx";   //   $user->save();

    更新:
    $user = User::find(1);
    $user->username = 'xxxx'; //save();

    $user = User::find(1);
    $user->delete();

    $user::select([4,5]);

    视图:
    use think\facade\view;

    return View::fetch('demo/index',["id"=>"xx"]) // 默认为index/view/demo/index.html;
    View('demo/index',['user'=>'xiaoming']);
    加载配置文件,额外的
    \think\facade\Config::load('extra/config', 'extra');
    获取变量的值:
    Env::get('database.username', 'root'); // 获取环境变量 如果不存在则使用默认值root
    Env::get('database.username');
    Env::get('database.password');
    Env::get('PATHINFO_PATH');

    use think\facade\Config;
    Config::get('database.default.host');
    判断是否存在某个设置参数:
    Config::has('route.route_rule_merge');
    Config::set(['name1' => 'value1', 'name2' => 'value2'], 'config');
    http://serverName/index.php/shop
    http://serverName/index.php/admin
    /控制器/操作/参数/值…
    也就是说 pathinfo 地址的第一个参数就表示当前的应用名, 后面才是该应用的路由或者控制器/操作。

    如果需要获取当前的应用名, 可以使用 app('http')->getName();
    root_path()   根目录
    base_path()  基础目录
    app_path()  app目录
    runtime_path()
    config_path()
    nginx:
    location / { // …..省略部分代码
      if (!-e $request_filename) {
        rewrite ^(.*)$ /index.php?s=/$1 last;
      }
    }


    Route::get('user/:id','index/Index/hello')->model('\app\index\model\User');//路由绑定模型

    <?php
    namespace app\index\controller;
    use app\index\model\User;
    class Index
    {
    public function hello(User $user)
    {
        return 'Hello,'.$user->name;
    }
    }

    Facade功能可以让类无需实例化而直接进行静态方式调用;
    所以你无需进行实例化就可以很方便的进行方法调用, 例如:
    use think\facade\Cache;
    Cache::set('name','value');
    echo Cache::get('name');

    php think make:middleware Check

    中间件的入口执行方法必须是 handle 方法, 而且第一个参数是 Request 对象, 第二个参数是一个闭包。中间件 handle 方法的返回值必须是一个 Response 对象。
    $http = (new App())->setEnvName('develop')->http;    //加载 .env.develop 配置文件,这样可以区分开发和生产环境;

    use think\facade\Config;
    Config::get('app.app_name');   读取配置文件变量;

    路由的作用远非URL规范这么简单, 还可以实现验证、 权限、 参数绑定及响应设置等功能;
    模型类通常完成实际的业务逻辑和数据封装, 并返回和格式无关的数据。

    中间件主要用于拦截或过滤应用的 HTTP 请求, 并进行必要的业务处理。
    php think version   //控制台应用

    多入口: http://serverName/index.php/think     会访问 /route/app.php
    Route::get('think', function () {
    return 'hello,ThinkPHP!';
    });  中的路由定义;

    $response = $http->path('path/to/app')->run(); //指定应用路径;

    -----------------------------------
    使用admin应用,增加入口文件时引入 name admin,这样使用admin应用;
    //$response = $http->run();
    $response = $http->name('admin')->run();
    获取当前应用名: app('http')->getName();

    URL:
    http://serverName/index.php/控制器/操作/参数/值…

    多应用:
    http://serverName/index.php/应用/控制器/操作/参数/值...

    参数兼容方式:
    http://serverName/index.php?s=/控制器/操作/[参数名/参数值...

    容器类的工作由 think\Container 类完成, 但大多数情况我们只需要通过 app 助手函数或者think\App 类即可容器操作, 如果在服务类中可以直接调用 this->app 进行容器操作。

    $app = app();
    // 判断对象实例是否存在
    isset($app->cache);
    // 注册容器对象实例
    $app->cache = think\Cache::class;
    // 获取容器中的对象实例
    $cache = $app->cache;
    // 调用配置类
    app()->config->get('app_name');
    // 调用session类
    app()->session->get('user_name');
    ----------------------------------------------
    可以给路由绑定模型对象实例
    Route::get('user/:id','index/Index/hello')
    ->model('\app\index\model\User');
    然后在操作方法中自动注入User模型:
    use app\index\model\User;
    public function hello(User $user)
    {
        return 'Hello,'.$user->name;
    }
    生成一个服务类:
    php think make:service FileSystemService
    默认生成的服务类会继承系统的 think\Service , 并且自动生成了系统服务类最常用的两个空方法:register 和 boot 方法。
    register 方法通常用于注册系统服务, 也就是将服务绑定到容器中;
    class FileSystemService extends Service
    {
    public function register()
    {
    $this->app->bind('file_system', FileSystem::class);
    }
    }
    门面为容器中的( 动态) 类提供了一个静态调用接口;说的直白一点, Facade功能可以让类无需实例化而直接进行静态方式调用。
    生成中间件:
    php think make:middleware Check
    中间件 handle 方法的返回值必须是一个 Response 对象。
    中间件支持定义请求结束前的回调机制, 你只需要在中间件类中添加 end 方法。
    1全局中间件->2应用中间件->3路由中间件->4控制器中间件
        1.全局中间件在 app 目录下面 middleware.php 文件中定义;
        2. 应用目录下面增加 middleware.php 文件, 定义方式和全局中间件定义一样, 只是只会在该应用下面生效。
        3. 路由中间件最常用:Route::rule('hello/:name','hello')->middleware(\app\middleware\Auth::class);
            Route::rule('hello/:name','hello')->middleware([\app\middleware\Auth::class, \app\middleware\Check::class]);
    分组中间件:
    Route::group('hello', function(){
    Route::rule('hello/:name','hello');
    })->middleware('auth');
    ------------------------------------
    Route::domain('admin', function(){
    // 注册域名下的路由规则,所有admin都需要登录
    })->middleware('auth');
    传参给中间件:Route::rule('hello/:name','hello')->middleware('auth', 'admin');
    可以统一传入同一个额外参数 Route::rule('hello/:name','hello')->middleware(['auth', 'check'], 'admin');
    或者分开多次调用, 指定不同的参数Route::rule('hello/:name','hello')->middleware('auth', 'admin')->middleware('hello', 'thinkphp');

    如可所有的路由均要添加中间件,可以在 config/route.php中配置;
    闭包中间件:
    Route::group('hello', function(){
    Route::rule('hello/:name','hello');
    })->middleware(function($request,\Closure $next){
    if ($request->param('name') == 'think') {
    return redirect('index/think');
    }
    return $next($request);
    });

    4.控制器中间件:
       控制器中定义 middleware 属性;
    class Index
    {
    protected $middleware = [
    'auth' => ['except' => ['hello'] ],
    'check' => ['only' => ['hello'] ],
    ];
    public function index()
    {
    return 'index';
    }

    事件本身可以是一个类, 并且可以更好的支持事件订阅者。
    事件系统的所有操作都通过 think\facade\Event 类进行静态调用。
    // 触发UserLogin事件 用于执行用户登录后的一系列操作
    Event::trigger('UserLogin');    
    event('UserLogin');    //使用助手函数;

    生成事件:事件类可以通过命令行快速生成
    php think make:event UserLogin
    动态绑定:Event::bind(['UserLogin' => 'app\event\UserLogin']);

    你可以在 event 方法中传入一个事件参数
    // user是当前登录用户对象实例
    event('UserLogin', $user);
    如果是定义了事件类, 可以直接传入事件对象实例
    // user是当前登录用户对象实例
    event(new UserLogin($user));

    可以通过命令行快速生成一个事件监听类  php think make:listener UserLogin
    你可以手动注册一个事件监听
    Event::listen('UserLogin', function($user) {
    //
    });
    或者使用监听类来执行监听
    Event::listen('UserLogin', 'app\listener\UserLogin');
    // 监听所有的模型事件
    Event::listen('model.*', 'app\listener\ModelListen');

    绑定事件:在event.php中:
    return [
    'bind' => [
    'UserLogin' => 'app\event\UserLogin',
    // 更多事件绑定
    ],
    'listen' => [
    'UserLogin' => ['app\listener\UserLogin'],
    // 更多事件监听],]

    事件订阅:
    php think make:subscribe User

    Route::rule('路由表达式', '路由地址', '请求类型');
    Route::rule('new/:id', 'News/update', 'POST');

    Route::rule('new/:id','News/read','GET|POST');
    Route::get('new/<id>','News/read'); // 定义GET请求路由规则
    Route::post('new/<id>','News/update'); // 定义POST请求路由规则
    Route::put('new/:id','News/update'); // 定义PUT请求路由规则
    Route::delete('new/:id','News/delete'); // 定义DELETE请求路由规则
    Route::any('new/:id','News/read'); // 所有请求都支持的路由规则
    Route::get('new/:cate$', 'News/category');  //希望URL进行完全匹配
    Route::get('blog/:id','blog/read')->append(['status' => 1, 'app_id' =>5]);   //隐性传值;
    Route::rule("new/:id",News/read')->name('new_read');

    url('new_read', ['id' => 10]) //生成地址的时候,用name;

    Route::get('item-<name><id?>', 'product/detail')->pattern(['name' => '[a-zA-Z]+', 'id' => '\d+']);

    Route::get('blog/:id','Blog/read');   //路由到控制器的read操作;
    Route::get('blog/:id','\app\index\service\Blog@read'); //路由到类
    Route::get('blog/:id','\app\index\service\Blog::read');  //路由到类的静态方法;
    Route::redirect('blog/:id', 'http://blog.thinkphp.cn/read/:id', 302);重定向
    // 路由到模板文件
    Route::view('hello/:name', 'index/hello');
    表示该路由会渲染当前应用下面的 view/index/hello.html 模板文件输出。

    Route::view('hello/:name', 'index/hello', ['city'=>'shanghai']);  //给模板增加变量;
    在闭包中指定响应状态码和内容格式:
    Route::get('hello/:name', function () {
    response()->data('Hello,ThinkPHP')
    ->code(200)
    ->contentType('text/plain');
    });
    ---------------------------------------
    Route::get('new/:id', 'News/read')->ext('html')->https();
    这些路由参数可以混合使用, 只要有任何一条参数检查不通过, 当前路由就不会生效, 继续检测后面的路由规则
    Route::get('new/:id', 'News/read')->option(['ext' => 'html','https' => true]);
    -----------------------------------
    Route::get('new/:id', 'News/read')->ext('shtml|html');
    ----------------------------------
    // 完整域名检测 只在news.thinkphp.cn访问时路由有效
    Route::get('new/:id', 'News/read')->domain('news.thinkphp.cn');
    // 子域名检测
    Route::get('new/:id', 'News/read')->domain('news');
    -------------------------------------
    // 必须是JSON请求访问
    Route::get('new/:id', 'News/read')->json();
    ---------------------------
    路由规则和分组支持绑定模型数据, 例如:
    Route::get('hello/:id', 'index/hello')->model('id', '\app\index\model\User');
    会自动给当前路由绑定 id 为 当前路由变量值的 User 模型数据。
    默认情况下, 如果没有查询到模型数据, 则会抛出异常, 如果不希望抛出异常, 可以使用
    Route::rule('hello/:id', 'index/hello')
    ->model('id', '\app\index\model\User', false);

    Route::rule('hello/:name/:id', 'index/hello')
    ->model('id&name', '\app\index\model\User'); //模糊查询,id,name;

    Route::get('new/:name$', 'News/read')->cache(3600); 表示对当前路由请求缓存 3600 秒, 更多内容可以参考请求缓存一节。

    Route::rule('hello/:name','hello')->middleware(\app\middleware\Auth::class);  
    Route::group('hello', function(){
    Route::rule('hello/:name','hello');
    })->middleware(\app\middleware\Auth::class);
    资源路由:
    Route::resource('blog', 'Blog');
    全局miss路由:
    Route::miss(function() {
    return '404 Not Found!';
    });
    如果某个路由或者分组需要支持跨域请求, 可以使用:
    Route::get('new/:id', 'News/read')
    ->ext('html')
    ->allowCrossDomain();

    那么必须使用路由标识来生成URL地址 Route::buildUrl('blog_read', ['id' => 5, 'name' => 'thinkphp']);以上方法都会生成下面的URL地址:/index.php/blog/5/name/thinkphp.html
    自动生成域名Route::buildUrl('index/blog/read', ['id'=>5])->suffix('shtml')->domain(true);
    打印结果 :http://localhost:8080/index.php/index/blog/read.html?id=5

    控制器一般不需要任何输出, 直接 return 即可。 并且控制器在 json 请求会自动转换为 json 格式输出。
    如果你需要调试并中止执行, 可以使用系统提供的 halt 助手函数。
    多级控制器:
    文件位置:app/index/controller/user/Blog.php 访问地址可以使用 http://serverName/index.php/user.blog/index
    则实现名字空间为:namespace app\index\controller\user;   class Blog   { index方法}
    生成控制器:
    php think make:controller index@Blog
    php think make:controller app\index\controller\Blog
    php think make:controller index@Blog --api

    请求对象:
    当前的请求对象由 think\Request 类负责, 该类不需要单独实例化调用, 通常使用依赖注入即可。 在其它场
    合则可以使用 think\facade\Request 静态类操作。
    public function index(Request $request)
    {
       return $request->param('name');
    }
    通过facade门面:
    Request::param('name');
    request()->param('name');    助手函数;

    如果使用了多应用模式, 可以通过下面的方法来获取当前应用
    app('http')->getName();

    可以通过 Request 对象完成全局输入变量的检测、 获取和安全过滤, 支持包括 $_GET 、 $_POST 、$_REQUEST 、 $_SERVER 、 $_SESSION 、 $_COOKIE 、 $_ENV 等系统变量, 以及文件上传信息。
    Request::has('id','get');  可以使用 has 方法来检测一个变量参数是否设置,变量检测可以支持所有支持的系统变量, 包括get/post/put/request/cookie/server/session/env/file

    // 只获取当前请求的id和name变量
    Request::only(['id','name']);

    // 排除GET请求的id和name变量
    Request::except(['id','name'], 'get');
    // 排除POST请求的id和name变量
    Request::except(['id','name'], 'post');

    变量的类型:
    Request::get('id/d');
    Request::post('name/s');
    Request::post('ids/a');
    判断变量是否定义:input('?get.id');  input('?post.name');
    input('param.name'); // 获取单个参数
    input('param.'); // 获取全部参数

    input('get.name','','htmlspecialchars'); // 获取get变量 并用htmlspecialchars函数过滤
    input('username','','strip_tags'); // 获取param变量 并用strip_tags函数过滤
    input('post.name','','org\Filter::safeHtml'); // 获取post变量 并用org\Filter类的safeHtml方法过滤
    获取变量,并按变量修饰符生成指定的类型:d->int,a->array,s->string
    input('get.id/d');
    input('post.name/s');
    input('post.ids/a');
    请求类型:
    isGet,isPost,isJson,isMobile,isHead
    Request::header();
    Request::header('user-agent');
    $ext = Request::ext();//获取伪静态的扩展名
    响应对象:
    输出类型 快捷方法 对应Response类
    HTML输出 response \think\Response
    渲染模板输出 view \think\response\View
    JSON输出 json \think\response\Json
    JSONP输出 jsonp \think\response\Jsonp
    XML输出 xml \think\response\Xml
    页面重定向 redirect \think\response\Redirect
    附件下载 download \think\response\File
    return json($data);   以json返回  json($data)->code(201);
    json($data)->code(201)->header([
    'Cache-control' => 'no-cache,must-revalidate'
    ]);
    重定向:
    return redirect('http://www.thinkphp.cn');
    return redirect('/hello')->with('name','thinkphp');
    public function hello()
    {
      $name = session('name');
      return 'hello,'.$name.'!';
    }

    if (session('?complete')) 判断session变量是否存在;
    return redirect('hello')->with('name', 'thinkphp')->remember();
    redirect()->restore(); 返回原来存盘的地址
    return download('image.jpg', 'my.jpg'); 访问 download 操作就会下载命名为 my.jpg 的图像文件。下载文件的路径是服务器路径而不是URL路径, 如果要下载的文件不存在, 系统会抛出异常。
    return download('image.jpg', 'my')->expire(300); 设置文件下载的有效期

    要使用Db类必须使用门面方式( think\facade\Db ) 调用;
    Db::name('user')->where('id', 1)->update(['name' => 'thinkphp']);
    Db::name('user')->master(true)->find(1);

    查:
    Db::table('think_user')->where('id', 1)->find();
    // table方法必须指定完整的数据表名

    Db::table('think_user')->where('id', 1)->findOrEmpty();  //失败后返回空

    Db::table('think_user')->where('id', 1)->findOrFail();  //失败后返回异常

    Db::table('think_user')->where('status', 1)->select();  //多条;
    Db::table('think_user')->where('status', 1)->select()->toArray();   转换
    Db::table('think_user')->where('status',1)->selectOrFail();
    Db::name('user')->where('id', 1)->find(); //如果设置了前缀,就要使用name了,没有则使用表;
    这个很常用,查询返回记录的某个值:比如,查询id为1的记录的姓名:
    Db::table('think_user')->where('id', 1)->value('name');
    返回数组:名称列:
    Db::table('think_user')->where('status',1)->column('name');
    数据分批处理:
    Db::table('think_user')->chunk(100, function($users) {
    foreach ($users as $user) {
    //}
    });
    你可以通过从闭包函数中返回 false 来中止对后续数据集的处理:
    Db::table('think_user')->chunk(100, function($users) {
    foreach ($users as $user) {
    // 处理结果集...
    if($user->status==0){
    return false;
    }
    }
    });
    如果你需要处理大量的数据, 可以使用新版提供的游标查询功能, 该查询方式利用了PHP的生成器特性, 可以大
    幅减少大量数据查询的内存开销问题
    $cursor = Db::table('user')->where('status', 1)->cursor();
    foreach($cursor as $user){
        echo $user['name'];
    }

    $data = ['foo' => 'bar', 'bar' => 'foo'];
    Db::name('user')->save($data);

    $data = ['foo' => 'bar', 'bar' => 'foo'];
    Db::name('user')->insert($data);

    $userId = Db::name('user')->insertGetId($data);   //插入数据并返回主键;
    $data = [
    ['foo' => 'bar', 'bar' => 'foo'],
    ['foo' => 'bar1', 'bar' => 'foo1'],
    ['foo' => 'bar2', 'bar' => 'foo2']
    ];
    Db::name('user')->insertAll($data);

    // 分批写入 每次最多100条数据
    Db::name('user')
    ->limit(100)
    ->insertAll($data);

    Db::name('user')
    ->where('id', 1)
    ->data(['name' => 'thinkphp'])
    ->update();

    如果数据中包含主键, 可以直接使用:Db::name('user')->update(['name' => 'thinkphp','id' => 1]);
    如果要更新的数据需要使用 SQL 函数或者其它字段, 可以使用下面的方式:
    Db::name('user')->where('id',1)->exp('name','UPPER(name)')->update();

    支持使用 raw 方法进行数据更新。
    Db::name('user')->where('id', 1)->update(['name' => Db::raw('UPPER(name)'),'score' => Db::raw('score-3'),'read_time' => Db::raw('read_time+1')
    ]);

    // score 字段加 1
    Db::table('think_user')->where('id', 1)->inc('score')->update();

    Db::table('think_user')->delete([1,2,3]);
    Db::table('think_user')->where('id','<',10)->delete();
    // 无条件删除所有数据 Db::name('user')->delete(true);
    whereBetweenTime   / whereTime

    模糊查询:Db::name('user')->where('name', 'like', 'thinkphp%')->select();
    Db::name('user')->where('name', 'like', ['%think','php%'],'OR')->select();

    Db::name('user')->whereLike('name','thinkphp%')->select();
    Db::name('user')->whereNotLike('name','thinkphp%')->select();

    Db::name('user')->where('id','between',[1,8])->select();
    Db::name('user')->where('id','in',[1,5,8])->select();

    Db::name('user')->where('name', null)->where('email','null')->where('name','not null')->select();

    Db::name('user')->whereNull('name')->whereNull('email')->whereNotNull('name')->select();

    exp 查询的条件不会被当成字符串, 所以后面的查询条件可以使用任何SQL支持的语法, 包括使用函数和字段
    名称。Db::name('user')->whereExp('id', 'IN (1,3,8) ')->select();

    Db::table('think_user')->where('status',1)->order('create_time')->limit(10)->select();

    Db::table('think_user')->where('id',1)->field('id,name,email')->find();

    // 传入数组作为查询条件
    Db::table('think_user')->where([
    ['name','=','thinkphp'],
    ['status','=',1]
    ])->select();

    Db::table('think_user')->whereRaw('type=1 AND status=1')->select();
    Db::name('user')->where('status>1')->select();
    多表操作:
    Db::field('user.name,role.title')->table('think_user user,think_role role')->limit(10)->select();
    Db::field('user.name,role.title')->table(['think_user'=>'user','think_role'=>'role'])->limit(10)->select();
    别名:Db::table('think_user')->alias('a')->join('think_dept b ','b.user_id= a.id')->select();
    Db::table('think_user')->alias(['think_user'=>'user','think_dept'=>'dept'])->join('think_dept','dept.user_id= user.id')->select();
    指定字段:Db::table('user')->field('id,title,content')->select();
    字段别名:Db::table('user')->field('id,nickname as name')->select();
    Db::table('user')->fieldRaw('id,SUM(score)')->select();
    Db::table('user')->field(['id','nickname'=>'name'])->select();
    Db::table('user')->select();
    Db::table('user')->field('*')->select();
    Db::table('user')->withoutField('content')->select(); //排除字段
    Db::table('user')->withoutField(['user_id','content'])->select();
    Db::table('user')->field('title,email,content')->insert($data);
    strict 方法用于设置是否严格检查字段名, 用法如下:
    // 关闭字段严格检查 Db::name('user')->strict(false)->insert($data);
    Db::table('article')->limit(10,25)->select(); //分页查询;

    // 查询第一页数据
    Db::table('article')->page(1,10)->select();
    // 查询第二页数据
    Db::table('article')->page(2,10)->select();
    自动分页:Db::table('article')->limit(25)->page(3)->select();
    排序 : ->order('id', 'desc')
    Db::table('user')->where('status', 1)->orderRaw("field(name,'thinkphp','onethink','kancloud')")->limit(5)->select();
    GROUP 方法通常用于结合合计函数, 根据一个或多个列对结果集进行分组 。
    Db::table('score')->field('username,max(score)')->group('user_id')->having('count(test_time)>3')->select();
    (right:右,left:左;)
    INNER JOIN: 等同于 JOIN( 默认的JOIN类型) ,如果表中有至少一个匹配, 则返回行
    LEFT JOIN: 即使右表中没有匹配, 也从左表返回所有的行
    RIGHT JOIN: 即使左表中没有匹配, 也从右表返回所有的行
    FULL JOIN: 只要其中一个表中存在匹配, 就返回行
    Db::table('think_user')->alias('a')->join(['think_work'=>'w'],'a.id=w.artist_id')->join(['think_card'=>'c'],'a.card_id=c.id')->select();
    合并两个结果集:
    Db::field('name')->table('think_user_0')->union([
    'SELECT name FROM think_user_1',
    'SELECT name FROM think_user_2',
    ])->select()  UNION 内部的 SELECT 语句必须拥有相同数量的列。 列也必须拥有相似的数据类型。 同时, 每条 SELECT 语
    句中的列的顺序必须相同。
    去重:Db::table('think_user')->distinct(true)->field('user_login')->select(); //去重user_login字段;
    Db::name('user')->where('id',1)->lock(true)->find();    //Db::name('user')->where('id',1)->lock('lock in share mode')->find();
    缓存:
    Db::table('user')->where('id',5)->cache(true)->find();
    Db::table('user')->cache(true,60)->find();
    // 或者使用下面的方式 是等效的
    Db::table('user')->cache(60)->find();
    cache方法可以指定缓存标识:Db::table('user')->cache('key',60)->find();
    echo Db::table('user')->fetchSql(true)->find(1);   //返回sql语句;
    Db::table('user')->force('user')->select();  //对查询强制使用 user 索引, user 必须是数据表实际创建的索引名称。
    // 数据不存在的话直接抛出异常
    Db::name('blog')
    ->where('status',1)
    ->failException()
    ->select();
    // 数据不存在返回空数组 不抛异常
    Db::name('blog')
    ->where('status',1)
    ->failException(false)
    ->select();

    Db::table('think_user')->count();  Db::table('think_user')->count('id');
    Db::table('think_user')->max('score');

    // 查询状态为1的用户数据 并且每页显示10条数据
    $list = Db::name('user')->where('status',1)->order('id', 'desc')->paginate(10);
    // 渲染模板输出
    return view('index', ['list' => $list]);

    // 查询状态为1的用户数据 并且每页显示10条数据
    $list = Db::name('user')->where('status',1)->order('id', 'desc')->paginate(10);
    // 获取分页显示
    $page = $list->render();
    return view('index', ['list' => $list, 'page' => $page]);
    分页模板:
    <ul class="pagination">
    <li><a href="?page=1">&laquo;</a></li>
    <li><a href="?page=1">1</a></li>
    <li class="active"><span>2</span></li>
    <li class="disabled"><span>&raquo;</span></li>
    </ul>
    ----------------------------------
    // 查询状态为1的用户数据 并且每页显示10条数据
    $list = Db::name('user')->where('status',1)->order('id' ,'desc')->paginate(10);
    // 获取总记录数
    $count = $list->total();
    return view('index', ['list' => $list, 'count' => $count]);
    ----------------------------------
    分页变量:
    list_rows 每页数量 page 当前页 path url路径 query url额外参数 fragment url锚点 var_page 分页变量
    对于大量数据的分页查询, 系统提供了一个高性能的 paginateX 分页查询方法, 用法和 paginate 分页查询存在一定区别。 如果你要分页查询的数据量在百万级以上, 使用 paginateX 方法会有明显的提升, 尤其是在分页数较大的情况下。 并且由于针对大数据量而设计, 该分页查询只能采用简洁分页模式, 所以没有总数。
    $list = Db::name('user')->where('status',1)->paginateX(20, 'id', 'desc');
    自定义分页:
    然后在 provider.php 定义文件中重新绑定 return [ 'think\Paginator' => 'app\common\Bootstrap' ];
    时间比较:
    // 大于某个时间
    Db::name('user')->whereTime('birthday', '>=', '1970-10-1')->select();
    // 小于某个时间
    Db::name('user')->whereTime('birthday', '<', '2000-10-1')->select();
    // 时间区间查询
    Db::name('user')->whereTime('birthday', 'between', ['1970-10-1', '2000-10-1'])->select();
    // 不在某个时间区间
    Db::name('user')->whereTime('birthday', 'not between', ['1970-10-1', '2000-10-1'])->select();
    // 查询两个小时内的博客
    Db::name('blog')->whereTime('create_time','-2 hours')->select();
    // 查询2017年上半年注册的用户
    Db::name('user')->whereBetweenTime('create_time', '2017-01-01', '2017-06-30')->select();
    // 查询不是2017年上半年注册的用户
    Db::name('user')->whereNotBetweenTime('create_time', '2017-01-01', '2017-06-30')->select();
    查询今年注册的用户
    Db::name('user')->whereYear('create_time')->select();
    Db::name('user')->whereYear('create_time', 'last year')->select();  //去年
    Db::name('user')->whereYear('create_time', '2018')->select();  //18年
    Db::name('user')->whereMonth('create_time')->select();  //本月
    Db::name('user')->whereMonth('create_time','last month')->select();   上月
    Db::name('user')->whereMonth('create_time', '2018-06')->select();  //指定月份
    Db::name('user')->whereWeek('create_time')->select();  本周
    Db::name('user')->whereWeek('create_time', 'last week')->select(); //上周
    Db::name('user')->whereDay('create_time')->select(); //当天
    Db::name('user')->whereDay('create_time', 'yesterday')->select() 昨天
    // 查询2018年6月1日注册的用户
    Db::name('user')->whereDay('create_time', '2018-06-01')->select();
    // 查询有效期内的活动
    Db::name('event')->whereBetweenTimeField('start_time', 'end_time')->select();
    Db::table('think_user')->where('name|title','like','thinkphp%')->where('create_time&update_time','>',0)->find();
    Db::table('think_user')->where([
    ['name', 'like', 'thinkphp%'],
    ['title', 'like', '%thinkphp'],
    ['id', '>', 0],
    ['status', '=', 1],
    ])->select();
    闭包查询:
    $name = 'thinkphp';
    $id = 10;
    Db::table('think_user')->where(function ($query) use($name, $id) {
    $query->where('name', $name)
    ->whereOr('id', '>', $id);
    })->select();
    原生:Db::table('think_user')->whereRaw('id > 0 AND name LIKE "thinkphp%"')->select();
    假设数据表 user 中有 email 和nick_name 字段, 我们可以这样来查询。
    $user = Db::table('user')
    ->whereEmail('thinkphp@qq.com')
    ->find();
    // 根据昵称(nick_name) 查询用户
    $email = Db::table('user')->whereNickName('like', '%流年%')->select();
    // 根据邮箱查询用户信息
    $user = Db::table('user')->getByEmail('thinkphp@qq.com');

    原生查询:Db::query("select * from think_user where status=:id", ['id' => 1]);
    如果希望从主库读取, 可以使用Db::query("select * from think_user where status=:id", ['id' => 1], true);
    用于更新和写入:Db::execute("update think_user set name='thinkphp' where status=1");
    使用下面的方法注册数据库查询事件
    \think\facade\Db::event('before_select', function ($query) {
    // 事件处理
    // 在这里可以对$query进行操作
    $query->where('site_id',1)->order('update_time desc');
    $model = $query->getModel(); // 实例化的模型对象,可以给模型自定义一些属性,
    在这里读取,相当于传参.
    });

    事件 描述
    before_select select 查询前回调
    before_find find 查询前回调
    after_insert insert 操作成功后回调
    after_update update 操作成功后回调
    after_delete delete 操作成功后回调
    查询结果过滤:
    Db::name('user')->filter(function($user) {
    $user['name'] = 'new value';
    $user['test'] = 'test';
    return $user;
    })->select();

    比如 MySQL 的 MyISAM 不支持事务处理, 需要使用 InnoDB 引擎。
    事务:
    Db::transaction(function () {
    Db::table('think_user')->find(1);
    Db::table('think_user')->delete(1);
    });
    手动事务:
    // 启动事务
    Db::startTrans();
    try {
          Db::table('think_user')->find(1);
          Db::table('think_user')->delete(1);
    // 提交事务
          Db::commit();
    } catch (\Exception $e) {
    // 回滚事务
          Db::rollback();
    }
    存储过程:Db::execute('call procedure_name');
    存储过程可以支持输入和输出参数, 以及进行参数绑定操作。
    $resultSet = Db::query('call procedure_name(:in_param1,:in_param2,:out_param)',
    [
    'in_param1' => $param1,
    'in_param2' => [$param2, PDO::PARAM_INT],
    'out_param' => [$outParam, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 4000],
    ]);

    从数据库中select()的数据集,有如下方法:
    isEmpty 是否为空
    toArray 转换为数组
    all 所有数据
    merge 合并其它数据
    diff 比较数组, 返回差集
    flip 交换数据中的键和值
    intersect 比较数组, 返回交集
    keys 返回数据中的所有键名
    pop 删除数据中的最后一个元素
    shift 删除数据中的第一个元素
    unshift 在数据开头插入一个元素
    push 在结尾插入一个元素
    reduce 通过使用用户自定义函数, 以字符串返回数组
    reverse 数据倒序重排
    chunk 数据分隔为多个数据块
    each 给数据的每个元素执行回调
    filter 用回调函数过滤数据中的元素
    column 返回数据中的指定列
    sort 对数据排序
    order 指定字段排序
    shuffle 将数据打乱
    slice 截取数据中的一部分
    map 用回调函数处理数组中的元素
    where 根据字段条件过滤数组中的元素
    whereLike Like查询过滤元素
    whereNotLike Not Like过滤元素
    whereIn IN查询过滤数组中的元素
    whereNotIn Not IN查询过滤数组中的元素
    whereBetween Between查询过滤数组中的元素
    whereNotBetween Not Between查询过滤数组中的元素
    模型:
    模型会自动对应数据表, 模型类的命名规则是除去表前缀的数据表名称, 采用驼峰法命名, 并且首字母大写
    UserType      think_user_type
    如果你希望给模型类添加后缀, 需要设置 name 属性或者 table 属性。
    protected $pk = 'uid'; 主键
    // 设置当前模型对应的完整数据表名称
    protected $table = 'think_user';
    // 设置当前模型的数据库连接
    protected $connection = 'db_config';
    // 模型初始化
    protected static function init()
    {
    //TODO:初始化内容
    }
    用模型查询 :
    User::where('id','>',10)->select();
    // 定义默认的表后缀(默认查询中文数据)
    protected $suffix = _cn';
    // 设置模型字段信息
    protected $schema = [
    'id' => 'int',
    'name' => 'string',
    'status' => 'int',
    'score' => 'float',
    'create_time' => 'datetime',
    'update_time' => 'datetime',
    ];

    php think optimize:schema
    // 设置废弃字段
    protected $disuse = [ 'status', 'type' ];
    echo $user['name'];

    $user = $this->find(1);
    echo $user->getAttr('create_time');

    $user = new User;
    // post数组中只有name和email字段会写入
    $user->allowField(['name','email'])->save($_POST);

    $user = new User;
    // 过滤post数组中的非数据表字段数据
    $data = Request::only(['name','email']);
    $user->save($data);

    $user = User::where('status',1)
    ->where('name','liuchen')
    ->find();
    $user->name = 'thinkphp';
    $user->email = 'thinkphp@qq.com';
    $user->save();

    User::update(['name' => 'thinkphp', 'id' => 1])
    ser::destroy(1);
    // 支持批量删除多个数据
    User::destroy([1,2,3]);

    User::destroy(function($query){
    $query->where('id','>',10);
    });

    $list = User::select([1,2,3]);
    // 对数据集进行遍历操作
    foreach($list as $key=>$user){
    echo $user->name;
    }

    // 获取某个用户的积分
    User::where('id',10)->value('score');
    // 获取某个列的所有值
    User::where('status',1)->column('name');
    // 以id为索引
    User::where('status',1)->column('name','id');

    模型对象赋值;
    调用模型的 data 方法, 并且第二个参数传入 true ;
    调用模型的 appendData 方法, 并且第二个参数传入 true ;
    调用模型的 save 方法, 并且传入数据;
    显式调用模型的 setAttr 方法;
    显式调用模型的 setAttrs 方法,效果与 appendData 并传入 true 的用法相同;
    public function setNameAttr($value)
    {
      return strtolower($value); //设置name属性;
    }
    模型中定义只读字段:protected $readonly = ['name', 'email'];

    // 软删除
    User::destroy(1);
    // 真实删除
    User::destroy(1,true);

    如果仅仅需要查询软删除的数据, 可以使用:
    User::onlyTrashed()->find();
    User::onlyTrashed()->select();

    恢复被软删除的数据
    $user = User::onlyTrashed()->find(1);
    $user->restore();

    protected $dateFormat = 'Y/m/d';
    protected $type = [
    'status' => 'integer',
    'score' => 'float',
    'birthday' => 'timestamp',
    ];

    // 'birthday' => 'timestamp:Y/m/d',

    $user = User::find(1);
    View::assign('user', $user);
    return View::fetch();

    设置不输出的字段属性:$user = User::find(1);
    dump($user->hidden(['create_time','update_time'])->toArray());

    $user = User::with('profile')->find(1);

    $user = User::find(1);
    echo $user->toJson();

    设置允许输出的属性:
    echo $user->visible(['id','name','email'])->toJson();

    echo json_encode(User::find(1));

    模型事件 描述 事件方法名
    after_read 查询后 onAfterRead
    before_insert 新增前 onBeforeInsert
    after_insert 新增后 onAfterInsert
    before_update 更新前 onBeforeUpdate
    after_update 更新后 onAfterUpdate
    before_write 写入前 onBeforeWrite
    after_write 写入后 onAfterWrite
    before_delete 删除前 onBeforeDelete
    after_delete 删除后 onAfterDelete
    before_restore 恢复前 onBeforeRestore
    after_restore 恢复后 onAfterRestore

    class User extends Model
    {
    public function profile()
    {
         return $this->hasOne(Profile::class);
    }
    }
    类型 关联关系 相对的关联关系
    一对一 hasOne belongsTo
    一对多 hasMany belongsTo
    多对多 belongsToMany belongsToMany
    远程一对多 hasManyThrough 不支持
    多态一对一 morphOne morphTo
    多态一对多 morphMany morphTo
    class Profile extends Model
    {
    public function user()
    {
         return $this->belongsTo(User::class);
    }
    }

    $profile = Profile::find(1);
    // 获取档案所属的用户名称
    echo $profile->user->name; //二个表己经关联;

    hasOne('关联模型类名', '外键', '主键');
    return $this->hasOne(Profile::class, 'uid');


    withJoin 方法默认使用的是 INNER JOIN 方式, 如果需要使用其它的, 可以改成
    $users = User::withJoin('profile', 'LEFT')->select();
    foreach ($users as $user) {
    echo $user->profile->name;
    }

    belongsTo('关联模型','外键', '关联主键');

    $user = User::find(1)->bindAttr('profile',['email','nickname']);
    // 输出Profile关联模型的email属性
    echo $user->email;
    echo $user->nickname;

    // 查询评论超过3个的文章
    $list = Article::has('comments','>',3)->select();
    // 查询评论状态正常的文章
    $list = Article::hasWhere('comments',['status'=>1])->select();

    hasManyThrough('关联模型', '中间模型', '外键', '中间表关联键','当前模型主键','中间模型主键');
    通常可以直接使用 think\facade\View 来操作视图。
    View::assign('email','thinkphp@qq.com');
    // 或者批量赋值
    View::assign([
    'name' => 'ThinkPHP',
    'email' => 'thinkphp@qq.com'
    ]);
    // 模板输出
    return View::fetch('index');
    助手函数:
    return view('index', [
    'name' => 'ThinkPHP',
    'email' => 'thinkphp@qq.com'
    ]);

    // 使用视图输出过滤
    return View::filter(function($content){
    return str_replace("\r\n",'<br/>',$content);
    })->fetch();

    // 不带任何参数 自动定位当前操作的模板文件
    return View::fetch();

    return View::fetch('admin@member/edit');
    return View::fetch('../template/public/menu.html');

    如果希望直接解析内容而不通过模板文件的话, 可以使用 display 方法:
    return View::display($content, ['name' => 'thinkphp', 'email' => 'think
    php@qq.com']);
    }

    // 使用内置PHP模板引擎渲染模板输出
    return View::engine('php')->fetch();

    protected $schema = [
    'id' => 'int',
    'name' => 'string',
    'status' => 'int',
    'score' => 'float',
    'create_time' => 'datetime',
    'update_time' => 'datetime',
    ];

    需要在数据库配置中设置 fields_cache 为 true 才能生成缓存,schema 属性一旦定义, 就必须定义完整的数据表字段类型。
    // 设置字段自动转换类型   protected $type = ['score' => 'float',];

    $user = new User;
    $list = [['name'=>'thinkphp','email'=>'thinkphp@qq.com'],['name'=>'onethink','email'=>'onethink@qq.com']];
    $user->saveAll($list);
    // 只允许写入name和email字段的数据  create 方法默认会过滤不是数据表的字段信息, 可以在第二个参数可以传入允许写入的字段列表
    $user = User::create([
    'name' => 'thinkphp',
    'email' => 'thinkphp@qq.com'
    ], ['name', 'email']);
    echo $user->name;
    echo $user->email;
    echo $user->id; // 获取自增ID
    更新:
    User::update(['name' => 'thinkphp', 'id' => 1]);

    如果你是在模型内部获取数据, 请不要使用 $this->name 的方式来获取数据, 请使用$this->getAttr('name') 替代。
    // 获取某个用户的积分
    User::where('id',10)->value('score');
    // 获取某个列的所有值
    User::where('status',1)->column('name');
    // 以id为索引
    User::where('status',1)->column('name','id');
    动态查询:
    // 根据name字段查询用户
    $user = User::getByName('thinkphp');
    // 根据email字段查询用户
    $user = User::getByEmail('thinkphp@qq.com');

    User::max('score');
    如果在模型中定义:
    class User extends Model
    {
    public function scopeThinkphp($query)
    {
          $query->where('name','thinkphp')->field('id,name');
    }
    public function scopeAge($query)
    {
          $query->where('age','>',20)->limit(10);
    }
    }
    就可以用动态查询:
    // 查找name为thinkphp的用户
    User::scope('thinkphp')->find();
    // 查找年龄大于20的10个用户
    User::scope('age')->select();
    // 查找name为thinkphp的用户并且年龄大于20的10个用户
    User::scope('thinkphp,age')->select()

    // 设置json类型字段
    protected $json = ['info'];

    $user->info = [
    'email' => 'thinkphp@qq.com',
    'nickname '=> '流年',
    ];
    $user = User::where('info->nickname','流年')->find();

    protected $jsonType = [
    'info->user_id' => 'int'
    ];

    搜索器的作用是用于封装字段( 或者搜索标识) 的查询条件表达式, 一个搜索器对应一个特殊的方法( 该方法必
    须是 public 类型) , 方法命名规范为:
    search FieldName Attr
    public function searchNameAttr($query, $value, $data)
    {
    $query->where('name','like', $value . '%');
    }
    然后可以用下面的语句搜索:
    User::withSearch(['name','create_time'], [
    'name' => 'think',
    'create_time' => ['2018-8-1','2018-8-5'],
    'status' => 1
    ])->select();

    // 开启自动写入时间戳字段 配置:
    'auto_timestamp' => 'datetime',
    在模型类中:protected $autoWriteTimestamp = 'datetime';
    系统会自动写入 create_time 和 update_time 字段
    // 定义时间戳字段名
    protected $createTime = 'create_at';
    protected $updateTime = 'update_at';
    在数据库中统一定义时间字段:
    'datetime_field' => 'create_at,update_at',
    模型中用于监听事件的:
    public static function onBeforeUpdate($user)
    {
    if ('thinkphp' == $user->name) {
    return false;
    }
    } //如果事件没有返回`false`,那么继续执行
    public static function onAfterDelete($user)
    {
    Profile::destroy($user->id);
    }
    有的事件:如果事件没有返回`false`,那么继续执行;

    模型关联操作把数据表的关联关系对象化, 解决了大部分常用的关联场景, 封装的关联操作比起常规的数据库联表操作更加智能和高效, 并且直观。hasOne('关联模型类名', '外键', '主键');
    public function profile()
    {
        return $this->hasOne(Profile::class);   //hasOne('关联模型类名', '外键', '主键');user_id为外键,如果不是则是uid;
    }
    echo $user->profile->phone;   这样可以使用profile字段;
    另一个属于:return $this->belongsTo(User::class);
    有这种关系的查询:$users = User::hasWhere('profile', ['nickname'=>'think'])->select();
    $user = User::with('profile')->select();//User 模型类有profile函数;这个函数有hasone
    // 注意第一个参数是关联方法名(不是关联模型名)
    $users = User::hasWhere('profile', ['nickname'=>'think'])->select();

    belongsTo('关联模型','外键', '关联主键');

    class Profile extends Model
    {
    public function user()
    {
        return $this->belongsTo(User::class, 'uid'); //belongsTo('关联模型','外键', '关联主键');
    }
    }

    $user = User::with('books')->find(1);
    // 直接输出Profile关联模型的绑定属性
    echo $user->email;
    echo $user->truename;
    由于是toMany,所有,不能直接写属性,返回的是数组:echo $user->books[0]->bookname;
    动态绑定关联属性;
    $user = User::find(1)->bindAttr('profile',['email','nickname']);
    // 输出Profile关联模型的email属性
    echo $user->email;
    echo $user->nickname;

    // 查询
    $blog = Blog::find(1);
    $blog->title = '更改标题';
    $blog->content->data = '更新内容';
    // 更新当前模型及关联模型
    $blog->together(['content'])->save();

    // 查询
    $blog = Blog::with('content')->find(1);
    // 删除当前及关联模型
    $blog->together(['content'])->delete();
    进行二次搜索:
    $user->books()->where('id',2)->select()

    // 查询评论超过3个的文章
    $list = Article::has('comments','>',3)->select();
    // 查询评论状态正常的文章
    $list = Article::hasWhere('comments',['status'=>1])->select();

    $where = Comment::where('status',1)->where('content', 'like', '%think%');
    $list = Article::hasWhere('comments', $where)->select();
    关联新增:
    $article = Article::find(1);
    // 增加一个关联数据
    $article->comments()->save(['content'=>'test']);
    // 批量增加关联数据
    $article->comments()->saveAll([
        ['content'=>'thinkphp'],
        ['content'=>'onethink'],
    ]);

    关联删除
    在删除文章的同时删除下面的评论
    $article = Article::with('comments')->find(1);
    $article->together(['comments'])->delete();

    多对多关联
    belongsToMany('关联模型','中间表','外键','关联键');
    return $this->belongsToMany(Role::class, 'access');
    多对多关联
    class User extends Model
    {
    public function roles()
    {
        return $this->belongsToMany(Role::class, 'access');
        //belongsToMany('关联模型','中间表','外键','关联键');
       //return $this->belongsToMany(Role::class, Access::class);
    }
    }

    关联新增
    $user = User::find(1);
    // 给用户增加管理员权限 会自动写入角色表和中间表数据
    $user->roles()->save(['name'=>'管理员']);
    // 批量授权
    $user->roles()->saveAll([
    ['name'=>'管理员'],
    ['name'=>'操作员'],
    ]);    

    $user = User::find(1);
    // 仅增加管理员权限(假设管理员的角色ID是1)
    $user->roles()->save(1);
    // 或者
    $role = Role::find(1);
    $user->roles()->save($role);
    // 批量增加关联数据
    $user->roles()->saveAll([1,2,3]);

    定义相对的关联:
    class Role extends Model
    {
    public function users()
    {
        return $this->belongsToMany(User::class, Access::class);
    }
    }
    果你的数据集查询返回的是数据集对象, 可以使用调用数据集对象的 load 实现延迟预载入:
    // 查询数据集
    $list = User::select([1,2,3]);
    // 延迟预载入
    $list->load(['cards']);
    foreach($list as $user){
    // 获取用户关联的card模型数据
    dump($user->cards);
    }

    $list = User::with(['profile'])->withCache(30)->select([1,2,3]);

    // 查询数据集
    $list = User::select([1,2,3]);
    // 延迟预载入
    $list->load(['cards'], 30);   //30秒

    return View::fetch('admin@member/edit'); //跨应用渲染模板

    public function index()
    {
    // 改变当前操作的模板路径
    View::config(['view_path' => 'mypath']);
    return View::fetch();
    }

    日志:
    Log::error('错误信息');
    Log::info('日志信息')
    trace('错误信息', 'error');
    trace('日志信息', 'info');
    Log::info('日志信息{user}', ['user' => '流年']);
    Log::clear(); //手动清空日志
    验证:
    php think make:validate User //建立User验证
    protected $rule = [
    'name' => 'require|max:25',
    'email' => 'email',
    ];
    ---------------------
    try {
          validate(User::class)->check([
          'name' => 'thinkphp',
          'email' => 'thinkphp@qq.com',
    ]);
    } catch (ValidateException $e) {
    // 验证失败 输出错误信息
          dump($e->getError());
    }
    ------------------------------
    protected $rule = [
    'name' => ['require', 'max' => 25, 'regex' => '/^[\w|\d]\w+/'],
    'age' => ['number', 'between' => '1,120'],
    'email' => 'email',
    ];
    -----------------------------
    use think\facade\Validate;
    use think\validate\ValidateRule as Rule;
    $validate = Validate::rule('age', Rule::isNumber()->between([1,120]))
    ->rule([
    'name' => Rule::isRequire()->max(25),
    'email' => Rule::isEmail(),
    ]);
    $data = [
    'name' => 'thinkphp',
    'email' => 'thinkphp@qq.com'
    ];
    if (!$validate->check($data)) {
    dump($validate->getError());
    }
    定义验证场景:
    protected $scene = [
    'edit' => ['name','age'],
    ];

    try {
      validate(app\validate\User::class)->scene('edit')->check($data);
    } catch (ValidateException $e) {
      dump($e->getError());
    }
    路由验证:
    Route::post('hello/:id', 'index/hello')
    ->validate([
    'name' => 'min:5|max:50',
    'email' => 'email',
    ]);
    对象化规则:
    Route::post('hello/:id', 'index/hello')
    ->validate(['name' => ValidateRule::min(5)->max(50),'email' => ValidateRule::isEmail(),]);
    内置验证规则 :
    require | number | integer | float | boolean | email | array | accepted  (yes,on,1)
    date | alpha(纯字母) | alphaNum(字母与数字) | chs (汉字)
    cntrl 控制字符( 换行、 缩进、 空格)
    lower upper 大小写 space 空格 xdigit 16进制
    activeUrl(有效域名与IP)url   ip
    dateFormat:format   'create_time'=>'dateFormat:y-m-d'  验证日期格式
    mobile 验证有效手机  idCard 身份证号 macAddr 网卡地址 zip 邮编
    'num'=>'in:1,2,3'     //in not in 范围
    'num'=>'between:1,10'  //区间
    'name'=>'length:4,25' //长度区间
    'name'=>'max:25'  //最大长度 'name'=>'min:5  最小长度
    'begin_time' => 'after:2016-3-18',  'end_time' => 'before:2016-10-01',  某段时间前,某段时间后
    'expire_time' => 'expire:2016-2-1,2016-10-01', 验证当前操作( 注意不是某个值) 是否在某个有效日期之内
    'name' => 'allowIp:114.45.4.55'  验证当前请求的IP是否在某个范围
    验证某个字段是否和另外一个字段的值一致, 例如:'repassword'=>'require|confirm:password'
    'password'=>'require|confirm' 会自动验证和 password_confirm 进行字段比较是否一致, 反之亦然。
    验证某个字段是否和另外一个字段的值不一致, 例如:'name'=>'require|different:account'
    'score'=>'eq:100'    //等于100      'num'=>'=:100'   'num'=>'same:100'
    'score'=>'egt:60'     'num'=>'>=:100'    大于等于
    'score'=>'gt:60'   'num'=>'>:100  大于
    'score'=>'elt:100' 'num'=>'<=:100'   小于
    正则验证'zip'=>'\d{6}'
    上传验证: file  
    image:width,height,type验证是否是一个图像文件, width height和type都是可选, width和height必须同时定义。
    fileExt:允许的文件后缀 验证上传文件后缀 fileMime:允许的文件类型验证上传文件类型fileSize:允许的文件字节大小
    表单验证:
    // 表示验证name字段的值是否在user表(不包含前缀) 中唯一
    'name' => 'unique:user',
    // 验证其他字段
    'name' => 'unique:user,account',
    // 排除某个主键值
    'name' => 'unique:user,account,10',
    // 指定某个主键值排除
    'name' => 'unique:user,account,10,user_id',
    缓存:
    Cache::set('name', $value, new DateTime('2019-10-01 12:00:00'));
    Cache::inc('name',3);

    Cache::get('name');
    Cache::get('name','')
    数组缓存:Cache::set('name', [1,2,3]);
    Cache::push('name', 4);
    Cache::get('name'); // [1,2,3,4]
    Cache::delete('name');

    Cache::pull('name');
    Cache::clear();

    Cache::remember('start_time', time());

    助手函数:
    cache('name', $value, 3600);     // cache('name')
    // 使用文件缓存
    Cache::set('name','value',3600);
    Cache::get('name');
    // 使用Redis缓存
    Cache::store('redis')->set('name','value',3600);
    Cache::store('redis')->get('name');
    // 切换到文件缓存
    Cache::store('default')->set('name','value',3600);
    Cache::store('default')->get('name');

    Session::set('name', 'thinkphp');
    Session::get('name');
    Session::has('name');
    / 如果值不存在, 返回null
    Session::get('name');
    // 如果值不存在, 返回空字符串
    Session::get('name', '');
    // 获取全部数据
    Session::all();
    Session::delete('name');
    // 取值并删除
    Session::pull('name');

    Session::clear();  清空
    // 设置session 并且在下一次请求之前有效
    Session::flash('name','value');
    // 清除当前请求有效的session
    Session::flush();
    // 赋值
    Session::set('name.item','thinkphp');
    // 判断是否赋值
    Session::has('name.item');
    // 取值
    Session::get('name.item');
    // 删除
    Session::delete('name.item');
    session助手函数:
    // 赋值
    session('name', 'thinkphp');
    // 判断是否赋值
    session('?name');
    // 取值
    session('name');
    // 删除
    session('name', null);
    // 清除session
    session(null);

    可以在Request对象中读取Session数据
    public function index(Request $request) {
    // 读取某个session数据
    $request->session('user.name', '');
    // 获取全部session数据
    $request->session();
    }

    cookie:
    // 设置Cookie 有效期为 3600秒
    Cookie::set('name', 'value', 3600);
    Cookie::forever('name', 'value');
    Cookie::delete('name');

    // 读取某个cookie数据
    Cookie::get('name');
    // 获取全部cookie数据
    Cookie::get();

    // 设置
    cookie('name', 'value', 3600);
    // 获取
    echo cookie('name');
    // 删除
    cookie('name', null);
    上传文件:
    public function upload(){
    // 获取表单上传文件 例如上传了001.jpg
        $file = request()->file('image');
        // 上传到本地服务器
        $savename = \think\facade\Filesystem::putFile( 'topic', $file);
                    //$savename = \think\facade\Filesystem::putFile( 'topic', $file, 'md5'); //md5命名方式 1 date md5 sha1
    }
    $savename = \think\facade\Filesystem::disk('public')->putFile( 'topic', $file);   //位置
    $savename = \think\facade\Filesystem::putFileAs( 'topic', $file,'abc.jpg'); //改名

    批量上传:
    <form action="/index/index/upload" enctype="multipart/form-data" method="post">
    <input type="file" name="image[]" /> <br>
    <input type="file" name="image[]" /> <br>
    <input type="file" name="image[]" /> <br>
    <input type="submit" value="上传" />
    </form>
    public function upload(){
    // 获取表单上传文件
    $files = request()->file('image');
    $savename = [];
    foreach($files as $file){
        $savename[] = \think\facade\Filesystem::putFile( 'topic', $file);
    }
    }
    ------------------------
    public function upload(){
    // 获取表单上传文件
        $files = request()->file();
        try {
            validate(['image'=>'fileSize:10240|fileExt:jpg|image:200,200,jpg'])->check($files);
            $savename = [];
        foreach($files as $file) {
            $savename[] = \think\facade\Filesystem::putFile( 'topic', $file);
        }
        } catch (\think\exception\ValidateException $e) {
            echo $e->getMessage();
        }
    }

    获取文件的sha1:
    echo $file->hash('sha1');
    echo $file->hash('md5');

    php think build admin //快速生成 admin 应用

    php think make:controller index@Blog
    php think make:controller Blog

    php think clear   清缓存

    php think optimize:route 生存路由映射缓存

    php think route:list admin    //查看多路由映射

    workman:
    composer require topthink/think-worker
    php think worker

    php think worker:server
    think助手工具库
    composer require topthink/think-helper
    验证码:
    <div>{:captcha_img()}</div>
    <div><img src="{:captcha_src()}" alt="captcha" /></div>
    注意一定要打开sessionInit::class中间件,否则验证不了;
    $captcha = input('captcha');
        if( !captcha_check($captcha )){
            return '验证码错误';
        }else{
            return '验证码正确';
        }
    就这,就可以了;
    Swoole: 仅支付linux运行:
    composer require topthink/think-swoole

    登录 :
    public function index()
    这个后台的主页控制器首页:
    if(session('adminSessionData')){
                return redirect('/qingadmin/index');
    }
    如果有session,则转向 后台首页,如果没有session,说明没有登录,这时,要检测登录;if (request()->isPost()) { 说明己经提交了表单过来 }己经传过来,说明只需要验证:这时,处理验证:验证验证码,读数据,数据查询,有数据验证密码。验证帐号是否禁用,然后session('adminSessionData', $adminData);加session存盘,然后,return alert('登录成功', '/qingadmin/index/index', 6); 提示 然后转向,否则,说明即没登录 ,又没提交,这时,转到view(login)登录页就可以了;
    session('adminSessionData',null);  登出
    return redirect('/qingadmin/login/index');然后退出转向;
    中间件:
    public function handle($request, \Closure $next)
        {
            if(empty(session('adminSessionData')) && !preg_match('/login/',$request->pathinfo())){
                return redirect((string) url('login/index'));
            }
            return $next($request);
        }

    更多相关内容
  • 上面的例子,我们采用了一对一的关联模型,它还有相对的反向关联; 下面给出一个例子: class Profile extends Model { public function user() { return $this->belongsTo(User::class); } } $profile...

    对于关联方式,系统提供了9种方案,具体如下:

             上面的例子,我们采用了一对一的关联模型,它还有相对的反向关联;

            下面给出一个例子: 

    class Profile extends Model {
        public function user() {
        return $this->belongsTo(User::class); 
        }
    }
    $profile = ProfileModel::find(1); 
    return $profile->user->email;

    一对一关联查询

            一张  tp_user表,主键为:id;附属表:tp_profile,建立两个字段:user_id和  hobby,外键是user_id。

    hasOne

             hasOne模式,适合主表关联附表,具体设置方式如下:

            hasOne('关联模型',['外键','主键']);

    关联模型(必须):关联的模型名或者类名
    外键:默认的外键规则是当前模型名(不含命名空间,下同)+_id ,例如  user_id
    主键:当前模型主键,默认会自动获取也可以指定传入

    return $this->hasOne(Profile::class,'user_id', 'id');

            创建User模型和Profile模型,均为空模型;User模型端,需要关联Profile,具体方式如下:

    class User extends Model
    {
        public function profile() {
        //hasOne表示一对一关联,参数一表示附表,参数二外键,默认user_id 
        return $this->hasOne(Profile::class,'user_id');
    } }

             创建一个控制器用于测试输出:Grade.php:

    $user = UserModel::find(21);
    return json($user->profile); 
    return $user->profile->hobby;

            使用  save()方法,可以设置关联修改,通过主表修改附表字段的值;

    $user = UserModel::find(19);
    $user->profile->save(['hobby'=>'酷爱小姐姐']);

            ->profile属性方式可以修改数据,->profile()方法方式可以新增数据;

    $user->profile()->save(['hobby'=>'不喜欢吃青椒']);

    belongsTo

            belongsTo模式,适合附表关联主表,具体设置方式如下:

            belongsTo('关联模型',['外键','关联主键']);

    return $this->belongsTo(Profile::class,'user_id', 'id');

    关联模型(必须):模型名或者模型类名
    外键:当前模型外键,默认的外键名规则是关联模型名+_id
    关联主键:关联模型主键,一般会自动获取也可以指定传入

            对于  belongsTo()的查询方案如下:

    $profile = ProfileModel::find(1);
    return $profile->user->email;

            使用  hasOne()也能模拟  belongsTo()来进行查询;

    //参数一表示的是User模型类的profile方法,而非Profile模型类 
    $user = UserModel::hasWhere('profile', ['id'=>2])->find(); 
    return json($user);
    
    //采用闭包,这里是两张表操作,会导致id识别模糊,需要指明表 
    $user = UserModel::hasWhere('profile', function ($query) {
        $query->where('profile.id', 2); 
    })->select();
    return json($user);

    一对多关联查询

    hasMany模式

            hasMany模式,适合主表关联附表,实现一对多查询,具体设置方式如下:

            hasMany('关联模型',['外键','主键']);

    return $this->hasMany(Profile::class,'user_id', 'id');

    关联模型(必须):模型名或者模型类名
    外键:关联模型外键,默认的外键名规则是当前模型名+_id
    主键:当前模型主键,一般会自动获取也可以指定传入

             使用->profile()方法模式,可以进一步进行数据的筛选;

    $user->profile()->where('id', '>', 10)->select();
    $user->profile->where('id', '>', 10)

            使用  has()方法,查询关联附表的主表内容,比如大于等于  2条的主表记录;

    UserModel::has('profile', '>=', 2)->select();

            使用  hasWhere()方法,查询关联附表筛选后记录,比如兴趣审核通过的主表记录;

    UserModel::hasWhere('profile', ['status'=>1])->select();

            使用  save()和  saveAll()进行关联新增和批量关联新增,方法如下:

    $user = UserModel::find(19);
    $user->profile()->save(['hobby'=>'测试喜好', 'status'=>1]); 
    $user->profile()->saveAll([
        ['hobby'=>'测试喜好', 'status'=>1], 
        ['hobby'=>'测试喜好', 'status'=>1]
    ]);

            使用  together()方法,可以删除主表内容时,将附表关联的内容全部删除;

    $user = UserModel::with('profile')->find(227);
    $user->together(['profile'])->delete();

    多对多关联查询

            首先,我们来看多对多关系的三张表,具体如下:

             tp_user:用户表;tp_role:角色表;tp_access:中间表;access表包含了  user和  role表的关联  id,多对多模式。

            在  User.php的模型中,设置多对多关联,方法如下:

    public function roles()
    {
        return $this->belongsToMany(Role::class, Access::class); 
    }

            在 roles方法中,belongsToMany为多对多关联,具体参数如下:

            belongsToMany('关联模型','中间表',['外键','关联键']);

    $this->belongsToMany(Role::class, Access::class, 'role_id', 'user_id');

             role.php和 access.php创建一个空模型即可,无须创建任何。注意,注意:Role继承  Model即可,而中间表需要继承  Pivot;在  user.php中,创建  many()方法,用于测试,查询方式如下:

    public function many()
    {
        //得到一个用户:蜡笔小新
        $user = UserModel::find(21); 
        //获取这个用户的所有角色
        $roles = $user->roles; 
        //输出这个角色所具有的权限
        return json($roles); 
    }

            当我们要给一个用户创建一个角色时,用到多对多关联新增;而关联新增后,不但会给  tp_role新增一条数据,也会给  tp_access新增一条;

    $user->roles()->save(['type'=>'测试管理员']);
    $user->roles()->saveAll([[...],[...]]);

             一般来说,上面的这种新增方式,用于初始化角色比较合适,也就是说,各种权限的角色,并不需要再新增了,都是初始制定好的。我们真正需要就是通过用户表新增到中间表关联即可;

    $user->roles()->save(1);
    或:
    $user->roles()->save(Role::find(1)); $user->roles()->saveAll([1,2,3]); 
    或:
    $user->roles()->attach(1);
    $user->roles()->attach(2, ['details'=>'测试详情']);

            除了新增,还有直接删除中间表数据的方法:

    $user->roles()->detach(2);

    展开全文
  • TP6多态笔记

    2021-08-08 18:05:29
    最近研究pearAdmin TP版时看到了获取用户权限时with关联查询的时候,看到了没理解的语句,后面查询了解到是多态用法,下面附上代码 // 用户的所有权限 public static function permissions($id,$root) { // $aaa ...

    最近研究pearAdmin TP版时看到了获取用户权限时with关联查询的时候,看到了没理解的语句,后面查询了解到是多态用法,下面附上代码

     // 用户的所有权限
        public static function permissions($id,$root)
        {
            // $aaa = self::with(['roles.permissions', 'directPermissions'])->fetchSql(true)->find($id);
            // roles.permissions 多态用法只,roles模型里的permissions方法
            $admin = self::with(['roles.permissions', 'directPermissions'])->findOrEmpty($id)->toArray();
            $permissions = [];
            //超级管理员缓存所有权限
            if ($admin['id'] == 1){
                $perms = AdminPermission::order('sort','asc')->select()->toArray();
                foreach ($perms as $p){
                    if($p['status'] == 1){
                        $permissions[$p['id']] =  $p;
                        $permissions[$p['id']]['href'] = is_url($p['href'])??$root.$p['href'];
                     }
                }
                if(env('APP_DEBUG')==true){
                    $permissions[0] = [
                        "id" => -1,
                        "pid" => 0,
                        "title" => "CRUD",
                        "icon" => "layui-icon layui-icon-util",
                        "href" => $root."/crud/index",
                        "type" => 1,
                    ];
                }
            }else{
                 //处理角色权限
                 if (isset($admin['roles']) && !empty($admin['roles'])) {
                    foreach ($admin['roles'] as $r) {
                        if (isset($r['permissions']) && !empty($r['permissions'])) {
                            foreach ($r['permissions'] as $p) {
                                if($p['status'] == 1){
                                    $permissions[$p['id']] =  $p;
                                    $permissions[$p['id']]['href'] = is_url($p['href'])??$root.$p['href'];
                                 }
                            }
                        }
                    }
                }
                //处理直接权限
                if (isset($admin['directPermissions']) && !empty($admin['directPermissions'])) {
                    foreach ($admin['directPermissions'] as $p) {
                        if($p['status'] == 1){
                           $permissions[$p['id']] =  $p;
                           $permissions[$p['id']]['href'] = is_url($p['href'])??$root.$p['href'];
                        }
                    }
                }
                $key = array_column($permissions, 'sort');
                array_multisort($key,SORT_ASC,$permissions);
            }
            //合并权限为用户的最终权限
            return $permissions;
        }
    

    在搜索学习过程中发现了一遍介绍得比较详细得文章《tp6使用with方法改进笔记!》,这边就直接搬他的文章了

    用户表模型:User.php

    namespace app\common\model;
    
    class User extends BaseModel
    {
        /*
         * 微信信息关联
         */
        public function userWeixin()
        {
            return $this->hasOne(UserWeixin::class,'user_id')->bind([
                'nickname'=>'nickName',
                'openid'=>'wxOpenid',
                'headimg'=>'headImg',
    
            ]);
        }
        //多级关联上级取指定字段
        public function up()
        {
            return $this->belongsTo(User::class,'upid')->field('id,mobile,upid');
        }
    
    }
    

    有问题写法(中间一级丢失微信关联):

    $user = User::field('id,mobile,upid')
        ->with(['userWeixin','up','up.userWeixin','up.up','up.up.userWeixin'])
        ->where('id','=',function($query) use($uid){
            $query->name('user')->where("id = {$uid}")->field('upid');
        })->find()->toArray();
    

    在这里插入图片描述
    改进写法:

    $user = User::field('id,mobile,upper')
       ->with(['userWeixin','up'=>['userWeixin','up'=>['userWeixin']]]) 
       ->where('id','=',function($query) use($uid){//因为传的ID是当前用户,需要的是上级用户ID
           $query->name('user')->where("id = {$uid}")->field('upid');//简写
          # $query->table(config('database.connections.mysql.prefix').'user')->where("id = {$uid}")->field('upid');
       })->find()->toArray() ;
    dd($user); 
    

    语法对比:

     with(['userWeixin','up','up.userWeixin','up.up','up.up.userWeixin']) 
     with(['userWeixin','up.userWeixin','up.up.userWeixin'])  
    改成下面写法:
     with(['userWeixin','up'=>['userWeixin','up'=>['userWeixin']]]) 
     with(['userWeixin','up'=>['userWeixin','up.userWeixin']]) 
    

    在这里插入图片描述

    展开全文
  • ThinkPHP-PHP

    2021-06-20 14:07:27
    ThinkPHP5.1底层架构做了进一步的改进,减少依赖,其主要特性包括: 采用容器统一管理对象 支持Facade 注解路由支持 路由跨域请求支持 配置和路由目录独立 取消系统常量 助手函数增强 类库别名机制 增加条件查询 ...
  • URL_PATHINFO_DEPR, depr表示 网页路径"分隔符",用"-", 有利于seo,注意是从 sername/index.... 在thinkphp中,有两个地方使用depr,另个就是tpl的文件目录组织分隔符: 'TMPL_FILE_DEPR'=&gt...

    URL_PATHINFO_DEPR, depr表示 网页路径"分隔符",用"-", 有利于seo,注意是从 sername/index.php(开始的)/home-user-login-var-value开始的,pathinfo也支持普通的参数传值(仅仅支持参数...). 在thinkphp中,有两个地方使用depr,另一个就是tpl的文件目录组织分隔符: 'TMPL_FILE_DEPR'=>'-'

    URL_PATHINFO: 意思是路径信息,意思是 网页的url地址就表明了 网页的模块/控制器/操作等信息, 即path indicates info of the page.

    'TAGLIB_BEGIN' => '<' 如果修改为[, 则扩展标签(也叫xml标签)的调用就是 [volist....]... [/volist], xml标签定界符 不能跟基本标签符号如{,相冲突...否则会引起解析错误.

    如何生成tp3.2.3的多个模块?

    1. 可以用手动创建类似Home模块的Admin模块目录
    2. define('BIND_MODULE' => 'Admin'); 将index.php入口文件绑定到Admin模块,由于Admin模块不存在,所以第一次访问localhost时会自动创建 Admin模块的目录.
    3. 以后要注释掉 BIND_MODULE 模块, 恢复默认的入口为Home模块..., 以后使用Admin模块就如同Home模块一样的方法使用了...

    标签库的配置,TAGLIB_PRE_LOAD => "cx,custom"TAGLIB_BUILT_IN=>"cx,custom"是两个不同的配置,前者主要是 用于外在的 自定义的 自己创建的标签库在tp启动时就载入,适用于外在标签在多个模板大量使用的场合,不必在 模板页面再用<taglib name="custom"> 注意,所有的标签都是小写的 载入;后者是指在使用标签时不必在前面加上标签库名称,如<custom:great name="uid" value="1">...</custom:great>, 如果定义了custom为内置标签,则直接写<great name="uid" value="1">....</great>

    在tp中,在模板html文件中,凡是可以使用普通变量如 {$name} 的地方,都可以使用系统变量,{$_Get["name"]},{$Think.config.name},而且可以使用函数...

    在xml标签中,注意区分 "变量" 和 "变量名称"的区别, 变量是要加$,而变量名称 则不加$. 通常像 <volist name="user" id="vo">....</volist>中的name属性使用的是变量名称, 在value属性中要使用变量,则要加上$. 同时在标签外面的,纯粹的普通变量的输出要加$: {$name}

    volist和foreach?
    volist 中的vo可以认为是, vector output,(数组/矢量输出) 也可以认为是数组/矢量 对象vector object. volist就是矢量对象列表. volist主要是用于数据表查询结果或二维数组的输出, foreach主要用于对象或数组的输出. volist的属性主要有name, id, offset-length(用于部分输出),mod. 而foreach的属性有name,item ,key

    volist的mod?
    它是一个属性,也可以认为是一个赋值, <volist ... mod="2,5,x"> 等价于 <volist name="result" id="vo" key="i"> ...<assign name="mod" value="$i mod x"> mod="2" 实际上是 mod="key % 2" 但是你不能单独的去赋值mod, 要在volist循环中赋值,所以就直接 写在volist的属性中了, 通常要把olist mod="x" 和 eq name="mod" value="1""2""..." 结合起来使用.

    通常写volist的 id就直接写成 vo, 这是约定 习惯:<volist name="result" id="vo">

    对tp标签库的理解,不管有多复杂, 就是把它理解为 解释扩展的 <?php .... ?>代码. 解析后的代码实际上是一个 php和html混合的页面. 扩展的xml标签是为了在 html中不只是 "肯定的,不变的"输出 模板变量, 而且还要实现如同 php/js等代码程序中的 条件语句if, switch, 和循环语句for foreach volist等, 用"纯粹的html标签式的页面" 来代替html和php的混合页面.

    compare标签和eq等标签, range标签和between等标签?
    eq, gt等比较标签,是compare标签的别名, 都有name, value属性,只是compare标签多了一个type属性来指明是eq, gt,lt(less than)等.注意, 比较标签和范围标签其实都是 条件标签 if,都要解析为if条件语句... 只是比if标签更简洁.

    tp中的模板标签和 html标签 的用法不同!! html标签是不允许 在标签名 中 嵌套的, 如:<p <span> span text</span>> para text </p>的写法是错误的, 但是tp中的 模板标签, 由于要解析成php代码, 所以 在 一个标签的名称中, 在标签的属性中, 是可以"嵌套" 其他tp标签的, 如: <tr <eq id="uid" value="1">style="background-color:#eee"</eq>> ....<td>....</td> </tr>

    php中的empty和isset的区别?
    empty是判断是否为空,而isset是判断该变量或数组的元素是否设置,
    通常, 如果 $var=0,false,null,'', 则empty($var)====true
    对于isseet来说, 跟上面的一样,当 $var=0,false,''时, 则isset($var)=true,只有一个, 当$var=null的时候, isset($var)===false.

    数组和对象的写法区别?
    数组的写法是 $arr['key'], 对象的写法则是用冒号表示: $obj:member, 而要自动识别时,则用点号 $some.member, 但是,在能够确定时,最好是写明确些

    import和vendor函数的区别?
    它们其实都是在内部调用的 require, 只是开始的部分做了些调整, 如果是ThinkPHP下的 Library/Think(或者core)下的类都是可以直接使用 , 如果是 Library下的Org,则用import来引入类, 如果是Vendor下的类,要引入, 则用vendor函数, 他们的区别, 只是针对的路径不同.
    通常自己写的类/类库,或引入的 按tp的规则 写的其他人,开发团队写的 类库, 都放在 Org目录下, 使用import来引入; 如同在C++中一样,如果是没有按tp默认约定规则来写的\放在vendor目录下的类库, 就用vendor方法来引用, 只是import和vendor的参数的默认值不同.

    tp的show,display,直接echo的区别?
    echo就是直接输出内容,跟tp函数没有毛关系; display和show都是View类的成员函数, 都有三个参数('tmpl对应文件','charset,doc-type),但是display要求要有对应的tmpl文件, 而show则不一定要有对应的tmpl文件, 可以直接输出html内容...

    php是解释型语言, 解释一句,再执行一句,所以前面有输出,当后面有错误时,会终止运行,只是并不是直接翻译成机器码: 先将php源代码转换为opcode(如同在汇编语言中,nop是助记符, 0x90是opcode...,即计算机的中间代码),然后由php的解释引擎(php虚拟机,pvm): zend 来运行,也可以用jit技术在虚拟机上运行时编译成机器码来提高运行速度. 现在的语言,编译和解释的分别都不是那么严密了.

    使用高版本的php, 功能更强大,

    像__ROOT__, PUBLIC,...等都是在模板文件中,使用的, 不是在 控制器/方法|操作,中使用的, 而且是在 配置文件中的 TMPL_PARSE_STR' => array( '__PUBLIC' => ...,.....)中定义的, 因为在默认情况下, ROOT, __PUBLIC__这些都是要被解析\替换的,所以如果确实要输出 像ROOT, __PUBLIC__这样的字符串, 则可以使用 另外的模板字符串定义 TMPL_PARSE_STR' => array( '--PUBLIC--' => '__PUBLIC__' ...,.....)

    ThinkPHP的内置标签库在哪里?
    内置标签库的基类是: \ThinkPHP\Library\Think\Template\TagLib.class.php, 内置的标签库cx(标签库的名称都用小写)在\ThinkPHP\Library\Think\Template\TagLib\Cx.class.php文件中.

    C/C++为什么要使用指针分配对象?
    Object myobj这种方式是自动分配,作用域在函数范围内,当1. (使用指针会带来两个作用,也可以说是 两个问题,看你是需要还是避免) 要延长对象的作用域和生命期, 并且要使用的是对象指向内存的本身, 而不是对象的拷贝; 2.要指向的对象本身分配的内存比较大,如果用对象的拷贝,耗费的内存比较大,可能溢出栈 时, 使用只能指针比较好, 具有RAII std::unique_ptr, std::shared_ptr, ...(这个比较少见) 因此, 如果只是要在文件作用域内,进行 函数传参时, 使用 对象的本身,但是不需要延长生命期的时候, 就不要使用 指针, 而是使用 引用 就可以了, 这样就避免了指针的 "延长生命期"的 "副作用" . 当然还有其他需要使用指针的时候, 如多态的实现...

    php中的对象, 因为都是用new来实例化的,所以都用 ->(叫对象运算符)来引用(对象的成员变量,也叫属性,字段,features), 静态用::(叫双冒号)来引用. 但是在tp的模板中使用冒号:来引用对象的成员.

    后台模块 Admin 的配置参考 http://www.mamicode.com/info-detail-1181250.html

    页面trace是怎样做到的过程?
    定义'SHOW_PAGE_TRACE' => true,

    模型类的定义问题? - 注意tp中的路径问题, 很多路径,都是 规定, 系统约定, 系统中的解析器, 会从约定的路径开始解析...
    自定义模型类, 要使用"相对路径", 不用加 , 从模块开始写起:
    <?php namespace Home\Model; use Think\Model; class FooModel extends Model{...} ?>
    而实例化自定义的模型类时, 要使用 "形式上的 绝对路径" ,从  写起:
    $User = new \Home\Model\FooModel();


    数据库的连接查询?
    目的是为了从多个表中获取字段的信息,条件是两个表 中要有相关联的字段,字段的数据类型要相同,名称不一定相同.

    内连接的方式:
    mysql默认的方式就是内连接,即join=inner join, 使用join要结合on使用, on是指明两个表用 哪两个字段 进行连接查询; 不同于where,where是过滤 连接查询结果 后的条件. 如果不使用join, 则使用 "隐含"内连接, 连接字段就放在where中(这时候的where就相当于on...).

    mysql支持 中文下标key吗? 是的:如{$vo["学号"]}

    thinkphp中为什么要使用query函数?
    如果是针对 单一的一个表, 的insert delete update select等操作, 就使用tp的 链接操作函数,
    但是如果要操作的情况比这个复杂, 如查询的表不是一个表,操作的是多个表, 或者是不是普通的Crud,而是联合查询,那么这个时候,就不能使用链式函数, 而要使用原生的sql语句,调用query函数了.如下:

        $Sql= M();
        $query = "select foo.uid as '学号',foo.name,score.score from foo,score where foo.uid=score.sno and foo.name='john'";
        $query = "select foo.uid, foo.name, score.score from foo join score on foo.uid=score.sno  where foo.name='john'";
    
        $result = $Sql->query($query);
        dump($result);
    

    tp支持标准的orm和AR及原生的sql操作,为什么要写这么多"眼花缭乱"的方法呢? 是因为在实际中的需求就有这么多,有的是功能的需求,有的是效率性能上的需求.

    tp的"增删改查"就是add, delete, save, select,跟原生的sql操作名称不一样,一是,不能去"占用""覆盖"原生的操作名称,二是正好与日常的"叫法"相一致.


    $User=M('user')就是数据表对应的类的实例化对象,从oop的观点来看,它本身就应该,也可以用来操作数据表的curd操作.

    通常只有在add和save方法中,才需要创建数据对象DO, 调用`$User->create(); create($data);create($another_do); 也可以使用

    data($data)方法`, 只有创建了do(在内存中),才能用add/save方法写入数据库

    create和data创建do的区别?
    create做的工作很多,包括了获取ds,ds合法性检验,检查字段映射, 字段验证,自动完成,令牌检查等. 而data则没有那么多的附加工作和
    功能,要自己去完成.

    select子查询的作用主要有四点?
    1.用作生成子表(返回多条数据), 如 join (select....)as another_table...
    2.用作生成一个静态数值, 在算术表达式中使用
    3.用作生成 "一个" "相关子查询""动态子查询" 数值, 用在 条件等 算数表达式中
    4.用作生成数值范围,用在exist,not exist语句中.

    rand和mt_rand?
    mt_rand比rand的速度更快(快4倍?),生成的随机数更好? 在windows下, RAND_MAX的值是32768, 并且rand和mt_rand都不需要播种.

    php中生成m,n之间的随机数?
    php生成随机整数值,比aspx,java更简洁,不需要去/100, 不需要去round,ceil等,直接用mt_rand(m, n)就得到了.

    count(*)和count(column)的区别?
    http://www.cnblogs.com/wzmenjoy/p/4244590.html count(column)不计 column为null的条数?
    sum(参数), 如果参数是列名, 则表示整个列的数值的和, 如果是条件表达式,则是表示 列值满足条件表达式 的记录 行数的 总和

    不能用count(条件表达式) 如count(score<60) 来统计不及格的总数, 因为 count(参数)中,只要参数 !=NULL 则都表示计算总的记录条数. 所以,count(0)=count(1)=count(2)...=count(*)... 的
    821299-20161123161543753-77434021.png

    group by ,having等的用法:http://blog.csdn.net/zuiwuyuan/article/details/39431639
    group: 意思是: 分组,聚合,组合,统计函数

    having和where的区别?
    where是对记录进行原始条件过滤,在分组 group by语句前使用; where中不能使用聚合函数.
    having是对分组后的结果,进行条件过滤, 在having中可以使用 聚合函数,也可以使用 一般过滤条件.

    where score > max(score): error: invalid use of group function.?
    这个问题就是,"为什么在 where 子句中 要使用where score > = (select avg(score) from table)' 而不是直接使用 where score> avg(score)', 上面已经做了回答: 因为在where字句中不能使用group function! 所以,要用子查询...

    mysql 为什么要使用group by 分组?
    因为实际项目中, 有"需要分组, 按类别"进行数据查询,统计的需求. 将"某列(某个字段)具有相同值的多条记录合并为一组,最后作为一条记录输出", 注意这里是说 作为一条记录输出. 通常分组是和 聚合函数一起进行输出的, 通常输出的字段是 '分组字段1', '分组字段2...', '字段的聚合函数' from table group by '分组字段1', '分组字段2...'. 分组字段的选择是关键,要选择"某一列的值都相同的" 那个字段作为 "分组字段", 否则就失去了分组的意义,因为就没有办法分组.
    (如果select语句中的 字段 没有使用组函数,那么它就必须出现在group by字句中, 即作为分组字段,否则,就只会显示第一条记录 的那个 字段值). 也就是说, 如果group by 不跟聚合函数一起使用, select中不是使用的分组字段/group function,则就是没有意义的分组,就是根本不懂分组的人.

    mysql->php->browser的中文乱码问题?
    下面的说法是不正确的!!!

    很简单: 在mysql中不管,不要修改,保持为默认的utf-8; php就是连接的桥梁,是保证无乱码的核心; browser不用手动去设置, 它的内容的编码, 可以通过php的header函数来指定,来控制.
    也就是说, 只要保证 *.php文件 要写入到 mysql数据库的文件编码是 utf-8 就 一切ok
    一是, 跟php文件的 编辑器/ide有关, 看editor能不能设置为utf-8编码;
    二是, 如果编辑器不能设置为utf-8编码,就要用字符集转换函数

    php的 iconv和mb_convert_encoding?
    两者都不是php的原生函数库函数, 要通过扩展开启才能使用: php_icon.dll, php_mbstring.dll(可以通过phpinfo查看);
    iconv的效率比mb_convert_encoding快, 只有当不知道原来的编码,或iconv转换出错时,才使用后者;
    iconv(in_charset, out_charset, str): out_charset//TRANSLIT(TRANSLATE + IT, 表示不能准确转换时,转换成一个近似的字符也可以),//IGNORE表示不能转换时,忽略它.
    iconv和mb_convert_encoding, 他们的参数都是一样的, 但参数的方向正好相反. mb_convert_encoding(str, out_charset, [in_charset]最后这个"原来的字符编码集"参数是可选的)...

    php header的格式
    header函数调用, 要放在方法函数中, 不能放在php标签后,函数外部.header("字符串 Content-type: text/html; charset=utf-8 ");

    mysql的查询操作 "时间"概念?
    通常,一个简单的查询操作, 费时: 0.000几秒, 即万分之几秒, 多一点的操作 是 0.00几秒, 即千分之几秒.


    php的类中的成员变量和成员方法 都要显式的说明其 访问类型, public,protected,private, 默认的,如果不写访问类型,则是public.

    PHP_EOL: end of line
    在mac中: \r, unix-like: \n, windows: \r\n. 只是换行符, 但是在html中仍然只是表现为一个空格, 不会换行.

    控制器中的方法,总是 先输出本方法中输出的内容, 然后,(如果有this->display()的话), 再输出对应的视图页的内容.

    注意区别常量和"模板解析字符串"的区别?
    因为这些常量和"convention"配置很容易混淆,所以要注意区别:
    tp的常量包括: 预定义常量(如: THINK_VERSION,URL_COMMON...), 路径常量(THINK_PATH,LIB_PATH,CORE_PATH)等,系统常量(APP,ROOT,MODULE,CONTROLLER,ACTION,SELF, IS_POST)等等(这些系统常量中, 分成两种,有的只能用在PHP文件中,如: IS_POST,有的既可以用于php文件中,又可以用于View视图的html页面中, 如: URL之类的系统常量,SELF,MODULE,CONTROLLER,__ACTION__等, 而且这些变量可以用在html模板中的任意地方,既可以是地址之类的,如href,form的action,也可以直接在页面内容中输出...)

    前面的常量, **只是限于系统已经定义了的(__PUBLIC__这个好像是已经定义了的, 好像不一定只是帮组手册上所提到的那些), 如果没有定义,你就不能在view视图页面内直接使用,要使用自己定义的模板变量进行地址替换, 就必须在配置文件的TMPL_PARSE_STRING中进行设置和规定.**

    系统常量中的URL地址之类的东西,总是从根路径 "/"开始输出的(并且除了__ROOT__之外,其余都是带index.php入口地址的), 如: ROOT:/, MODULE: /index.php/Home, CONTROLLER: /index.php/Home/Index, 而且通常URL地址类的系统常量,是不带最后面的斜杠的,所以后面要接地址时,要自己加/

    R函数是做什么的?
    在同一个控制器内,调用方法时,可以直接使用 funcName(); 但是如果一个控制器的方法, 要调用另一个控制器的方法, 那么就要用R 函数了,支持从 R(module/controller/method)

    A方法和R方法的区别?
    都是跨"模块/控制器"调用方法的, A方法是明确实例化一个控制器的对象,然后调用其中的方法$Con=A('Foo'); $Con->method1(); $Con->method2()..., 相当于$Con=new FooController()..., 而R方法是每次都要实例化一个类的对象,R('Foo')->method1(); R('Foo')->method2(); 这个会生成两个实例. 因此,如果要使用其他模块的多个方法,建议使用A方法.如果只使用其他模块内的一个方法, 用R方法最简洁.

    U方法和"地址类系统变量"的区别?
    "地址类系统变量" 只能使用本模块/本控制器/本操作的方法, 如果要使用其他模块或控制器的方法地址时,就 要使用U方法了. U方法可以通过在php操作中赋值然后assign的方式使用,也可以直接在模板中使用 {:U(oper)} 会一直生成完整 的路径 /index.php/Home/Index/oper.html(很奇怪,这个也可以访问,其实应该是重定向了?)

    如何根据md5值反向 找到是哪个方法生成的cache?
    这个是不可以的! 因为md5: message-digest algorithm 5,将任意长度的字符串,经过算法处理,转换成128bit的整数,共32为16进制数字 md5是 哈希混淆,不可逆的, 也就是md5是不可解密的,将用户的密码经过md5加密后放入数据库中, 即使是管理员也不能看到用户的密码,做到了地位平等 要暴力破解,也是用一些常用的字符串经过md5加密后,做成一个表,然后遍历比较.密码验证的原理也是这样的: 将输入的密码,md5转换后,然后与数据库中保存的相比较...

    Application/Runtime/Cache/Home/缓存规则名称??.php缓存文件名称是怎么来的,如何知道它是哪个 html文件的缓存?
    为什么thinkphp的 View/Controller_name/oper_name.html 的缓存竟然成了????.php文件呢? 因为tp的view下的模板文件中使用了 模板标签,如{$varname}, {:U(....)}等, 所以经过缓存后,就成了<?php echo $varname} , echo U(...)...?> 的 php文件 tp手册上有说明, 静态缓存文件的 名称 有 多种 规则,(当然绝对不是模板文件的名称, 所以就不要用模板文件名去试探了...) 最后可能使用了md5函数

    肯定的: convention.php中并没有包含完全/所有的配置项, 如关于静态缓存的配置 TMPL_CACHE_ON => true, TMPL_CACHE_TIME => 60秒... **注意这里应该是TMPL,不是HTML. 有些所谓的手册或文章是错误的!

    part: n.部分,零件;v. 使分割,分开,分隔.
    apart: a-part: 分开的;
    partial: 部分的, 偏爱的, 钟爱的 be partial to Chinese food.
    impartial: 不偏不倚的,公平的,公正的,持平的 as an impartial observer, an impartial view.
    partly:部分地
    depart: de-(分开)-part(分隔): 分隔|分开| -> 离开 he departed from Beijing.
    因此, thinkphp中的DEPR,就是分隔符,分割符的意思.包括: TMPL_FILE_DEPR, URL_PATHINFO_DEPR等.


    thinkphp为什么能够 全盘(在任何目录或文件中都可以)应用那些 常量/变量/设置/类/函数?

    1. 所有的请求都被应用程序的入口文件index.php所拦截了
    2. 入口文件包含了ThinkPHP框架的入口文件 require ...ThinkPHP.php
    3. 在ThinkPHP.php, 首先定义了 (最基本的一些常量) 包括框架的const 预定义常量(const URL_COMMON=0 ... const EXT='.class.php' const THINK_VERSION = '3.2.3'...) , 路径常量(THINK_PATH, LIB_PATH, CORE_PATH,....), 跟系统信息 有关的常量(IS_WIN, IS_CGI,IS_CLI) 还有一个 ROOT,是在ThinkPHP.php文件中定义的.

    4. 然后调用了 require CORE_PATH.'Think'.EXT
    5. 在Think.class.php是tp 整个底层框架的 引导类, 由它加载所有的底层架构,包括模型/视图/缓存/日志/配置等等... 所以可以实现上面的目的...
      6 最后引导应用程序启动 Think\Think::start();

    Thinkphp为什么能够拦截所有请求, 实现单一入口?
    由index.php来响应所有的http请求,来统一调度 :如同一栋房子中的多个房间只有一扇门,进入门之后, 再到哪个房间,则由 dispatch::dispatch() 来决定路由和哪个控制器和action,在dispatch中有 $_SERVER['HTTP_URI'],解析它就知道是哪个controller和action了. 这个 dispatch::dispatch() 里面就对url进行了分析, 结合 getController /Action/ Module 确定出了 ...

    Runtime目录是在App目录下, 不是在模块目录下Home, 它是包括Cache, Data, Log等在内的,其中Cache下再分模块Home等...

    页面布局: 按钮元素靠两边, 内容占中间.

    开发功能模块的思路?
    先要进行功能整理, 弄清该模块(管理)包括哪些功能, 然后可以用两种方式来组合实现: 一是模块为目录,每个功能为一个单独的文件,这样功能之间相互独立,但是不利于代码的共享; 二是,模块定义为一个类文件,其中的功能定义为类中的方法...

    有关/module/controller/action____的系统常量 是在: CORE_PATH/dispatch.class.php中定义的, dispatcher类就是完成 /module/controller/action对应的常量的定义, 以及解析pathinfo的路径地址进行 路由和调度 ,将模块/控制器/动作的形式 解释调度到 对应的视图html模板上去...

    class dispatcher{  //这里是er
        static public function dispatch(){  // 这里没有-er
            ....
            define('__CONTROLLER__', __MODULE__.$depr.(defined(BIND_CONTROLLER) ? '' :
                 ($urlCase ? parse($controller) : $controller ));
    
            ...
    
    }
    
    }
    

    而__PUBLIC__, ROOT, __MODUEL__等在模板中的替换工作, 则是在 THINK_PATH/Behavior/ContentReplace.class.php中 的 入口函数 public function run(&$content)->templateContentReplace($content)中,作为$replace=array(..., 'PUBLIC' => ROOT."/Public"...); 来替换的...

    static 和publi private等的位置关系?
    static和public等位置可以颠倒. 说法是: 编译的先后顺序不同,但结果是一样的; 静态的公开成员和公开的静态成员; 跟不同语言的编写"约定"的风格有关,比如c++中就把public放在static的前面, php中就把static放在public的前面,遵循大多数人的/语言的默认风格就好. 在php中, 类都是public的 ,static是类层次的,public是成员层次的.php中大多数都是将static放在public的前面的,如: static public function dispatch(){...}

    如何设置地址重写?
    地址重写Rewrite跟 配置文件convention.php中的 URL_REWRITE=>2, 'URL_MODEL'=>1等都没有关系,.htacess是分布式重写控制, 可以实现服务器级别和目录级别的重写. 只要放在某个目录下,那么这个目录就可以自动 实现地址重写,如果放在app的父目录下,则整个项目都可以实现重写. (原生的.htaccess实际上只是实现了隐藏index.php的功能)
    要开启Rewrite, 只要开启apache的rewrite模块功能就好了 在上面打勾就行.

    Rewrite目的是为了 url跳转和地址隐藏,可以实现 伪静态, 域名跳转,防止盗链.
    <IfModule mod_rewrite.c>
    Options +FollowSymLinks //这个是必须的,否则报错: 500 服务器内部错误
    
    RewriteEngine On
    
    测试(Perl的 (类似linux的shell)正则表达式) 匹配条件, 依次有多条, 条件成立(测试匹配,如同if...)才执行下面的Rewrite substition
    
    // %{REQUEST_FILENAME}: htaccess/mod_rewrite定义的内部变量,表示请求的文件
    // -d:表示前面的%{REQUEST_FILENAME}, 存在且是目录 , -f表示 存在且为普通文件.
    // !-d, !-f 就表示 要么不存在, 或者不是目录或文件.  (通常的情况是 表示 "不存在", 如果要访问的地址存在,一般都是目录/文件,则直接访问,
    // 因为不匹配测试条件,所以就不执行 rewrite rule了
    RewriteCond %{REQUEST_FILENAME} !-d  
    RewriteCond %{REQUEST_FILENAME} !-f
    
    RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] 
    
    RewriteRule ^(.*)$  http://other.example.com/$1 [参数/标记/附加说明]
    
    RewriteRule指令/语句的格式:  RewriteRule Pattern Substitution [flags] 参考:http://blog.csdn.net/paulluo0739/article/details/17711851
    QSA: qsappend, PT: passthrough(在应用多个模块如mod_rewrite, mod_alias对地址进行重写时使用),L: last.
    
    </IfModule>

    821299-20161123091356503-1014887863.png

    配置文件convention.php中的'VAR_CONTROLLER'=>'c' ,就是用来在 $_GET['c']中获取控制器的.


    展开全文
  • thinkphp5 开发的那点事

    千次阅读 2017-03-28 10:59:11
    知识点1:* 应用程序的流程图。对于一般的框架是这样的。...在加载应用程序控制器之前,http请求以及任何用户提交的数据进行安全检查; 控制器加载模型、核心类库、辅助函数以及其他所有处理请求所需
  • 解决laravel groupBy 查询结果进行分组出现的问题使用laravel groupBy方法时不知为什么一直出现语法错误,查了很资料才找到原因:$data = Orders::select("orders.*","user.name","orderstatu.name as ssname")-...
  • thinkphp5 速查表

    2018-05-21 15:13:39
    // 格式: mysql://username:passwd@localhost:3306/DbName?param1=val1¶m2=val2#utf8 Db::parseDsn($dsnStr); // 调用驱动类的方法 Db::__callStatic($method, $params); Debug // 记录时间(微秒)和内存使用...
  • 关注微信公众号 “PHP大神” 回复“面试题”可以免费下载更php相关面试题,整理不易请关注,如有错误请包涵哈! 1、冒泡排序,面试前一定要记住哦! function maopao($arr) { $len = count($arr); $n ...
  • Python:orator-orm操作实践

    千次阅读 2019-12-12 15:40:59
    orator ...Orator文档不是很完整,不过可以结合Laravel和ThinkPHP文档,思想和操作基本一致 (英文)https://laravel.com/docs/5.8/database (中文)https://www.kancloud.cn/manual/thinkphp5/13...
  • PHP面试100题汇总

    2021-01-28 08:40:05
    PHP面试100题汇总1,Http 和Https的区别第:http是超文本传输协议,信息是明文传输,https是具有安全性的ssl加密传输协议第二:http和https使用的是完全不同的连接方式,端口也不一样,前者80 或者443第三:http...
  • MVCS 提供种将你的应用程序分离到提供特定功能的无关联的层的很自然的方法。 view 层处理用户交互。 model 层处理用户创建的或从外部获取的数据。 controller 提供种封装各层之间复杂 交互的机制。 最后, ...
  • PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、Thinkphp,...
  • [乐意黎原创]PHP 老司机指南

    千次阅读 2017-01-13 11:56:25
    8、用php和mysql如何创建一个数据库?P Mysql_create_db(‘dbname’); 9、require和include有什么区别?P 都是用来加载文件的。 1)include报警报,require报致命错误。 2)include执行时文件每次都...
  • MySQL数据库基础与应用 1.【单选题】下列哪个是MySQL的配置文件(B) (8分) A COPYING B my-default.ini C README D bin 2. 【单选题】以下哪项不是mysql的特点(D) (8分) A Mysql是开源的 B使用方便 C功能全面 D ...
  • 步骤:网页搭建入门 │ │ ├─01 html │ │ │ 1-1 html准备工作.mp4 │ │ │ 1-2 选择练习.png │ │ │ 1-3 编程练习.png │ │ │ 2-1 字体标签.mp4 │ │ │ 2-3 段落标签和注释.mp4 │ │ │ 2-4 标题标签...
  • 2020最新PHP很全的面试题(附答案)

    万次阅读 2020-05-23 09:04:04
    主要特征:封装、继承、多态。 2.SESSION 与 COOKIE的区别是什么,请从协议,产生的原因与作用说明? 1、http无状态协议,不能区分用户是否是从同个网站上来的,同个用户请求不同的页面不能看做是同个用户。 ...
  • 1.__construct(),类的构造函数 ...6.__set(),设置个类的成员变量时调用 7.__isset(),当不可访问属性调用isset()或empty()时调用 8.__unset(),当不可访问属性调用unset()时被调用。 9.__sleep
  • tp5

    千次阅读 2018-05-06 23:46:03
    ThinkPHP5.0开发.架构1.架构总览MVC是个设计模式,它强制性的使应用程序的输入,处理和输出分开。使用MVC应用程序被分成三个核心部件:模型,视图,控制器,他们各自处理自己的任务。入口文件:用户请求的php...
  • PHP面试题()

    千次阅读 2018-06-09 11:33:14
    PHP的意思PHP是个基于服务端来创建动态网站的脚本语言,您可以用PHP和HTML生成网站主页 什么事面向对象?主要特征是什么?面向对象是程序的种设计方式,它利于提高程序的重用性,使程序结构更加清晰。主要特征...
  • TP5学习(七):模型

    千次阅读 2019-05-03 20:38:22
    、定义 定义个User模型类: namespace app\index\model; use think\Model; class User extends Model { } 默认主键为自动识别,如果需要指定,可以设置属性: namespace app\index\model; use think\Model; ...
  • select_db()函数更改默认的数据库 266 15.3.3 使用mysqli_close()函数关闭MySQL连接 267 15.3.4 使用mysqli_query()函数执行SQL语句 267 15.3.5 获取查询结果集中的记录数 268 15.3.6 获取结果集中的条记录作为...
  • 记录php-面试

    2021-08-11 09:31:37
    简单来说,Redis做个快照(利用fork)保存在磁盘上 优点: - 结构紧凑体积小,加载速度快(相比AOF) - 可以做定期备份 缺点: - 动作大、消耗大:全量操作对于磁盘、CPU、内存等均有消耗 - 无法做到"实时...
  • PHP面试总结

    2022-01-06 23:28:02
    主要特征:封装、继承、多态。 SESSION 与 COOKIE的区别是什么,请从协议,产生的原因与作用说明? http无状态协议,不能区分用户是否是从同个网站上来的,同个用户请求不同的页面不能看做是同个用户。 ...
  • php常见面试题总结

    2022-01-07 17:43:49
    以下全部是转载别人的总结,感觉回答不错: 面试之前看看公司的资料,可以看出面试的...答:由于我们公司是个外包公司,很项目都是交叉进行的,论坛,微信,商城我都做过,我主要负责的模块有.....; 3.你为什...
  • PHP面试题(2021版)

    千次阅读 2021-04-28 15:43:53
    关注微信公众号 “PHP大神” 回复“面试题”可以免费下载更php相关面试题,整理不易请关注,如有错误请包涵哈! 1、__FILE__表示什么意思? 文件的完整路径和文件名。如果用在包含文件中,则返回包含文件名...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 133
精华内容 53
关键字:

thinkphp6 多态一对多关联 mysql 创建

mysql 订阅