首页 > 编程技术 > php

网易式评论箱的实现原理分析

发布时间:2016-11-25 14:55

网易式评论箱的实现是许多站长非常想做到的一个东西了,今天我们来看看网易式评论箱的实现原理吧,具体的如下所示。
预览
QQ20160416-0.png
实现
基础
  1. 表的设计
  2. 前端的实现

由于每个回复的展示都需要完整的引用路径,我们需要一个字段来记录本条回复所回复的回复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渲染数据

Untitled.png

用伪代码可以表示为如下结构

<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

页面跳转可以使用header函数来实现了当然如果多种办法我们看看还会有哪几种呢,下面我们一起来看小编整理的PHP页面跳转的三种方法例子。

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页面跳转实现方法。

下面我们来看一篇关于 PHP实现抓取HTTPS内容的方法和错误处理的教程希望这篇教程能够帮助到各位朋友。

最近在研究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;
}

对象转array的意思是把一些对象转换成数组了这个在json处理时会经常用到了,下面我们来看一篇关于PHP中把stdClass Object转array的几个方法,希望文章能够帮助到各位。

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的,否则得先转码下。

标签:[!--infotagslink--]

您可能感兴趣的文章: