Web开发 | ThinkPHP 3.2.3 - 05.命名空间与多语言

1.前台注册完善

  数据库中不能存储数组的信息,所以在上篇文章末尾的user_hobby是无法存入数据库中的。
  可以使用implode()方法把数组元素用逗号合并起来,变成字符串。
程序代码如下:

    function register(){
        $user = new \Model\UserModel();

        //判断表单是否提交
        if (!empty($_POST)) {

            //只有全部验证通过才会为真
            if (!$user -> create()) {
                //因为在这里还需要对user_hobby数组进行验证,并且我们的验证是针对数组的
                //所以不能在这里对该数组的元素进行合并
                //验证失败,输出错误信息
                //getError()方法返回验证失败的信息
                //show_bug($user->getError());
            } else {
                //user_hobby数组合并成字符串
                //使用AR方式处理user_hobby字段信息
                //create()方法收集的数据也是把数据变为模型对象的属性
                //在这里收集单条数据并且把数据变为模型对象的属性
                $user -> user_hobby = implode(',', $_POST['user_hobby']);
                $rst = $user -> add();
                if ($rst) {
                    $this -> success("注册成功",U('Index/index'));
                } else {
                    $this -> error("注册失败",U('Index/index'));
                }
            }       

        } else {
            $this -> display();
        }   
    }

  由于我们使用的Smarty引擎,此时的success("注册成功",U('Index/index'));将调用失败。
  我们只需要在其父类Controller(ThinkPHP/Library/Think/Controller.class.php)进行修改即可。
  ThinkPHP/Library/Think/Controller.class.php
程序代码如下:

    /**
     * 操作成功跳转的快捷方法
     * @access protected
     * @param string $message 提示信息
     * @param string $jumpUrl 页面跳转地址
     * @param mixed $ajax 是否为Ajax方式 当数字时指定跳转时间
     * @return void
     */
    protected function success($message='',$jumpUrl='',$ajax=false) {
        $this->dispatchJump($message,1,$jumpUrl,$ajax);
    }

  从上面代码可以知道,这里展现了一个模板(dispatch_jump.tpl)
  ThinkPHP/Tpl/dispatch_jump.tpl
程序代码如下:

<?php
    if(C('LAYOUT_ON')) {
        echo '{__NOLAYOUT__}';
    }
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>跳转提示</title>
<style type="text/css">
*{ padding: 0; margin: 0; }
body{ background: #fff; font-family: '微软雅黑'; color: #333; font-size: 16px; }
.system-message{ padding: 24px 48px; }
.system-message h1{ font-size: 100px; font-weight: normal; line-height: 120px; margin-bottom: 12px; }
.system-message .jump{ padding-top: 10px}
.system-message .jump a{ color: #333;}
.system-message .success,.system-message .error{ line-height: 1.8em; font-size: 36px }
.system-message .detail{ font-size: 12px; line-height: 20px; margin-top: 12px; display:none}
</style>
</head>
<body>
<div class="system-message">
<?php if(isset($message)) {?>
<h1>:)</h1>
<p class="success"><?php echo($message); ?></p>
<?php }else{?>
<h1>:(</h1>
<p class="error"><?php echo($error); ?></p>
<?php }?>
<p class="detail"></p>
<p class="jump">
页面自动 <a id="href" href="<?php echo($jumpUrl); ?>">跳转</a> 等待时间: <b id="wait"><?php echo($waitSecond); ?></b>
</p>
</div>
<script type="text/javascript">
(function(){
var wait = document.getElementById('wait'),href = document.getElementById('href').href;
var interval = setInterval(function(){
    var time = --wait.innerHTML;
    if(time <= 0) {
        location.href = href;
        clearInterval(interval);
    };
}, 1000);
})();
</script>
</body>
</html>

参照此模板进行修改
正确页面提醒

  ThinkPHP/Library/Think/Controller.class.php
程序代码如下:

    protected function success($message='',$jumpUrl='',$ajax=false) {
        $waitSecond = 3;
        $info =<<<EOT

            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <html xmlns="http://www.w3.org/1999/xhtml">
            <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <title>跳转提示</title>
            <style type="text/css">
            *{ padding: 0; margin: 0; }
            body{ background: #fff; font-family: '微软雅黑'; color: #333; font-size: 16px; }
            .system-message{ padding: 24px 48px; }
            .system-message h1{ font-size: 100px; font-weight: normal; line-height: 120px; margin-bottom: 12px; }
            .system-message .jump{ padding-top: 10px}
            .system-message .jump a{ color: #333;}
            .system-message .success,.system-message .error{ line-height: 1.8em; font-size: 36px }
            .system-message .detail{ font-size: 12px; line-height: 20px; margin-top: 12px; display:none}
            </style>
            </head>
            <body>
            <div class="system-message">  
            <present name="message"> 
            <h1>:)</h1>
            <p class="success">$message</p>
            <p class="detail" ></p>
            <p class="jump">
            页面自动 <a id="href" href="$jumpUrl">跳转</a> 等待时间: <b id="wait">$waitSecond</b>
            </p>
            </div>
            <script type="text/javascript">
            (function(){
            var wait = document.getElementById('wait'),href = document.getElementById('href').href;
            var interval = setInterval(function(){
                var time = --wait.innerHTML;
                if(time <= 0) {
                    location.href = href;
                    clearInterval(interval);
                };
            }, 1000);
            })();
            </script>
            </body>
            </html>
EOT;
        echo $info;
        exit;

        //$this->dispatchJump($message,1,$jumpUrl,$ajax);
    }

错误页面提醒

  ThinkPHP/Library/Think/Controller.class.php
程序代码如下:

   protected function error($message='',$jumpUrl='',$ajax=false) {
        $waitSecond = 3;
        $info =<<<EOT

            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <html xmlns="http://www.w3.org/1999/xhtml">
            <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <title>跳转提示</title>
            <style type="text/css">
            *{ padding: 0; margin: 0; }
            body{ background: #fff; font-family: '微软雅黑'; color: #333; font-size: 16px; }
            .system-message{ padding: 24px 48px; }
            .system-message h1{ font-size: 100px; font-weight: normal; line-height: 120px; margin-bottom: 12px; }
            .system-message .jump{ padding-top: 10px}
            .system-message .jump a{ color: #333;}
            .system-message .success,.system-message .error{ line-height: 1.8em; font-size: 36px }
            .system-message .detail{ font-size: 12px; line-height: 20px; margin-top: 12px; display:none}
            </style>
            </head>
            <body>
            <div class="system-message">  
            <present name="message"> 
            <h1>):</h1>
            <p class="error">$message</p>
            <p class="detail" ></p>
            <p class="jump">
            页面自动 <a id="href" href="$jumpUrl">跳转</a> 等待时间: <b id="wait">$waitSecond</b>
            </p>
            </div>
            <script type="text/javascript">
            (function(){
            var wait = document.getElementById('wait'),href = document.getElementById('href').href;
            var interval = setInterval(function(){
                var time = --wait.innerHTML;
                if(time <= 0) {
                    location.href = href;
                    clearInterval(interval);
                };
            }, 1000);
            })();
            </script>
            </body>
            </html>
EOT;
        echo $info;
        exit;

        //$this->dispatchJump($message,0,$jumpUrl,$ajax);
    }

  注意:此时的修改我们已经破坏了原则:不应该在框架核心代码直接修改,而是要覆盖重写。后续我们再将次进行完善。


2.简单命名空间使用

  在php文件中,同一个应用请求中如果存在两个方法(类名)名字字样(例如都是getName()),由于php本身语法规则限制,系统是会报错的。

  1.php
程序代码如下:

<?php

function getName(){
    return "123456";
}

function getName(){
    return "654321";
}

运行结果
运行结果

解决方法

  1、把他们名字改成不一样的。例如:agetName()、bgetName()
  2、通过命名空间解决
    例如:YII框架为了避免名字重复引起问题,类前面都有C字样

简单应用

  1、命名空间是虚拟的定义空间,不是真实存在的目录。
  2、命名空间的分隔符都是反斜杠 \
  3、非限定名称:getName()—— 获得与其最近的命名空间的getName()。
  4、限定名称:AAA\getName()——相对方式:通过最近的命名空间定位AAA\getName()。
  5、完全限定名称:\AAA\getName()——直接在指定的命名空间获得具体元素。
  6、命名空间针对:函数、类名、常量三者起作用,在命名空间中把这是那种统称为元素。

  test.php
程序代码如下:

<?php

//声明命名空间
namespace AAA;
function getName(){
    return "123456";
}

//非限定名称:getName() 获得与其最近的命名空间的getName()

//可以使用到AAA命名空间的getName()
echo getName()."<br/>";   //输出123456

//声明命名空间
namespace BBB;
function getName(){
    return "654321";
}

//非限定名称:getName() 获得与其最近的命名空间的getName()
//可以使用到BBB命名空间的getName()
echo getName()."<br/>";   //输出654321

//根据命名空间决定使用哪个getName()

//限定名称:AAA\getName() 会认为在当前命名命名空间中获得BBB\aaa\getName()
//相对定位
//echo AAA\getName();

//完全限定名称
//绝对定位
echo \AAA\getName();

3.子空间和引入

子空间

  test.php
程序代码如下:

<?php

//声明命名空间
namespace AAA\aa;
function getName(){
    return "aa";
}

namespace BBB\bb;
function getName(){
    return "bb";
}

namespace AAA\cc;
function getName(){
    return "cc";
}

namespace AAA\dd;
function getName(){
    return "dd";
}

//获得最下边的getName()使用非限定名称,使用上边的getName()需要使用完全限定名称
//echo getName(); //输出dd
//echo cc\getName(); //输出错误 -> AAA\dd\cc\getName() 
//echo \AAA\cc\getName(); //输出cc -> \AAA\cc\getName()
echo \BBB\bb\getName(); //输出bb
别名和引入

  1、引入:use
  2、使用一个元素,使用非限定名称,在当前最接近的空间中获得元素
  3、如果当前空间中没有指定元素,也可以在导入的空间中寻找

  test.php
程序代码如下:

<?php

//声明命名空间
namespace AAA;
function getName(){
    return "aaa";
}

namespace BBB;
function getName(){
    return "bbb";
}
class Person{
    static $name = "BBB";
}

namespace CCC;
function getName(){
    return "ccc";
}

//第一种使用
//use BBB\Person;
//Person在本身默认空间没有找到就会去引入的空间中寻找
//echo Person::$name; //输出BBB

//第二种使用
use BBB;
echo BBB\Person::$name; //输出BBB

  test.php
程序代码如下:

<?php

//子空间-引入命名空间应用
namespace AAA\aa;
class Person{
    static $name = "aa";
}

namespace BBB\bb;
function getName(){
    return "bb";
}

//echo \AAA\aa\Person::$name;  //输出aa

//引入空间(空间和元素都引入)
//use AAA\aa\Person;
//echo Person::$name; //输出aa

//引入空间
use AAA\aa;
//使用限定名称就可以定位已经引入的空间元素
echo aa\Person::$name; //输出aa

  4、别名应用

  如果在引入空阿金的时候也把元素给引入了,在当前的空间中也有同名的元素,那么这个外来的元素和内部元素会有冲突,这时可以通过别名定义来重新给外来的元素起名字并使用。

  test.php
程序代码如下:

<?php

//子空间-引入命名空间应用
namespace AAA\aa;
class Person{
    static $name = "aa";
}

namespace BBB\bb;
function getName(){
    return "bb";
}
class Person{
    static $name = "bb";
}

//引入空间和元素
//use AAA\aa\Person;
//echo Person::$name; //输出错误 
//Cannot use AAA\aa\Person as Person because the name is already in use

//引入空间和元素(别名使用)
//use AAA\aa\Person as pon;
//echo pon::$name; //输出aa

use AAA\aa;
echo Person::$name; //输出bb
echo aa\Person::$name; //输出aa

4.公共空间使用

  没有使用namespace定义空间,当前空间就是一个公共空间

有namespace的文件引入了一个没有namespace的文件程序

  1、默认使用当前空间的元素
  2、统一使用斜杠访问公共空间元素

  common.php
程序代码如下:

<?php

//公共空间
function getName(){
    return "commom";
}

  test.php
程序代码如下:

<?php
//命名空间的第一个namespace声明之前不能有任何代码
namespace AAA;
include ("./common.php");

function getName(){
    return "AAA";
}

//echo getName();  //输出AAA

//访问公共空间的元素
echo \getName();  //输出common
没有namespace的文件引入了一个有namespace的文件程序

  1、默认调用当前公共空间的元素(非限定名称)
  2、使用有公共空间的元素(限定名称、完全限定名称)

  test.php
程序代码如下:

<?php
namespace AAA;
function getName(){
    return "AAA";
}
class Person{
    static $name = "AAAAAA";
}

  common.php
程序代码如下:

<?php

//公共空间
//当前文件没有空间,引入文件有空间
//默认空间就是当前空间
function getName(){
    return "commom";
}
class Person{
    static $name = "commomcommom";
}

include "./test.php";

//echo getName(); //输出common
//echo \getName(); //输出common

//echo AAA\getName(); //输出AAA
//echo \AAA\getName(); //输出AAA

//use AAA\getName;
//echo Person::$name; //输出commomcommom

//use AAA\Person;
//echo Person::$name; //输出错误
//Cannot use AAA\Person as Person because the name is already in use

use AAA\Person as pon;
echo pon::$name ; //输出AAAAAA
引用常量const

  const.php
程序代码如下:

<?php

namespace AAA;
const XYZ = "xyz";

  test.php
程序代码如下:

<?php

include "./const.php";

//引用常量
echo AAA\XYZ;

  同一个页面中有许多空间,在页面最下面使用上面的空间的元素,名称需要使用完全限定名称。还可以把上面空间的元素给use引入过来,也可以通过非限定名称或限定名称使用。

注意

  1、针对类名、函数名、常量const起作用
      define()定义的常量不受命名空间的限制
  2、声明namespace的当前脚本的第一个命名空间前面不能有任何代码(header头代码也要写在下面)
  3、命名空间是虚构抽象的空间,不是真实存在的目录
  4、当前文件可以include具有命名空间的文件,默认空间是当前文件的公共空间
  5、元素调用:非限定名称、限定名称、完全限定名称


5.多语言切换使用

多语言设置就是通过get参数告诉当前的请求使用何种语言。

  第一次使用get变量传递语言,之后语言还会保存在cookie中,供下次使用。
  如果get没有传递语言,浏览器会根据当前地区选中对应的语言,我们程序也可以读取浏览器的对应的语言变量选择对应的语言。

设置步骤

  1、多语言通过行为Behavior支持
    ThinkPHP/Library/Behavior/CheckLangBehavior.class.php
  程序代码如下:

    private function checkLanguage() {
        // 不开启语言包功能,仅仅加载框架语言文件直接返回
        if (!C('LANG_SWITCH_ON',null,false)){
            return;
        }
        $langSet = C('DEFAULT_LANG');
        $varLang =  C('VAR_LANGUAGE',null,'l');
        $langList = C('LANG_LIST',null,'zh-cn');
        // 启用了语言包功能
        // 根据是否启用自动侦测设置获取语言选择
        if (C('LANG_AUTO_DETECT',null,true)){
            if(isset($_GET[$varLang])){
                $langSet = $_GET[$varLang];// url中设置了语言变量
                cookie('think_language',$langSet,3600);
            }elseif(cookie('think_language')){// 获取上次用户的选择
                $langSet = cookie('think_language');
            }elseif(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){// 自动侦测浏览器语言
                preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
                $langSet = $matches[1];
                cookie('think_language',$langSet,3600);
            }
            if(false === stripos($langList,$langSet)) { // 非法语言参数
                $langSet = C('DEFAULT_LANG');
            }
        }
        // 定义当前语言
        define('LANG_SET',strtolower($langSet));

        // 读取框架语言包
        $file   =   THINK_PATH.'Lang/'.LANG_SET.'.php';
        if(LANG_SET != C('DEFAULT_LANG') && is_file($file))
            L(include $file);

        // 读取应用公共语言包
        $file   =  LANG_PATH.LANG_SET.'.php';
        if(is_file($file))
            L(include $file);

        // 读取模块语言包
        $file   =   MODULE_PATH.'Lang/'.LANG_SET.'.php';
        if(is_file($file))
            L(include $file);

        // 读取当前控制器语言包
        $file   =   MODULE_PATH.'Lang/'.LANG_SET.'/'.strtolower(CONTROLLER_NAME).'.php';
        if (is_file($file))
            L(include $file);
    }

  2、从上面代码可知,语言包一共有4种,后定义的要覆盖先定义的(类似配置文件config.php覆盖convention.php)

  3、在config.php中开启多语言支持
    shop/Common/Conf/config.php
  程序代码如下:

<?php
return array(
    ...

    //多语言支持
    'LANG_SWITCH_ON'        => true,   // 开启语言包功能,默认关闭
    'LANG_AUTO_DETECT'      => true, // 自动侦测语言 开启多语言功能后有效
    //'LANG_LIST'             => 'zh-cn', // 允许切换的语言列表 用逗号分隔
    'LANG_LIST'             => 'zh-cn,zh-tw,en-us',
    'VAR_LANGUAGE'          => 'l', // 默认语言切换变量
);

  4、确保行为Behavior代码执行。
    手动启动该CheekLanguageBehavior行为。
    新建shop/Common/Cong/tags.php文件,参考ThinkPHP/Mode/common.php文件中行为扩展定义的 'app_begin' => array( 'Behavior\ReadHtmlCacheBehavior', // 读取静态缓存),

    shop/Common/Cong/tags.php
  程序代码如下:

<?php

return array(
    //'配置项'=>'配置值'
    //覆盖ThinkPHP/Mode/common.php的配置
    'app_begin'     =>  array(
            'Behavior\ReadHtmlCacheBehavior', // 读取静态缓存
            'Behavior\CheckLangBehavior',//启动多语言支持
        ),
);

  5、语言包的4个等级并定义语言包
    ThinkPHP/Library/Behavior/CheckLangBehavior.class.php
  程序代码如下:

设置debug设置debug
运行效果
运行效果

读取框架语言包
string(53) "C:\Soft\phpStudy\WWW\ThinkPHP\ThinkPHP/Lang/zh-cn.php"

读取公共语言包
string(56) "C:/Soft/phpStudy/WWW/ThinkPHP/shop/Common/Lang/zh-cn.php"

读取指定模块语言包
string(54) "C:/Soft/phpStudy/WWW/ThinkPHP/shop/Home/Lang/zh-cn.php"

读取指定模块具体控制器对应的语言包
string(59) "C:/Soft/phpStudy/WWW/ThinkPHP/shop/Home/Lang/zh-cn/user.php"

语言包从上往下划分越来越细

定义语言包

    新建shop/Common/Lang/zh-tw.php
  程序代码如下:

<?php

return array(   
    'username' => '用戶名',
    'password' => '密碼',
);

  6、获得语言变量信息
    a)L()快捷函数,可以获得全部或指定语言变量
    b)使用语言,获得全部语言,assign()传递语言变量到模板进行具体使用
    c){$Think.language.名称}

    shop/Home/Controller/UserController.class.php
  程序代码如下:

    function login(){

        //获得语言变量信息
        //L()获得全部语言
        //L('USERNAME')获得指定语言
        $this -> assign('lang',L());

        $this -> display();
    }

  shop/Home/View/User/login.html
  使用{$lang.USERNAME}进行替换

程序代码如下:

...
<!-- <label for="username" class="col-sm-offset-1 col-sm-2 control-label">用户名:</label> -->
                        <label for="username" class="col-sm-offset-1 col-sm-2 control-label">{$lang.USERNAME}</label>
...
<!-- <label for="password" class="col-sm-offset-1 col-sm-2 control-label">密 &nbsp; &nbsp;码:</label>-->
                        <label for="password" class="col-sm-offset-1 col-sm-2 control-label">{$lang.PASSWORD}</label>

    运行http://localhost/ThinkPHP/shop/index.php/Home/User/login/l/zh-tw

运行效果
运行效果

  7、每个语言自己对应具体的一个文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值