php中php://input的用法详细

 更新时间:2016年11月25日 15:48  点击:2655
在使用xml-rpc的时候,server端获取client数据,主要是通过php输入流input,而不是$_POST数组。所以,这里主要探讨php输入流php://input。


下面的例子摘取的是wordpress中的一段代码,里面有用到http://input,有需要的可以进一步研究。

 代码如下 复制代码

if (!isset( $HTTP_RAW_POST_DATA ) ) {  
    $HTTP_RAW_POST_DATA = file_get_contents('php://input');  
}  
 
// fix for mozBlog and other cases where xml isn't on the very first line  
if ( isset($HTTP_RAW_POST_DATA) )  
    $HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA); 


对php://input介绍,PHP官方手册文档有一段话对它进行了很明确地概述。

 代码如下 复制代码

“php://input allows you to read raw POST data. It is a less memory intensive alternative to $HTTP_RAW_POST_DATA and does not need any special php.ini directives. php://input is not available with enctype=”multipart/form-data”.

翻译成中文就是:

“php://input可以读取没有处理过的POST数据。相较于$HTTP_RAW_POST_DATA而言,它给内存带来的压力较小,并且不需要特殊的php.ini设置。php://input不能用于enctype=multipart/form-data”


读取POST数据PHPer们一定很熟悉$_POST这个内置变量。$_POST与php://input存在哪些关联与区别呢?另外,客户端向服务端交互数据,最常用的方法除了POST之外,还有GET。既然php://input作为PHP输入流,它能读取GET数据吗?这二个问题正是我们这节需要探讨的主要内容。
经验告诉我们,从测试与观察中总结,会是一个很凑效的方法。这里,我写了几个脚本来帮助我们测试。

@file 192.168.0.6:/phpinput_server.php 打印出接收到的数据
@file 192.168.0.8:/phpinput_post.php 模拟以POST方法提交表单数据
@file 192.168.0.8:/phpinput_xmlrpc.php 模拟以POST方法发出xmlrpc请求.
@file 192.168.0.8:/phpinput_get.php 模拟以GET方法提交表单表数phpinput_server.php与phpinput_post.php

 代码如下 复制代码

<?php
//@file phpinput_server.php
$raw_post_data = file_get_contents('php://input', 'r');
echo "-------$_POST------------------n";
echo var_dump($_POST) . "n";
echo "-------php://input-------------n";
echo $raw_post_data . "n";
?>
?
<?php
//@file phpinput_post.php
$http_entity_body = 'n=' . urldecode('perfgeeks') . '&amp;p=' . urldecode('7788');
$http_entity_type = 'application/x-www-form-urlencoded';
$http_entity_length = strlen($http_entity_body);
$host = '192.168.0.6';
$port = 80;
$path = '/phpinput_server.php';
$fp = fsockopen($host, $port, $error_no, $error_desc, 30);
if ($fp) {
  fputs($fp, "POST {$path} HTTP/1.1rn");
  fputs($fp, "Host: {$host}rn");
  fputs($fp, "Content-Type: {$http_entity_type}rn");
  fputs($fp, "Content-Length: {$http_entity_length}rn");
  fputs($fp, "Connection: closernrn");
  fputs($fp, $http_entity_body . "rnrn");
?
  while (!feof($fp)) {
    $d .= fgets($fp, 4096);
  }
  fclose($fp);
  echo $d;
}
?>

我们可以通过使用工具ngrep抓取http请求包(因为我们需要探知的是php://input,所以我们这里只抓取http Request数据包)。我们来执行测试脚本phpinput_post.php

 代码如下 复制代码

@php /phpinput_post.phpHTTP/1.1 200 OK
Date: Thu, 08 Apr 2010 03:23:36 GMT
Server: Apache/2.2.3 (CentOS)
X-Powered-By: PHP/5.1.6
Content-Length: 160
Connection: close
Content-Type: text/html; charset=UTF-8
-------$_POST------------------
array(2) {
  ["n"]=> string(9) "perfgeeks"
  ["p"]=> string(4) "7788"
}
-------php://input-------------
n=perfgeeks&p=7788通过ngrep抓到的http请求包如下:

T 192.168.0.8:57846 -> 192.168.0.6:80 [AP]
  POST /phpinput_server.php HTTP/1.1..
  Host: 192.168.0.6..Content-Type: application/x-www-form-urlencoded..Co
  ntent-Length: 18..Connection: close....n=perfgeeks&p=7788....

仔细观察,我们不难发现
1,$_POST数据,php://input 数据与httpd entity body数据是“一致”的
2,http请求中的Content-Type是application/x-www-form-urlencoded ,它表示http请求body中的数据是使用http的post方法提交的表单数据,并且进行了urlencode()处理。
(注:注意加粗部分内容,下文不再提示). http://www.k686.com

我们再来看看脚本phpinput_xmlrpc.php的原文件内容,它模拟了一个POST方法提交的xml-rpc请求。

 代码如下 复制代码

<?php
//@file phpinput_xmlrpc.php
$http_entity_body = "nn   jt_userinfon";
$http_entity_type = 'text/html';
$http_entity_length = strlen($http_entity_body);
$host = '192.168.0.6';
$port = 80;
$path = '/phpinput_server.php';
$fp = fsockopen($host, $port, $error_no, $error_desc, 30);
if ($fp) {
  fputs($fp, "POST {$path} HTTP/1.1rn");
  fputs($fp, "Host: {$host}rn");
  fputs($fp, "Content-Type: {$http_entity_type}rn");
  fputs($fp, "Content-Length: {$http_entity_length}rn");
  fputs($fp, "Connection: closernrn");
  fputs($fp, $http_entity_body . "rnrn");
  while (!feof($fp)) {
    $d .= fgets($fp, 4096);
  }
?
  fclose($fp);
  echo $d;
}
?>

同样地,让我们来执行这个测试脚本

 代码如下 复制代码

@php /phpinput_xmlrcp.phpHTTP/1.1 200 OK
Date: Thu, 08 Apr 2010 03:47:18 GMT
Server: Apache/2.2.3 (CentOS)
X-Powered-By: PHP/5.1.6
Content-Length: 154
Connection: close
Content-Type: text/html; charset=UTF-8

-------$_POST------------------
array(0) {
}

-------php://input-------------
<?xml version="1.0">
<methodcall>
   <name>jt_userinfo</name>
</methodcall>

执行这个脚本的时候,我们通过ngrep抓取的http请求数据包如下

T 192.168.0.8:45570 -> 192.168.0.6:80 [AP]
  POST /phpinput_server.php HTTP/1.1..
  Host: 192.168.0.6..Content-Type: text/html..Content-Length: 75..Connec
  tion: close....<?xml version="1.0">.<methodcall>.   <name>jt_userinfo<
  /name>.</methodcall>....同样,我样也可以很容易地发现:
1,http请求中的Content-Type是text/xml。它表示http请求中的body数据是xml数据格式。
2,服务端$_POST打印出来的是一个空数组,即与http entity body不一致了。这跟上个例子不一样了,这里的Content-Type是text/xml,而不是application/x-www-form-urlencoded
3,而php://input数据还是跟http entity body数据一致。也就是php://input数据和$_POST数据不一致了。

我们再来看看通过GET方法提交表单数据的情况,php://input能不能读取到GET方法的表单数据?在这里,我们稍加改动一下phpinput_server.php文件,将$_POST改成$_GET。

 代码如下 复制代码

<?php
//@file phpinput_server.php
$raw_post_data = file_get_contents('php://input', 'r');
echo "-------$_GET------------------n";
echo var_dump($_GET) . "n";
echo "-------php://input-------------n";
echo $raw_post_data . "n";
?>
?
<?php
//@file phpinput_get.php
$query_path = 'n=' . urldecode('perfgeeks') . '&amp;p=' . urldecode('7788');
$host = '192.168.0.6';
$port = 80;
$path = '/phpinput_server.php';
$d = '';
$fp = fsockopen($host, $port, $error_no, $error_desc, 30);
if ($fp) {
  fputs($fp, "GET {$path}?{$query_path} HTTP/1.1rn");
  fputs($fp, "Host: {$host}rn");
  fputs($fp, "Connection: closernrn");
?
  while (!feof($fp)) {
    $d .= fgets($fp, 4096);
  }
  fclose($fp);
  echo $d;
 }
?>

同样,我们执行下一phpinput_get.php测试脚本,它模拟了一个通常情况下的GET方法提交表单数据。

 代码如下 复制代码

@php /phpinput_get.phpHTTP/1.1 200 OK
Date: Thu, 08 Apr 2010 07:38:15 GMT
Server: Apache/2.2.3 (CentOS)
X-Powered-By: PHP/5.1.6
Content-Length: 141
Connection: close
Content-Type: text/html; charset=UTF-8

-------$_GET------------------
array(2) {
  ["n"]=>
  string(9) "perfgeeks"
  ["p"]=>
  string(4) "7788"
}

-------php://input-------------在这个时候,使用ngrep工具,捕获的相应的http请求数据包如下

T 192.168.0.8:36775 -> 192.168.0.6:80 [AP]
  GET /phpinput_server.php?n=perfgeeks&p=7788 HTTP/1.1..
  Host: 192.168.0.6..Connection: close....

比较POST方法提交的http请求,通常GET方法提交的请求中,entity body为空。同时,不会指定Content-Type和Content-Length。但是,如果强硬数据http entity body,并指明正确地Content-Type和Content-Length,那么php://input还可是读取得到http entity body数据,但不是$_GET数据。


实践中关于php://input用法总结:

1、只有Content-Type为application/x-www-data-urlencoded时,php://input数据才跟$_POST数据相一致。
2、PHP不能识别的Content-Type类型的时候,会将http请求包中相应的数据填入变量$HTTP_RAW_POST_DATA
3、只有Coentent-Type为multipart/form-data的时候,PHP不会将http请求数据包中的相应数据填入php://input,否则其它情况都会。填入的长度,由Coentent-Length指定。
4、Coentent-Type仅在取值为application/x-www-data-urlencoded和multipart/form-data两种情况下,PHP才会将http请求数据包中相应的数据填入全局变量$_POST。
5、php://input数据总是跟$HTTP_RAW_POST_DATA相同,但是php://input比$HTTP_RAW_POST_DATA更凑效,且不需要特殊设置php.ini
6、PHP会将PATH字段的query_path部分,填入全局变量$_GET。php://input读取不到$_GET数据,是因为$_GET数据作为query_path写在http请求头部(header)的PATH字段,而不是写在http请求的body部分。

一个PHP二维数组按照一个字段排序程序实现代码,有需要的朋友可参考参考。

二维数组

 代码如下 复制代码
$arr = array ( 
    array ( 'key' => '69931', 
         'hsex' => '女', 
         'username' => 'jiayang3401', 
         'clicks' => 10, 
         'hyinglou' => '无' ),      
    array ( 'key' => '81', 
         'hsex' => '女', 
        'username' => 'susan', 
         'clicks' => 15, 
     'hyinglou' => '摄影名店' ),      
);   

 


 代码如下 复制代码

foreach($arr as $vo){ 
    $t[] = $vo['clicks']; 

array_multisort($t, $arr);//排序 
var_dump($arr); 

php中关联数据用法与一些关联数组的一些小技巧,包括添加,删除,编辑,遍历,交换键和值,排序,查询等等关联数组的一些实例。

1、添加数组元素
PHP是一种弱类型语言,这意味着你不需要显示声明一个数组及其大小,相反,你可以同时声明并填充数组。

 代码如下 复制代码
$capitals = array( 
  'Alabama' => 'Montgomery', 
  'Alaska'  => 'Juneau', 
  'Arizona' => 'Phoenix' 
);

额外的数组元素可以象下面这样追加:

$capitals['Arkansas'] = 'Little Rock'; 如果你正在处理数字索引数组,你可能想使用显示命名的函数前置和追加元素,如array_push()和array_unshift()函数,但这些函数不能操作关联数组。

 

2、删除数组元素
如果要从数组中删除一个元素,请使用unset()函数,如:

 代码如下 复制代码
unset($capitals['California']);

使用数字索引数组时,删除数组元素的办法更多,更灵活,可以使用array_shift()和array_pop()函数分别从数组的开头和末尾删除一个元素。

 

3、交换键和值
假设你想创建一个名叫$states的新数组,使用州府作为索引,使用州名作为关联值,使用array_flip()函数很容易完成这个任务。

 

 代码如下 复制代码
$capitals = array( 
  'Alabama' => 'Montgomery', 
  'Alaska'  => 'Juneau', 
  'Arizona' => 'Phoenix' 
); 
$states = array_flip($capitals); 
// $states = array( 
//  'Montgomery' => string 'Alabama', 
//  'Juneau'     => string 'Alaska', 
//  'Phoenix'    => string 'Arizona' 
// ); 

 

4、合并数组
假设前面的数组由一个基于Web的“FlashCard”服务使用,你想提供一种方法测试学生对美国各州首府的掌握情况,你可以使用array_merge()函数合并包含州和首府的数组。

 代码如下 复制代码


$stateCapitals = array( 
  'Alabama' => 'Montgomery', 
  'Alaska'  => 'Juneau', 
  'Arizona' => 'Phoenix' 
); 
$countryCapitals = array ( 
  'Australia' => 'Canberra', 
  'Austria'   => 'Vienna', 
  'Algeria'   => 'Algiers' 
); 
$capitals = array_merge($stateCapitals, $countryCapitals); 

5、编辑数组值
假设在数组中的数据包含大小写错误,在插入到数据库之前,你想纠正这些错误,你可以使用array_map()函数给每个数组元素应用一个回调。

 代码如下 复制代码


function capitalize($element) 

  $element = strtolower($element); 
  return ucwords($element); 

$capitals = array( 
  'Alabama' => 'montGoMEry', 
  'Alaska'  => 'Juneau', 
  'Arizona' => 'phoeniX' 
); 
$capitals = array_map("capitalize", $capitals); 

6、按键对数组排序
FlashCard程序常常使用各种排序,如按字母顺序排序,你可以使用ksort()函数按键对关联数组进行排序。

 代码如下 复制代码

$capitals = array( 
  'Arizona' => 'Phoenix', 
  'Alaska'  => 'Juneau', 
  'Alabama' => 'Montgomery' 
); 
ksort($capitals);

因为数组是通过参数传递给ksort()函数的,意味着你不再需要将排序结果分配给另一个变量。

 

7、随机数组排序
在FlashCard程序中还涉及到另一种随机排序技术,这时你要使用shuffle()函数实现数组项目的随机排序。

 代码如下 复制代码

$capitals = array( 
  'Arizona' => 'Phoenix', 
  'Alaska'  => 'Juneau', 
  'Alabama' => 'Montgomery' 
); 
shuffle($capitals);

如果不需要打乱数组顺序,你只是想随机选择一个值,那么使用array_rand()函数即可。

 

8、确定键和值是否存在
你可以使用in_array()函数确定一个数组元素是否存在。

 代码如下 复制代码

$capitals = array( 
  'Arizona' => 'Phoenix', 
  'Alaska'  => 'Juneau', 
  'Alabama' => 'Montgomery' 
); 
if (in_array("Juneau", $capitals)) 

  echo "Exists!"; 
} else { 
  echo "Does not exist!"; 
}

很少有人知道这个函数也可以确定一个数组键是否存在,在这一点上,它和array_key_exists()函数的功能一样。

 

 代码如下 复制代码
$capitals = array( 
  'Arizona' => 'Phoenix', 
  'Alaska'  => 'Juneau', 
  'Alabama' => 'Montgomery' 
); 
if (array_key_exists("Alaska", $capitals)) 

  echo "Key exists!"; 
} else { 
  echo "Key does not exist!"; 

9、搜索数组
你可能想搜索数组资源,这样用户就可以方便地用一个特定的州府检索关联的州,可以通过array_search()函数实现数组搜索。

 代码如下 复制代码


$capitals = array( 
  'Arizona' => 'Phoenix', 
  'Alaska'  => 'Juneau', 
  'Alabama' => 'Montgomery' 
); 
$state = array_search('Juneau', $capitals); 
// $state = 'Alaska' 

10、标准PHP库
标准PHP库(Standard PHP Library,SPL)为开发人员提供了许多数据结构,迭代器,接口,异常和其它以前PHP语言没有的功能,使用这些功能可以通过面向对象的语法遍历数组。

 代码如下 复制代码


$capitals = array( 
  'Arizona' => 'Phoenix', 
  'Alaska'  => 'Juneau', 
  'Alabama' => 'Montgomery' 
); 
$arrayObject = new ArrayObject($capitals); 
foreach ($arrayObject as $state => $capital) 

  printf("The capital of %s is %s<br />", $state, $capital); 

// The capital of Arizona is Phoenix 
// The capital of Alaska is Juneau 
// The capital of Alabama is Montgomery

遍历关联数组的三种方法:

foreach

 代码如下 复制代码
<?php
$sports = array(
    'football' => 'good',
    'swimming' => 'very well',
    'running'  => 'not good'
 );
 
foreach ($sports as $key => $value) {
    echo $key.": ".$value."<br />";
}
?>

程序运行结果:

football: good 

swimming: very well 

 running: not good


each

 

 代码如下 复制代码

<?php
$sports = array(
    'football' => 'good',
    'swimming' => 'very well',
    'running'  => 'not good'
 );
 
while ($elem = each($sports)) {
    echo $elem['key'].": ".$elem['value']."<br />";
}
?>

程序运行结果:

football: good
swimming: very well
running: not good

list & each

 代码如下 复制代码

<?php
$sports = array(
    'football' => 'good',
    'swimming' => 'very well',
    'running'  => 'not good'
 );
 
while (list($key, $value) = each($sports)) {
    echo $key.": ".$value."<br />";
}
?>

程序运行结果:

football: good
swimming: very well
running: not good


哈希表== Hash Table


有一份用户名列表,存储了 10000 个用户名,没有重复项;
还有一份黑名单列表,存储了 2000 个用户名,格式与用户名列表相同;
现在需要从用户名列表中删除处在黑名单里的用户名,要求用尽量快的时间处理。

这个问题是一个小规模的处理量,如果实际一点,2 个表都可能很大,比如有 2 亿条记录。

我最开始想到的方法,就是做一个嵌套的循环,设用户名表有 M 条记录,黑名单列表有 N 条记录,那么,循环的次数是 M * N 次!
PHP 版代码:

 代码如下 复制代码
<?php
foreach($arrayM as $keyM => $nameM) {
   foreach($arrayN as $nameN) {
   if ($nameM == $nameN) {
   // 本行执行了 M * N 次!
   unset($arrayM[$keyM]);
   }
   }
}
return $arrayM;
?>

另一种方式,利用数组索引。

PHP 是一种弱类型的语言,不像 C 语言那样有严格的变量类型限制。C 语言的数组,每一个元素的类型必须一致,而且索引都是从 0 开始。
PHP 的数组,可以用字符串作为索引,也称为关联数组。
数组索引,有一个天然的限制就是不会重复,而且访问的时候不需要查找,可以直接定位。

还是刚才的那个问题,我们采用另一种办法。

把黑名单列表的用户名组织到一个数组里,数组的索引就是用户名。

然后,遍历用户列表的时候,只需直接用 isset 查询那个用户名是否存在即可。

PHP 版代码:

 代码如下 复制代码

<?php
$arrayHash = array();
foreach($arrayN as $nameN) {
   // 本行执行了 N 次。
   $arrayHash[$nameN] = 1;
}
 

foreach($arrayM as $keyM => $nameM) {
   if (isset($arrayHash[$nameM])) {
   // 本行执行了 M 次!
   unset($arrayM[$keyM]);
   }
}
return $arrayM;
?>

可以看到,优化过的代码,循环次数是 M + N 次。

假如 M 和 N 都是 10000,优化前,循环了 1 亿次;优化后,只循环了 20000 次,差了 5000 倍!
如果第二个程序耗时 1 秒,则第一个程序需要将近一个半小时

在php中要保存远程图片到自己服务器本地,我们需要先正则字符串中的内容图片,然后再利用相关函数把图片读取并保存到本地硬盘即可。
 代码如下 复制代码

<?
header("Content-type:image/jpeg");
function read_url($str)
{
$file=fopen($str,"r");
while(!feof($file))
{
$result.=fgets($file,9999);
}
fclose($file);
return $result;

}

function save_img($str)
{
$result=read_url($str);
$result=str_replace(""","",$result);
$result=str_replace("'","",$result);

preg_match_all('/<imgssrc=(http://.*?)(s(.*?)>|>)/i',$result,$matches);

foreach($matches[1] as $value)
{
echo $value."<br>n";
//GrabImage($value,$filename="");
}
}

// $url 是远程图片的完整URL地址,不能为空。
// $filename 是可选变量: 如果为空,本地文件名将基于时间和日期
// 自动生成.

function GrabImage($url,$filename="") {
if($url==""):return false;endif;

$path="download/"; //指定存储文件夹

//若文件不存在,则创建;
if(!file_exists($path)){
mkdir($path);
}

if($filename=="") {
$ext=strrchr($url,".");
if($ext!=".gif" && $ext!=".jpg"):return false;endif;
$filename=$path.date("dMYHis").$ext;
}

ob_start();
readfile($url);
$img = ob_get_contents();
ob_end_clean();
$size = strlen($img);

$fp2=@fopen($filename, "a");
fwrite($fp2,$img);
fclose($fp2);

return $filename;
}
save_img("http://www.111cn.net");
?>

dedecms中图版保存到本地方法

 代码如下 复制代码

 if(!empty($saveremoteimg))
        {
                $body = stripslashes($body);
                $img_array = array();
                preg_match_all("/(src|SRC)=[""|'| ]{0,}(http://(.*).(gif|jpg|jpeg|bmp|png))/isU",$body,$img_array);
                $img_array = array_unique($img_array[2]);
                set_time_limit(0);
                $imgUrl = $img_dir."/".strftime("%Y%m%d",time());
                $imgPath = $base_dir.$imgUrl;
                $milliSecond = strftime("%H%M%S",time());
                if(!is_dir($imgPath)) @mkdir($imgPath,0777);
                foreach($img_array as $key =>$value)
                {
                        $value = trim($value);
                        $get_file = @file_get_contents($value);
                        $rndFileName = $imgPath."/".$milliSecond.$key.".".substr($value,-3,3);
                        $fileurl = $imgUrl."/".$milliSecond.$key.".".substr($value,-3,3);
                        if($get_file)
                        {
                                $fp = @fopen($rndFileName,"w");
                                @fwrite($fp,$get_file);
                                @fclose($fp);
                        }
                        $body = ereg_replace($value,$fileurl,$body);
                }
                $body = addslashes($body);
        }

无限级分类是我们常用见的一个程序方法了,原理是得到有层级关系的数组,就是顶级是顶级分类,然后每个分类中有个children子数组,记录它的子分类,这样一级一级的分级数组

算法的数据库结构设计最为简单。category表中一个字段id,一个字段fid(父id)。这样可以根据WHERE id = fid来判断上一级内容,运用递归至最顶层

我们先查出数组

 代码如下 复制代码
<?php
$a = array(
  'AAAAAA'  =>  array(
        'aaaaaa' => array(
                 '111111',
                 '222222',
                 '333333'
        ),
        'bbbbbb'  => array(
                  '111111',
                 '222222',
                 '333333'
        ),
        'cccccc'  => array(
                  '111111',
                  '222222',
                  '333333'
        ),                     
  ),
  'BBBBBB'  =>   array(
        'aaaaaa' => array(
                  '111111',
                  '222222',
                  '333333'
        ),
        'bbbbbb'=> array(
                  '111111',
                  '222222',
                  '333333'
        ),
        'cccccc'=> array(
                  '111111',
                  '222222',
                  '333333'
        ),
  ),
  'CCCCCC'  => array(
        'aaaaaa'=> array(
                  '111111',
                  '222222',
                  '333333'
        ),
        'bbbbbb'=> array(
                  '111111',
                  '222222',
                  '333333'
        ),
        'cccccc'         => array(
                  '111111',
                  '222222',
                  '333333'
        ),
  ),
);
foreach ($a as $k=>$v){
   echo $k."<br>";
  // if(is_array($v)){
       foreach($v as $key=>$val){
          echo "  ".$key."<br>";
  //     }                           
       if(is_array($val)){
          foreach($val as $kkk=>$vall){
             echo "    ".$vall."<br>";
          }
       }
   }
   echo "<br>";
   }
  
  
    /*******mysql查询无限级分类的代码******/
    /***
   $sql = "SELECT a.Title AS big, b.Title AS small
            FROM largeTitle AS a LEFT JOIN smallTitle  AS b ON  a.ID=b.LargeID";
           
    $a = array();
   
    $r = mysql_query($sql);
   
    while( $arr = mysql_fetch_array($r)){
        $a[$arr['big']] = $arr['small'];
    }
    ***/
?>  

       

好了下面先读取数据库然后再递归读出

分类表,比如category,字段有 id,parentid,title

 代码如下 复制代码

//查询
 
$dsql->SetQuery("SELECT * FROM category ORDER BY sortorder ASC");
$dsql->Execute('parentlist');
$array = array();
$parentlist = array();
while ($rs=$dsql->getObject('parentlist'))
{
    if($rs->parentid == 0)
    {
        $parentlist[$rs->id] = (array)$rs;
    }
    else
    {
        $array[$rs->id] = (array)$rs;
    }
}
$parentlist = cat_options($parentlist, $array);  //我们求的结果数组
 
//$list父级分类的数组
 
//$array是除父级分类外的全部分类的数组
 
function cat_options(&$list,&$array)
{
    foreach ($list as $key => $arr)
    {
        foreach ($array as $k => $value)
        {
            if($value['parentid'] == $arr['id'])
            {
                $list[$key]['children'][] = $value;
                unset($array[$k]);
            }
        }
    }
    foreach ($list as $key => $arr)
    {
        if(is_array($arr['children']) && count($arr['children']) > 0)
        {
            $list[$key]['children'] = cat_options($list[$key]['children'], $array);
        }
    }
    return $list;
}

其它的方法,设置fid字段类型为varchar,将父类id都集中在这个字段里,用符号隔开,比如:1,3,6
这样可以比较容易得到各上级分类的ID,而且在查询分类下的信息的时候,
可以使用:SELECT * FROM category WHERE pid LIKE “1,3%”。

 

 代码如下 复制代码

--
-- 表的结构 `category`
--
CREATE TABLE IF NOT EXISTS `category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` int(11) NOT NULL COMMENT '1为文章类型2为产品类型3为下载类型',
`title` varchar(50) NOT NULL,
`lft` int(11) NOT NULL,
`rgt` int(11) NOT NULL,
`lorder` int(11) NOT NULL COMMENT '排序',
`create_time` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;
--
-- 导出表中的数据 `category`
--
INSERT INTO `category` (`id`, `type`, `title`, `lft`, `rgt`, `lorder`, `create_time`) VALUES
(1, 1, '顶级栏目', 1, 18, 1, 1261964806),
(2, 1, '公司简介', 14, 17, 50, 1264586212),
(3, 1, '新闻', 12, 13, 50, 1264586226),
(4, 2, '公司产品', 10, 11, 50, 1264586249),
(5, 1, '荣誉资质', 8, 9, 50, 1264586270),
(6, 3, '资料下载', 6, 7, 50, 1264586295),
(7, 1, '人才招聘', 4, 5, 50, 1264586314),
(8, 1, '留言板', 2, 3, 50, 1264586884),
(9, 1, '总裁', 15, 16, 50, 1267771951);

/**
* 显示树,把所有的节点都显示出来。
* 1、先得到根结点的左右值(默认根节点的title为“顶级目录”)。
* 2、查询左右值在根节点的左右值范围内的记录,并且根据左值排序。
* 3、如果本次记录右值大于前次记录的右值则为子分类,输出时候加空格。
* @return array
**/
function display_tree(){

//获得root左边和右边的值
$arr_lr = $this->category->where("title = '顶级栏目'")->find();
//print_r($arr_lr);
if($arr_lr){
$right = array();
$arr_tree = $this->category->query("SELECT id, type, title, rgt FROM category WHERE lft >= ". $arr_lr['lft'] ." AND lft <=".$arr_lr['rgt']." ORDER BY lft");
foreach($arr_tree as $v){
if(count($right)){
while ($right[count($right) -1] < $v['rgt']){
array_pop($right);
}
}
$title = $v['title'];
if(count($right)){
$title = '|-'.$title;
}
$arr_list[] = array('id' => $v['id'], 'type' => $type, 'title' => str_repeat(' ', count($right)).$title, 'name' =>$v['title']);
$right[] = $v['rgt'];
}
return $arr_list;
}
}

好了 只要这样所有的分类都可以一次性查询出来了,而不用通过递归了。

[!--infotagslink--]

相关文章

  • 源码分析系列之json_encode()如何转化一个对象

    这篇文章主要介绍了源码分析系列之json_encode()如何转化一个对象,对json_encode()感兴趣的同学,可以参考下...2021-04-22
  • C#中using的三种用法

    using 指令有两个用途: 允许在命名空间中使用类型,以便您不必限定在该命名空间中使用的类型。 为命名空间创建别名。 using 关键字还用来创建 using 语句 定义一个范围,将在此...2020-06-25
  • php中去除文字内容中所有html代码

    PHP去除html、css样式、js格式的方法很多,但发现,它们基本都有一个弊端:空格往往清除不了 经过不断的研究,最终找到了一个理想的去除html包括空格css样式、js 的PHP函数。...2013-08-02
  • index.php怎么打开?如何打开index.php?

    index.php怎么打开?初学者可能不知道如何打开index.php,不会的同学可以参考一下本篇教程 打开编辑:右键->打开方式->经文本方式打开打开运行:首先你要有个支持运行PH...2017-07-06
  • PHP中func_get_args(),func_get_arg(),func_num_args()的区别

    复制代码 代码如下:<?php function jb51(){ print_r(func_get_args()); echo "<br>"; echo func_get_arg(1); echo "<br>"; echo func_num_args(); } jb51("www","j...2013-10-04
  • vue:el-input输入时限制输入的类型操作

    这篇文章主要介绍了vue:el-input输入时限制输入的类型操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-05
  • PHP编程 SSO详细介绍及简单实例

    这篇文章主要介绍了PHP编程 SSO详细介绍及简单实例的相关资料,这里介绍了三种模式跨子域单点登陆、完全跨单点域登陆、站群共享身份认证,需要的朋友可以参考下...2017-01-25
  • JS双击变input框批量修改内容

    这篇文章主要介绍了JS双击变input框批量修改内容的实现代码,非常不错,具有参考借鉴价值,需要的朋友可以参考下...2017-01-09
  • iscroll.js 用法介绍

    最新版下载: http://www.csdn123.com/uploadfile/2015/0428/20150428062734485.zip 概要 iScroll 4 这个版本完全重写了iScroll这个框架的原始代码。这个项目的产生...2016-05-19
  • PHP实现创建以太坊钱包转账等功能

    这篇文章主要介绍了PHP实现创建以太坊钱包转账等功能,对以太坊感兴趣的同学,可以参考下...2021-04-20
  • C++中cin的用法详细

    这篇文章主要介绍了C++中cin的用法详细,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • C#中的try catch finally用法分析

    这篇文章主要介绍了C#中的try catch finally用法,以实例形式分析了try catch finally针对错误处理时的不同用法,具有一定的参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • php微信公众账号开发之五个坑(二)

    这篇文章主要为大家详细介绍了php微信公众账号开发之五个坑,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2016-10-02
  • PHP如何通过date() 函数格式化显示时间

    这篇文章主要介绍了PHP如何通过date() 函数格式化显示时间,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-11-13
  • ThinkPHP使用心得分享-ThinkPHP + Ajax 实现2级联动下拉菜单

    首先是数据库的设计。分类表叫cate.我做的是分类数据的二级联动,数据需要的字段有:id,name(中文名),pid(父id). 父id的设置: 若数据没有上一级,则父id为0,若有上级,则父id为上一级的id。数据库有内容后,就可以开始写代码,进...2014-05-31
  • vue element table中自定义一些input的验证操作

    这篇文章主要介绍了vue element table中自定义一些input的验证操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-18
  • 示例详解react中useState的用法

    useState 通过在函数组件里调用它来给组件添加一些内部 state,React 会在重复渲染时保留这个 state,接下来通过一个示例来看看怎么使用 useState吧...2021-06-04
  • golang与php实现计算两个经纬度之间距离的方法

    这篇文章主要介绍了golang与php实现计算两个经纬度之间距离的方法,结合实例形式对比分析了Go语言与php进行经纬度计算的相关数学运算技巧,需要的朋友可以参考下...2016-07-29
  • PHP+jQuery+Ajax实现多图片上传效果

    今天我给大家分享的是在不刷新页面的前提下,使用PHP+jQuery+Ajax实现多图片上传的效果。用户只需要点击选择要上传的图片,然后图片自动上传到服务器上并展示在页面上。...2015-03-15
  • PHP中print_r、var_export、var_dump用法介绍

    文章详细的介绍了关于PHP中print_r、var_export、var_dump区别比较以及这几个在php不同的应用中的用法,有需要的朋友可以参考一下 可以看出print_r跟var_export都...2016-11-25