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";
}
![运行结果](https://i-blog.csdnimg.cn/blog_migrate/f73d281e0bbaeecc4ce1c1e6227e2848.jpeg)
运行结果
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变量传递语言,之后语言还会保存在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](https://i-blog.csdnimg.cn/blog_migrate/634ea9d1880b566c2b3e554ef1f6609d.jpeg)
![运行效果](https://i-blog.csdnimg.cn/blog_migrate/abe44b1039908b260cf4c3c3bc83d71a.jpeg)
运行效果
读取框架语言包
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">密 码:</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
![运行效果](https://i-blog.csdnimg.cn/blog_migrate/e31a708659760b5bf7378df5e97a0de2.jpeg)
运行效果
7、每个语言自己对应具体的一个文件