在使用ThinkPHP3.1.3多语言的时候,发现如果输入未定义的多语言参数比如?l=zn-c那么就会返回大写的变量名,这是因为官方用的stripos函数只看有没有存在而不看是否完全匹配,应该要换个方式查看是否匹配,我的方法如下:

把官方 ThinkPHP -> Extend -> Behavior -> CheckLangBehavior.class.php 中 checkLanguage 函数中的这一段

if (false === stripos(C('LANG_LIST'), $langSet)) { // 非法语言参数
    $langSet = C('DEFAULT_LANG');
}

替换为

$hasDefined = false;
foreach (explode(',', C('LANG_LIST')) as $langDefined){
    if ($langSet === $langDefined) {
        $hasDefined = true;
        break;
    }
}
if (!$hasDefined) {
    $langSet = C('DEFAULT_LANG');
}

data.update.lastsys.time.agopunc.commaarticle.create.bypunc.commaarticle.file.inpunc.colonThinkPHP

cookie:
在ThinkPHP应用配置文件中添加

'COOKIE_DOMAIN' => 'xxx.com'

session:
在根目录index.php中添加

define ( 'DOMAIN', 'yourdomain.com' );
ini_set ( 'session.cookie_path', '/' );
ini_set ( 'session.cookie_domain', DOMAIN );

客户端cookie使用jquery操作,需要添加:

$.cookie(COOKIE_KEY, COOKIE_VALUE, {
    expires : COOKIE_EXPIRES_DAY,
    path : '/',
    domain : COOKIE_DOMAIN
});

同样的,在删除cookie的时候也要对应添加:

$.removeCookie(COOKIE_KEY, {
    path : '/',
    domain : COOKIE_DOMAIN
});

data.update.lastsys.time.agopunc.commaarticle.create.bypunc.commaarticle.file.inpunc.colonThinkPHP

修改php.ini:allow_call_time_pass_reference = Off改为allow_call_time_pass_reference = On

文档注解为:

是否启用在函数调用时强制参数被按照引用传递。此方法已不被赞成并在 PHP/Zend 未来的版本中很可能不再支持。鼓励使用的方法是在函数定义中指定哪些参数应该用引用传递。鼓励大家尝试关闭此选项并确保脚本能够正常运行,以确保该脚本也能在未来的版本中运行(每次使用此特性都会收到一条警告,参数会被按值传递而不是按照引用传递)。

在函数调用时通过引用传递参数是不推荐的,因为它影响到了代码的整洁。如果函数的参数没有声明作为引用传递,函数可以通过未写入文档的方法修改其参数。要避免其副作用,最好仅在函数声明时指定那个参数需要通过引用传递。

要引用传入参数,可以两种方法:

// 1
function test1($a, $b){
    $b = "fun_test1";
    return;
}

$a = "a_value";
$b = "b_value";

test1($a, &$b);
// 2
function test2($a, &$b){
    $b = "fun_test2";
    return;
}

$a = "a_value";
$b = "b_value";

test2($a, $b);

第一种情况就有可能会出现Call-time pass-by-reference has been deprecated这样的警告,所以建议使用第二种。


data.update.lastsys.time.agopunc.commaarticle.create.bypunc.commaarticle.file.inpunc.colonThinkPHP

ThinkPHP关闭调试后,我开启了错误报告'SHOW_ERROR_MSG' => 'true'结果页面报错提示Log类找不到。

以下为在官方找到的解决办法:

解决偶尔出现Class ‘Think\Log’ not found的奇葩问题(并非每次必现,偶尔删除缓存可以解决,偶尔删除缓存页不行)— php5.3版本bug(PHP 5.4.21已经fixed这个bug):set_error_handler处理函数无法调用spl_autoload_register来自动加载Log类的问题。

解决方法:
文件:ThinkPHP/Library/Think/Think.class.php
位置:Storage::connect(STORAGE_TYPE);后面添加一行代码version_compare(PHP_VERSION, ‘5.4.21’, ‘<') && Log::INFO;,在error_handler之前预先加载Log类。

原因参考:
http://stackoverflow.com/questions/1942507/set-error-handler-function-not-calling-autoload
https://bugs.php.net/bug.php?id=47987
https://bugs.php.net/bug.php?id=65322


data.update.lastsys.time.agopunc.commaarticle.create.bypunc.commaarticle.file.inpunc.colonThinkPHP

首先,要说一下MySQL这个大坑…MySQL中的UTF-8并不是真正的UTF-8,只支持最多三个字节的字符,这个BUG没有修复,取而代之(不肯认错)提供了utf8mb4这个字符集…具体请看

然后使用了UTF-8后,发现中文排序混乱,出现这个问题的原因是因为MySQL在查询字符串时是大小写不敏感的,在编绎MySQL时一般以ISO-8859字符集作为默认的字符集,因此在比较过程中中文编码字符大小写转换造成了这种现象。

解决方案有很多,以下几种思路:

1.对于包含中文的字段加上”binary”属性,使之作为二进制比较,例如将name char(10)改成name char(10) binary。如果你使用源码编译MySQL,可以编译MySQL时使用–with–charset = gbk参数,这样MySQL就会直接支持中文查找和排序了(默认的是latin1)。也可以用extra-charsets = gb2312,gbk 来加入多个字符集。

2.如果不想对表结构进行修改或者重新编译MySQL,也可以在查询语句的order by部分使用CONVERT函数来强制MySQL按中文排序(UTF8 默认校对集是utf8_general_ci)。比如:

select * from table_name order by CONVERT(ChineseColumnName USING GBK);

我选了第二种方案来操作,结果又带出来个坑:在前段传参时候使用order = 'CONVERT(ChineseColumnName USING GBK)',结果ThinkPHP直接报错。一开始以为是不是不能这么用,然后查了半天无果,用fetchSql(true)方法输出MySQL语句一看,乖乖,怎么order这里只剩下USING前面的部分了,GBK)这右边部分屁股消失了,导致MySQL语句出现明显的语法错误。继续查看问题,网上有说ThinkPHP库里的ViewModel.class.php文件,在checkOrder方法这里有个trim()的遗漏,填补即可,一激动:

仔细看看我的文件目录和他不一样啊,他是www\ThinkPHP\Extend\Model\ViewModel.class.php,我是www\ThinkPHP\Library\Think\Modal\ViewModel.class.php,估计差了几个版本。然后我的文件里,trim()已经有了,Boom…我陷入了沉思…仔细看方法,实际上是对字符串进行了切割,而我现在的字符串,有3个空格,他只用了前两个…我TMD…改源码吧不太想,然后又查了查,突然看到人家用了个array(),哦!对哦!他不是判断是否字符串再处理么,我用数组不就好了。果然,妥妥的!


data.update.lastsys.time.agopunc.commaarticle.create.bypunc.commaarticle.file.inpunc.colonThinkPHPpunc.caesuraMySQL

ThinkPHP模型视图使用很便捷,但是这次开发游戏公会系统却遇到了一个问题,一个公用道具隶属于一个公会,而借用道具的角色也有自己隶属的公会,但可能并不是同一个公会。因此在做视图模型的时候,需要两次左外联公会表。问题由此产生,虽然我用了_as这个别名参数,但是无论如何操作,都只显示后面那个公会表。百度找不到相关材料,因此自己尝试修复,过程如下:

首先就是确认_as的效果,通过输出sql语句发现是起效果的,的确在语句中显示了别名,但此时仍只能显示后一个公会表。

思考是否是我模型顺序问题?尝试修改左外联表的顺序,结果直接报错说找不到某个条件,百度后发现也有同样问题,好像是个BUG?

弄到凌晨2点,因为还在做单位里疾控工作,这几天一直熬夜太累了实在难受,躺床上继续想…突然想到是否列别名也要都不一样?尝试无果…

第二天起来记得好像以前解决过,查之前代码和笔记无果…简化视图模型,尝试加法,从零开始拼视图,然后发现自己做的数据里缺少了角色的ID信息,马上加上去,结果还是不行,BUG依旧(看来真的可能是BUG?)

再次阅读官方文档,官档有提到_table这个参数,思考了下,感觉每次第一个公会表都被忽略,是否是ThinkPHP的方法里重复表名会过滤?修改表名为自定义表名,然后用_table参数来指定实际表,果然就可以了,也不用再使用_as这个参数,我真的是…

<?php

namespace Home\Model;

use Think\Model\ViewModel;

class PCHRUGViewModel extends ViewModel
{
    public $viewFields = array(
        'piecehistoryt' => array(
            'PCH_Id',
            '_type' => 'LEFT'
        ),
        'guildt' => array(
            'G_Id',
            '_on' => 'piecehistoryt.G_Id = guildt.G_Id',
            '_type' => 'LEFT'
        ),
        'rolet' => array(
            'R_Id',
            '_on' => 'piecehistoryt.R_Id = rolet.R_Id',
            '_type' => 'LEFT'
        ),
        'roleguildt' => array(
            '_table'=> 'guildt',
            'G_Id' => 'RG_Id',
            '_on' => 'rolet.G_Id = roleguildt.G_Id'
        )
    );
}

我TM真聪明…


data.update.lastsys.time.agopunc.commaarticle.create.bypunc.commaarticle.file.inpunc.colonThinkPHP

定位到安装目录,composer输入composer require topthink/think-view即可…升级问题多…


data.update.lastsys.time.agopunc.commaarticle.create.bypunc.commaarticle.file.inpunc.colonThinkPHP

ThinkPHP 3.X版本中使用header会自动跳转,但是到了5.X/6.X不行。实际上只要后面加exit();就可以了。但是不推荐,因为会引发另外个问题:对session操作失效。建议还是用return redirect($uri)


data.update.lastsys.time.agopunc.commaarticle.create.bypunc.commaarticle.file.inpunc.colonThinkPHP

ThinkPHP 6.0取消了字母方法,也就是说本来TP3.X里用得好好的R方法不行了…在TP6.X里需要引用空间命名来实现。但是使用后发现,会报错:

...
use app\controller\Wx;
...

class Index extends BaseController
{
  public function test()
  {
    $Wx = new Wx;
...
too few arguments to function app\basecontroller::__construct()... Blablabla

查了下资料,官方大佬说:永远不要去手动实例化一个控制器类,如果你需要这样做就拆分一个控制器分层出来或者逻辑层、服务层之类的。
但还是有解决方案:

$Wx = new Wx($this->app);

不过就像官方说的还是不建议这样,写在公共函数里吧。


data.update.lastsys.time.agopunc.commaarticle.create.bypunc.commaarticle.file.inpunc.colonThinkPHP

1.MySQL的版本
utf8mb4的最低mysql版本支持版本为5.5.3+,若不是,请升级到较新版本。

2.修改MySQL配置文件
修改mysql配置文件my.cnf(windows为my.ini)
my.cnf一般在etc/mysql/my.cnf位置。找到后请在以下三部分里添加如下内容:
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect = ‘SET NAMES utf8mb4’

3.重启数据库,检查变量

SHOW VARIABLES WHERE Variable_name LIKE 'character_set_%' OR Variable_name LIKE  'collation%';

Variable_name Value
character_set_client utf8mb4
character_set_connection utf8mb4
character_set_database utf8mb4
character_set_filesystem binary
character_set_results utf8mb4
character_set_server utf8mb4
character_set_system utf8
collation_connection utf8mb4_unicode_ci
collation_database utf8mb4_unicode_ci
collation_server utf8mb4_unicode_ci

collation_connection 、collation_database 、collation_server是什么没关系。
但必须保证这几个变量必须是utf8mb4。
系统变量 (描述)
character_set_client (客户端来源数据使用的字符集)
character_set_connection (连接层字符集)
character_set_database (当前选中数据库的默认字符集)
character_set_results (查询结果字符集)
character_set_server (默认的内部操作字符集)

—————————————————————
到这里为止,上面都是服务器环境方面配置调整
—————————————————————

4.将数据库、表、列三个同时也转换成utf8mb4
更改数据库编码:ALTER DATAbase alfredsw CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
更改表编码:ALTER TABLE TABLE_NAME CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
更改列编码:在需要存储的字段进行更改
[注意:数据库和表编码可以不更改,不影响使用]

5.服务器连接排序规则:utf8mb4_general_ci

6.最关键的,thinkphp的配置要修改

'DB_CHARSET' => 'utf8mb4', // 数据库编码默认采用utf8

data.update.lastsys.time.agopunc.commaarticle.create.bypunc.commaarticle.file.inpunc.colonThinkPHPpunc.caesuraMySQL
article.category