![QQ20160416-0.png](/upload/news/201611/20160616151658404.png)
- 表的设计
- 前端的实现
由于每个回复的展示都需要完整的引用路径,我们需要一个字段来记录本条回复所回复的回复quote_id
,在一个列表中如果每次都递归获取引用的评论,性能上会有很大的瓶颈,所以我们冗余一个字段,记录本条回复的引用路径 quote_path
CREATE TABLE `pre_comments` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`article_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`quote_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`quote_path` varchar(255) NOT NULL DEFAULT '',
`user_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`username` char(15) NOT NULL DEFAULT '',
`content` varchar(1024) NOT NULL,
`up` bigint(20) NOT NULL DEFAULT '0',
`down` bigint(20) NOT NULL DEFAULT '0',
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`deleted_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_article_id` (`article_id`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
数据展示流程:
获取最新的10条评论
获取与最新的10条评论相关被引用的评论
组装数据,返回json
Reactjs渲染数据
用伪代码可以表示为如下结构
<CommentBox>
<CommentList>
<CommentItem>
<CommentQuote>
<CommentQuote>
<CommentToolBar>
<CommentForm></CommentForm>
</CommentToolBar>
</CommentQuote>
<CommentToolBar>
<CommentForm></CommentForm>
</CommentToolBar>
</CommentQuote>
<CommentToolBar>
<CommentForm></CommentForm>
</CommentToolBar>
</CommentItem>
</CommentList>
<CommentForm></CommentForm>
</CommentBox>
优化
分库分表
通用计数组件
缓存
静态化
通过查询场景来决定分库分表的策略
根据articleId查询最新的评论
根据articleId 和 commentId更新计数
根据articleId 和 quoteId写入新的评论
展示某个用户(userId)所有的评论
其中有两个分表的路由key articleId 和 userId
Web系统中,从一个网页跳转到另一个网页,是项目中最常用的技术之一。
页面跳转可能是由于用户单击链接、按钮等引发的,也可能是系统自动产生的。
此处介绍PHP中常用的实现页面自动跳转的方法。
PHP页面跳转一、header()函数
header()函数是PHP中进行页面跳转的一种十分简单的方法。
header()函数的主要功能是将HTTP协议标头(header)输出到浏览器。
header()函数的定义如下:
void header (string string [,bool replace [,int http_response_code]])
可选参数replace指明是替换前一条类似标头还是添加一条相同类型的标头,默认为替换。
第二个可选参数http_response_code强制将HTTP相应代码设为指定值。
header函数中Location类型的标头是一种特殊的header调用,常用来实现页面跳转。
注意:
1.location和“:”号间不能有空格,否则不会跳转。
2.在用header前不能有任何的输出。
3.header后的PHP代码还会被执行。
< ?php
//重定向浏览器
header("Location: http://www.111cn.net/");
//确保重定向后,后续代码不会被执行
exit;
?>
PHP页面跳转二、Meta标签
Meta标签是HTML中负责提供文档元信息的标签,在PHP程序中使用该标签,也可以实现页面跳转。
若定义http-equiv为refresh,则打开该页面时将根据content规定的值在一定时间内跳转到相应页面。
若设置content=”秒数;url=网址”,则定义了经过多长时间后页面跳转到指定的网址。
< meta http-equiv="refresh"
content="1;url=http://www.111cn.net/">
< ?php
$url = "http://www.111cn.net/"; ?>
< html>
< head>
< meta http-equiv="refresh" content="1;
url=< ?php echo $url; ?>">
< /head>
< body>
页面只停留一秒……
< /body>
< /html>
PHP页面跳转三、JavaScript
例如,此代码可以放在程序中的任何合法位置。
< ?php
$url = "http://www.111cn.net/";
echo "< script language='javascript'
type='text/javascript'>";
echo "window.location.href='$url'";
echo "< /script>";
?>
以上就是我们向大家介绍的三种PHP页面跳转实现方法。
最近在研究Hacker News API时遇到一个HTTPS问题。因为所有的Hacker News API都是通过加密的HTTPS协议访问的,跟普通的HTTP协议不同,当使用PHP里的函数 file_get_contents() 来获取API里提供的数据时,出现错误,使用的代码是这样的:
<?php
$data = file_get_contents("https://www.liqingbo.cn/son?print=pretty");
......
当运行上面的代码是遇到下面的错误提示:
PHP Warning: file_get_contents(): Unable to find the wrapper "https" - did you forget to enable it when you configured PHP?
为什么会出现这样的错误?
在网上经过一番搜索,发现遇到这样错误的人还不少,问题很直接,是因为在PHP的配置文件里没有开启一个参数,在我本机上是 /apache/bin/php.ini 里的 ;extension=php_openssl.dll 这一项,需要将前面的分号去掉。你可以用下面的脚本来检查你的PHP环境的配置:
$w = stream_get_wrappers();
echo 'openssl: ', extension_loaded ('openssl') ? 'yes':'no', "\n";
echo 'http wrapper: ', in_array('http', $w) ? 'yes':'no', "\n";
echo 'https wrapper: ', in_array('https', $w) ? 'yes':'no', "\n";
echo 'wrappers: ', var_dump($w);
运行上面的这个脚本片段,在我的机器上得到的结果是:
openssl: no
http wrapper: yes
https wrapper: no
wrappers: array(10) {
[0]=>
string(3) "php"
[1]=>
string(4) "file"
[2]=>
string(4) "glob"
[3]=>
string(4) "data"
[4]=>
string(4) "http"
[5]=>
string(3) "ftp"
[6]=>
string(3) "zip"
[7]=>
string(13) "compress.zlib"
[8]=>
string(14) "compress.bzip2"
[9]=>
string(4) "phar"
}
替代方案
发现错误,改正错误,这很简单,困难的是,发现错误后无法改正错误。我原本是想将这个脚本方法远程主机上,但我无法修改远程主机的PHP配置,结果是,我无法使用这一方案,但我们不能在一棵树上吊死,这条路走不通,看看有没有其它路。
另外一个我经常用的PHP里抓取内容的函数是 curl ,它比 file_get_contents() 更强大,提供了很多的可选参数。对于访问 HTTPS 内容的问题,我们需要使用的 CURL 配置参数是:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
你可以从语义上看出,它是忽略/跳过了SSL安全验证。也许这不是一个很好的做法,但对于普通的场景中,这几经足够了。
下面是利用 Curl 封装的一个能访问HTTPS内容的函数:
function getHTTPS($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
stdClass的分析
stdclass在php中是预定义的几个类之一,是zent保留的一个类。实际上它是PHP提供的一个基类,就是一个空白的类,里面什么都没有,我们可以实例化它,然后定义一系列的变量,通过它来进行变量的传递(很多php程序员用它来传递一系列变量的值,而同时又懒得去创建一个自己的类)。但是,由于实例化后不能添加方法,只能传递属性。因为,一旦类被实列化以后,就不能在添加方法了。
stdclass可以作为基类使用,其最大特点是,(其派生类)可以自动添加成员变量,而无须在定义时说明。
一切php变量都是stdClass的实例。
使用方法:
1、使用stdclass:
$andy = array();
$andy = (object)$andy;
$andy->a = 1;
$andy->b = 2;
$andy->c = 3;
这样数量a、b、c就填进了stdclass里面。这样要省事,因为新建空对像却要$andy = new Andy; 而且还得先有个class Andy{}。又如:
<?php
$a = new stdClass();
$a->id = '11 ';
$a->username = 'me';
print_r($a);
?>
将会输出:stdClass Object ( [id] => 11 [username] => me ) 。
很多时候用这种方法取代数组的使用,只不过是换一种语法形式。
读取:
stdClass Object
(
[getWeatherbyCityNameResult] => stdClass Object
(
[string] => Array
(
[0] => 四川
[1] => 成都
[2] => 56294
[3] => 56294.jpg
[4] => 2009-5-17 13:52:08
[5] => 26℃/19℃
[6] => 5月17日 阴转阵雨
)
)
)
其实和array差不多,只是访问方式改变一点就行,我们一般习惯使用array['key']这种方式来访问数组。
对于这种stdClass来说,如上例,$weather->getWeatherbyCityNameResult->string[0]可以这样来访问属性,这个将得到结果“四川”。
3、实例化,new。
对比这两个代码:
<?php
$a = array(1=>2,2=>3);
$a = (object)$a;
$a->id = '11 ';
$a->username = 'me';
print_r($a);
?>
将输出:stdClass Object ( [1] => 2 [2] => 3 [id] => 11 [username] => me ) 。
<?php
$a = array(1=>2,2=>3);
$a = (object)$a;
$a = new stdClass();
$a->id = '11 ';
$a->username = 'me';
print_r($a);
?>
将输出:stdClass Object ( [id] => 11 [username] => me ) 。
原来用new实例化后,前面的数组清空,只留下后面添加进来的,如果不实例化,stdClass将保留所有元素。
需要注意的是,在函数里面使用global、static时遇new stdclass引用的情况,这时&new stdclass将会失效,应避免使用引用,直接用new stdclass。
我们在经常使用API接口获取数据返回json数值的时候,往往单纯通过json_decode方法解析获得得数值一般并非数组,而是带有stdClass Objec的对象字符串,这时如果我们想获取相应的PHP数组时,需通过以下几种方法来获取。
方法一:
//PHP stdClass Object转array
function object_array($array) {
if(is_object($array)) {
$array = (array)$array;
} if(is_array($array)) {
foreach($array as $key=>$value) {
$array[$key] = object_array($value);
}
}
return $array;
}
方法二:
$array = json_decode(json_encode(simplexml_load_string($xmlString)),TRUE);
方法三:
function object2array_pre(&$object) {
if (is_object($object)) {
$arr = (array)($object);
} else {
$arr = &$object;
}
if (is_array($arr)) {
foreach($arr as $varName => $varValue){
$arr[$varName] = $this->object2array($varValue);
}
}
return $arr;
}
如果是10W的数据量的话,执行要进1s,结构再复杂些,可以达到3s, 性能太差了
可以用以下替换:
function object2array(&$object) {
$object = json_decode( json_encode( $object),true);
return $object;
}
但是对json的特性,只能是针对utf8的,否则得先转码下。