ThinkPHP 3.2 使用的一些记录

在 View 模板引擎中输出数组的下标值

如 数组 $list 和 下标 $data.vo.id

{$list[$data[vo][id]]}

若变量为空,赋予默认值(判断空)

{$vo.position_id|default='空'}

获得 MySQL 数据表备注

//获取备注信息
public function _get_field() {
  $model = new \Think\Model();
  $controller_name = $this->CamelCaseToUnderScore(CONTROLLER_NAME);
  $rs = $model->query("select `column_name`,`column_comment` from information_schema.COLUMNS WHERE TABLE_SCHEMA = '".C('DB_NAME')."' AND TABLE_NAME = '".C('DB_PREFIX').$controller_name."'");

  $arr = array_column($rs,'column_comment','column_name');
  return $arr;
}
//驼峰命名转下划线命名
public function CamelCaseToUnderScore($str)
{
  $dstr = preg_replace_callback('/([A-Z]+)/',function($matchs)
  {
    return '_'.strtolower($matchs[0]);
  },$str);
  return trim(preg_replace('/_{2,}/','_',$dstr),'_');
}

PHP 数组变量传递给 JS

var arr=transArr({$array|json_encode=true}); 
function transArr(obj) {
  var tem=[];
  $.each(obj, function(i) {
	tem[i]=obj[i];
  });
  return tem;
}

ThinkPHP 使用 WorkerMan 的一些记录

通过 composer 安装

composer require topthink/think-worker

启动

php think worker

初次使用可能会报错

[root@instance-jewlel2q www.imgram.cn]# php think worker
Starting Workerman http server...
Workerman[think] start in DEBUG mode
stream_socket_server() has been disabled for security reasons in file /home/wwwroot/www.imgram.cn/vendor/workerman/workerman/Worker.php on line 2178

原因是 stream_socket_server 函数被 php.ini 禁用

  • 运行 php –ini 找到 php.ini 文件
  • 打开 php.ini 找到 disable_functions 一项,将 stream_socket_server 禁用项删掉。
  • 重启 php-fpm。

ThinkPHP 5 引入 百度云 BaiduBCE SDK

项目根目录使用 Composer

composer require baidubce/bce-sdk-php

在 Controller 中引入

<?php
require '../vendor/autoload.php';//这句不用,自动引入
use BaiduBce\Services\Bos\BosClient;

测试连接

public function baidu(){
  $BOS_TEST_CONFIG =
	array(
	  'credentials' => array(
	  'accessKeyId' => '684b94f7675142d79ed2bxxxxxxxxxxx',
	  'secretAccessKey' => '0ee6b11cc38445fc8xxxxxxxxxxxxx',
	  ),
	  'endpoint' => 'https://todo.cdn.bcebos.com',
	);
  $client = new BosClient($BOS_TEST_CONFIG);
  dump($client);
}

输出结果

上传文件测试

public function baidu(){
  $BOS_TEST_CONFIG =
    array(
      'credentials' => array(
      'accessKeyId' => '684b94f7675142d79ed2bxxxxxxxxxxx',
      'secretAccessKey' => '0ee6b11cc38445fc8xxxxxxxxxxxxx',
      'sessionToken' => ''
      ),
    'endpoint' => 'https://todo.cdn.bcebos.com',
    'stsEndpoint' => '',
  );
  $client = new BosClient($BOS_TEST_CONFIG);
  $bucketName = 'path';
  $a = $client->putObjectFromFile($bucketName, 'abc.png', 'tmp/x.png');
  dump($a);
}

如果用的是百度的服务器,可能出现在线报错

[curl] 6: Could not resolve host: todo.cdn.bcebos.com; Unknown error [url] 

DNS 的问题

vim /etc/resolv.conf 

修改

但是修改 DNS 的方式会使无法使用内网传输,

所以需要将上传地址改为官方域名,不要用 CDN 加速域名,这样百度内网服务器之间网就可以妙传了

ThinkPHP 3.2.3 提示 could not find driver PDO 链接报错

ThinkPHP 3.2.3 提示

could not find driver

抛出了 PDOException 异常,说明 PDO 连接报错

解决方法安装 pdo_mysql 扩展,该扩展在 php 源码包里 下载 php 源码并解压

cd ~
cd php-5.6.30/ext/pdo_mysql
/usr/local/php5/bin/phpize
./configure --with-php-config=/usr/local/php5/bin/php-config
make
make install

在 php.ini 里添加 extension=pdo_mysql.so

Linux 下 ThinkPHP 与 Swoole 搭配 ThinkPHP 性能对比测试

ThinkPHP 5.0.21

Server Software:        nginx
Server Hostname:        127.0.0.1
Server Port:            8080

Document Path:          /
Document Length:        39 bytes

Concurrency Level:      10
Time taken for tests:   9.064 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      218000 bytes
HTML transferred:       39000 bytes
Requests per second:    110.33 [#/sec] (mean)
Time per request:       90.637 [ms] (mean)
Time per request:       9.064 [ms] (mean, across all concurrent requests)
Transfer rate:          23.49 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       1
Processing:    15   90  37.8     87     217
Waiting:       15   90  37.8     87     217
Total:         15   90  37.8     88     217

Swoole 搭配 ThinkPHP 5.0.21

Server Software:        swoole-http-server
Server Hostname:        127.0.0.1
Server Port:            9501

Document Path:          /
Document Length:        39 bytes

Concurrency Level:      10
Time taken for tests:   4.355 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      1870000 bytes
HTML transferred:       390000 bytes
Requests per second:    2296.38 [#/sec] (mean)
Time per request:       4.355 [ms] (mean)
Time per request:       0.435 [ms] (mean, across all concurrent requests)
Transfer rate:          419.36 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       6
Processing:     1    4   3.7      4     166
Waiting:        0    4   3.6      3     166
Total:          1    4   3.7      4     166

配置信息

Swoole 适配 ThinkPHP 5 ab 压力测试 与 原生 ThinkPHP 对比

swoole 适配 thinkphp 5.0.21

Server Software:        swoole-http-server
Server Hostname:        127.0.0.1
Server Port:            9501

Document Path:          /
Document Length:        39 bytes

Concurrency Level:      10
Time taken for tests:   2.378 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      1870000 bytes
HTML transferred:       390000 bytes
Requests per second:    4204.38 [#/sec] (mean)
Time per request:       2.378 [ms] (mean)
Time per request:       0.238 [ms] (mean, across all concurrent requests)
Transfer rate:          767.79 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       2
Processing:     1    2   1.2      2      21
Waiting:        1    2   1.1      2      21
Total:          1    2   1.1      2      21

与原生 ThinkPHP 对比

Server Software:        nginx/1.15.3
Server Hostname:        127.0.0.1
Server Port:            8080

Document Path:          /index.php
Document Length:        39 bytes

Concurrency Level:      10
Time taken for tests:   48.468 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      2020000 bytes
HTML transferred:       390000 bytes
Requests per second:    206.32 [#/sec] (mean)
Time per request:       48.468 [ms] (mean)
Time per request:       4.847 [ms] (mean, across all concurrent requests)
Transfer rate:          40.70 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    2  75.8      0    3611
Processing:     9   45  73.4     42    3651
Waiting:        9   45  73.4     42    3651
Total:          9   47 105.2     42    3651

原生 PHP 输出 hello world

Server Software:        nginx/1.15.3
Server Hostname:        127.0.0.1
Server Port:            8080

Document Path:          /hello_world.php
Document Length:        11 bytes

Concurrency Level:      10
Time taken for tests:   0.870 seconds
Complete requests:      5000
Failed requests:        0
Total transferred:      870000 bytes
HTML transferred:       55000 bytes
Requests per second:    5749.02 [#/sec] (mean)
Time per request:       1.739 [ms] (mean)
Time per request:       0.174 [ms] (mean, across all concurrent requests)
Transfer rate:          976.88 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       2
Processing:     1    2   0.5      1       5
Waiting:        1    1   0.4      1       4
Total:          1    2   0.5      2       5

本机配置

Swoole 适配 ThinkPHP 5.0.21

新增代码

server/http_server.php

<?php
/**
 * Created by PhpStorm.
 * User: guofeng
 * Date: 2018/9/8
 * Time: 上午11:21
 */

$http = new swoole_http_server('0.0.0.0',9501);
$http->set([
    'enable_static_handler'=>true,
    'document_root'=>'../public/static',
    'worker_num'=>4,
]);
$http->on('WorkerStart',function(swoole_server $server,$worker_id){
    // 定义应用目录
    define('APP_PATH', __DIR__ . '/../application/');
    // ThinkPHP 引导文件
    // 1. 加载基础文件
    require __DIR__ . '/../thinkphp/base.php';
});
$http->on('request',function ($request,$response) use($http){

    $_SERVER = [];
    if(isset($request->server)){
        foreach($request->server as $k => $v){
            $_SERVER[strtoupper($k)] = $v;
        }
    }

    if(isset($request->header)){
        foreach($request->header as $k => $v){
            $_SERVER[strtoupper($k)] = $v;
        }
    }

    $_GET = [];
    if(isset($request->get)){
        foreach($request->get as $k => $v){
            $_GET[$k] = $v;
        }
    }

    $_POST = [];
    if(isset($request->post)){
        foreach($request->post as $k => $v){
            $_POST[$k] = $v;
        }
    }

    // 2. 执行应用
    ob_start();

    try{
        think\App::run()->send();
    }catch (\Exception $e){
        //todo
    }

    $res = ob_get_contents();
    ob_end_clean();
    $response->end($res);
});
$http->start();

ThinkPHP 核心文件修改

thinkphp/library/think/Request.php

/**
 * 获取当前请求URL的pathinfo信息(含URL后缀)
 * @access public
 * @return string
 */
public function pathinfo()
{
    if(isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] !='/'){
        return ltrim($_SERVER['PATH_INFO'], '/');
    }
    //if (is_null($this->pathinfo)) {
        if (isset($_GET[Config::get('var_pathinfo')])) {
            // 判断URL里面是否有兼容模式参数
            $_SERVER['PATH_INFO'] = $_GET[Config::get('var_pathinfo')];
            unset($_GET[Config::get('var_pathinfo')]);
        } elseif (IS_CLI) {
            // CLI模式下 index.php module/controller/action/params/...
            $_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
        }

        // 分析PATHINFO信息
        if (!isset($_SERVER['PATH_INFO'])) {
            foreach (Config::get('pathinfo_fetch') as $type) {
                if (!empty($_SERVER[$type])) {
                    $_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ?
                    substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type];
                    break;
                }
            }
        }
        $this->pathinfo = empty($_SERVER['PATH_INFO']) ? '/' : ltrim($_SERVER['PATH_INFO'], '/');
    //}
    return $this->pathinfo;
}
/**
 * 获取当前请求URL的pathinfo信息(不含URL后缀)
 * @access public
 * @return string
 */
public function path()
{
    //if (is_null($this->path)) {
        $suffix   = Config::get('url_html_suffix');
        $pathinfo = $this->pathinfo();
        if (false === $suffix) {
            // 禁止伪静态访问
            $this->path = $pathinfo;
        } elseif ($suffix) {
            // 去除正常的URL后缀
            $this->path = preg_replace('/\.(' . ltrim($suffix, '.') . ')$/i', '', $pathinfo);
        } else {
            // 允许任何后缀访问
            $this->path = preg_replace('/\.' . $this->ext() . '$/i', '', $pathinfo);
        }
    //}
    return $this->path;
}

访问方式

命令行 启动

php http_server.php

访问地址

http://localhost:9501/?s=index/index/index
http://localhost:9501/index/index/index

ThinkPHP 3.2 连接多数据库

<?php

return array(
    /* 数据库设置 */
    'DB_TYPE'               =>  'mysqli',     // 数据库类型
    'DB_HOST'               =>  'localhost', // 服务器地址 rds190co1ii65n556p9v.mysql.rds.aliyuncs.com
    'DB_NAME'               =>  'kh',          // 数据库名
    'DB_USER'               =>  'root',      // 用户名
    'DB_PWD'                =>  'root',          // 密码
    'DB_PORT'               =>  '3306',        // 端口
    'DB_PREFIX'             =>  'bj_',    // 数据库表前缀
    'DB_PARAMS'          	=>  array(), // 数据库连接参数
    'DB_DEBUG'  			=>  TRUE, // 数据库调试模式 开启后可以记录SQL日志
    'DB_FIELDS_CACHE'       =>  true,        // 启用字段缓存
    'DB_CHARSET'            =>  'utf8',      // 数据库编码默认采用utf8
    'DB_DEPLOY_TYPE'        =>  0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
    'DB_RW_SEPARATE'        =>  false,       // 数据库读写是否分离 主从式有效
    'DB_MASTER_NUM'         =>  1, // 读写分离后 主服务器数量
    'DB_SLAVE_NO'           =>  '', // 指定从服务器序号
    'DB_CONFIG2'=>array(
        /* 数据库设置 */
        'DB_TYPE'               =>  'mysqli',     // 数据库类型
        'DB_HOST'               =>  'localhost', // 服务器地址 rds190co1ii65n556p9v.mysql.rds.aliyuncs.com
        'DB_NAME'               =>  'ald',          // 数据库名
        'DB_USER'               =>  'root',      // 用户名
        'DB_PWD'                =>  'root',          // 密码
        'DB_PORT'               =>  '3306',        // 端口
        'DB_PREFIX'             =>  'ocenter_',    // 数据库表前缀
        'DB_PARAMS'          	=>  array(), // 数据库连接参数
        'DB_DEBUG'  			=>  TRUE, // 数据库调试模式 开启后可以记录SQL日志
        'DB_FIELDS_CACHE'       =>  true,        // 启用字段缓存
        'DB_CHARSET'            =>  'utf8',      // 数据库编码默认采用utf8
        'DB_DEPLOY_TYPE'        =>  0, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
        'DB_RW_SEPARATE'        =>  false,       // 数据库读写是否分离 主从式有效
        'DB_MASTER_NUM'         =>  1, // 读写分离后 主服务器数量
        'DB_SLAVE_NO'           =>  '', // 指定从服务器序号
    )
);
使用默认的:M('tablename')
使用第二个:M('tablename','表前缀','DB_CONFIG2')

 

MySQL 中支持 emoji 表情的存储 ThinkPHP

MySQL 的 utf8 编码的一个字符最多 3 个字节,但是一个 emoji 表情为 4 个字节,所以 utf8 不支持存储 emoji 表情。但是 utf8 的超集 utf8mb4 一个字符最多能有 4 字节,所以能支持 emoji 表情的存储。下面介绍了关于如何修改 mysql 数据库的编码格式变为 utf8mb4 的具体方法。

找到 /etc/ 路径下的 my.cnf 文件(或 /etc/mysql/ 路径下),通过 vim 命令 vim /etc/my.cnf 打开该文件并进行编辑,需添加如下所示配置:

[client]
default-character-set=utf8mb4

[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect=’SET NAMES utf8mb4'

[mysql]
default-character-set=utf8mb4

Continue reading MySQL 中支持 emoji 表情的存储 ThinkPHP