yeah

搜索

计数器

64545

链接

谈谈PHP的输入输出流

Jan 31, 2010 11:57:28 PM | Comments(0) | Category:教程 | Tags:


手册上说:

PHP 3.0.13 及以上版本,自 PHP 4.3.0 起支持 php://output 和 php://input,自 PHP 5.0.0 起支持 php://filter。 

php://stdin

php://stdout

php://stderr

php://output

php://input

php://filter

php://stdin,php://stdout 和 php://stderr 允许访问 PHP 进程相应的输入或者输出流。 

php://output 允许向输出缓冲机制写入数据,和 print() 与 echo() 的方式相同。 

php://input 允许读取 POST 的原始数据。和 $HTTP_RAW_POST_DATA 比起来,它给内存带来的压力较小,并且不需要任何特殊的 php.ini 设置。php://input 不能用于 enctype="multipart/form-data"。 

php://stdin 和 php://input 是只读的,同时 php://stdout,php://stderr 和 php://output 是只写的。 

php://filter 是一种设计用来允许过滤器程序在打开时成为流的封装协议。这对于单独具有完整功能的文件函数例如 readfile(),file() 和 file_get_contents() 很有用,否则就没有机会在读取内容之前将过滤器应用于流之上。 


   也就是说post的原始数据是保存在一个叫php://input的文件。你可以通过简单的文件操作读取里面的数据来控制。

  

示例:

html部分:

<!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>test</title>
</head>

<body>
<form id="form1" name="form1" method="post" action="r.php">
  <label>名字
  <input type="text" name="name" id="name" />
  </label>
  <label><br />
  密码
  <input type="text" name="password" id="password" />
  <br />
  <input type="submit" name="submit" id="submit" value="提交" />
  </label>
  <label>
  <input type="reset" name="reset" id="reset" value="重置" />
  </label>
</form>
</body>
</html>


PHP部分:

if(strtolower($_SERVER['REQUEST_METHOD']) == "post"){
 echo file_get_contents("php://input"); 
}

你试试就知道效果了


Tags -

检查指定网址的 DNS 记录

Jan 16, 2010 11:28:56 PM | Comments(0) | Category:教程 | Tags:

checkdnsrr
检查指定网址的 DNS 记录。

语法: int checkdnsrr(string host, string [type]);

返回值: 整数

函数种类: 网络系统




内容说明


本函数用来检查 DNS 的字段纪录。指定的参数 host 可以是网络位址 (IP Address),也可以用机器名称 (Domain Name)。参数 type 可以省略,内定值为 MX。而参数 type 的值可为以下的其中之一:A、MX、NS、SOA、PTR、CNAME 或 ANY。若找到了指定网址的 DNS 字段,返回 true;若未找到指定的 DNS 字段或是有错误均会返回 false。

10个关于PHP你可能不知道的东东

Jan 16, 2010 11:28:00 PM | Comments(2) | Category:教程 | Tags:

貌似可以看到有很多的确没注意,充实下自己的PHP,也分享给大家。
下面是英语原文:
1.Use ip2long() and long2ip() to store IP addresses as integers instead of strings in a database. This will reduce the storage space by almost a factor of four (15 bytes for char(15) vs. 4 bytes for the integer), make it easier to calculate whether a certain address falls within a range, and speed-up searches and sorts (sometimes by quite a bit).
2.Partially validate email addresses by checking that the domain name exists with checkdnsrr(). This built-in function checks to ensure that a specified domain name resolves to an IP address. A simple user-defined function that builds on checkdnsrr() to partially valid email addresses can be found in the user comments section in the PHP docs. This is handy for catching those occasional folks who think their email address is ‘joeuser@wwwphp.net’ instead of ‘joeuser@php.net’.
3.If you’re using PHP 5 with MySQL 4.1 or above, consider ditching the mysql_* functions for the improved mysqli_* functions. One nice feature is that you can use prepared statements, which may speed up queries if you maintain a database-intensive website. Some benchmarks.
4.Learn to love the ternary operator.
5.If you get the feeling that you might be reinventing the wheel during a project, check PEAR before you write another line. PEAR is a great resource that many PHP developers are aware of, yet many more are not. It’s an online repository containing over 400 reusable snippets that can be dropped right into your PHP application. Unless your project is trully unique, you ought to be able to find a PEAR package that saves at least a little time. (Also see PECL)
6.Automatically print a nicely formatted copy of a page’s source code with highlight_file().This function is handy for when you need to ask for some assistance with a script in a messageboard, IRC, etc. Obviously, some care must be taken not to accidently show your source when it contains DB connection information, passwords, etc.
7.Prevent potentially sensitive error messages from being shown to users with the error_reporting(0) function. Ideally error reporting should be completely disabled on a production server from within php.ini. However if you’re on a shared webhost and you aren’t given your own php.ini, then your best bet is to add error_reporting(0); as the first line in each of your scripts (or use it with require_once().) This will prevent potentially sensitive SQL queries and path names from being displayed if things go awry.
8.Use gzcompress() and gzuncompress() to transparently compress/decompress large strings before storing them in a database. These built-in functions use the gzip algorithm and can compress plaintext up to 90%. I use these functions almost everytime I read/write to a BLOB field within PHP. The only exception is when I need full text indexing capabilities.
9.Return multiple values from a function with “by reference” parameters. Like the ternary operator, most PHP developers who come from a more formalized programming background already know this one. However, those who’s background is more HTML than Pascal, probably have wondered at one time “how do I get multiple values back from a function I wrote, even though I can only use one return value?” The answer is that you precede a variable with “&” and use it “by reference” instead of “by value”.
10.Fully understand “magic quotes” and the dangers of SQL injection. I’m hoping that most developers reading this are already familiar with SQL injection. However, I list it here because it’s absolutely critical to understand. If you’ve never heard the term before, spend the entire rest of the day googling and reading.

下面是中文翻译:(摘自网络)
1.使用 ip2long() 和 long2ip() 函数来把 IP 地址转化成整型存储到数据库里。这种方法把存储空间降到了接近四分之一(char(15) 的 15 个字节对整形的 4 个字节),计算一个特定的地址是不是在一个区段内页更简单了,而且加快了搜索和排序的速度(虽然有时仅仅是快了一点)。
2.在验证 email 地址的时候使用 checkdnsrr() 函数验证域名是否存在。这个内置函数能够确认指定的域名能够解析成 IP 地址。该函数的PHP 文档的用户评论部分有一个简单的用户自定义函数,这个函数基于 checkdnsrr(),用来验证 email 地址的合法性。对于那些认为自己的 email 地址是 “joeuser@wwwphp.net” 而不是 “joeuser@php.net” 的家伙们,这个方法可以很方便的抓住他们。
3.如果你使用的是 PHP 5 和 MySQL 4.1 或者更高的版本,考虑抛弃 mysql_* 系列函数改用改进版的 mysqli_* 系列函数。一个很好的功能就是你可以使用预处理语句,如果你在维护一个数据库密集型站点,这个功能能够加快查询速度。一些评估分数。
4.学会爱上三元运算符。
5.如果你在项目中感觉到有可复用的部分,在你写下一行代码前先看看 PEAR 中是否已经有了。很多 PHP 程序员都知道 PEAR 是一个很好的资源库,虽然还有很多程序员不知道。这个在线资源库包含了超过 400 个可以复用的程序片段,这些程序片段你可以立即用刀你的程序里。除非说你的项目真的是非常特别的,你总能找到帮你节省时间的 PEAR 包。(参见 PECL)
6.用 highlight_file() 来自动的打印出格式化的很漂亮的源代码。如果你在留言板、IRC 这些地方寻求一个脚本的帮助的话,这个函数用起来非常的顺手。当然了,要小心不要意外的泄露出你的数据库连接信息和密码等。
7.使用 error_reporting(0) 函数来防止用户看到潜在的敏感错误信息。]在理想情况下,发布服务器应该在 php.ini 里完全禁止。但是如果你用的是一个共享的 web 服务器的话,你没有自己的 php.ini 文件,那么这种情况下你最好的选择就是在所有脚本的第一行前加上 error_reporting(0);(或者使用 require_once() 方法)。这就能够在出错的时候完全屏蔽敏感的 SQL 查询语句和路径名。
8.在网数据库中存储很大的字符串之前使用 gzcompress() 和 gzuncompress() 来显式的压缩/解压字符串。这个 PHP 内置函数使用 gzip 算法,可以压缩普通文本达 90%。在我每次要读写 BLOB 类型的字段的时候都使用这些函数。唯一额例外就是当我需要全文检索的时候。
9.通过“引用”传递参数的方法从一个函数中得到多个返回值。就像三元运算符一样,大部分受过正式编程训练的程序员都知道这个技巧。但是那些 HTML 背景大于 Pascal 背景的程序员都或多或少的有过这样的疑问“在仅能使用一次 return 的情况下,从一个函数里返回多个值?”答案就是在变量前加上一个 “&” 符号,通过“引用”传递而非“值”传递。
10.完全理解“魔术引号”和 SQL 注入的危险性。我希望阅读到这里的开发者都已经很对 SQL 注入和了解了。不过我还是把这条列在这里,是因为这个确实有点难以理解。

如果你还没有听说过这种说法,那么把今天剩下的时间都用来 Google、阅读吧。

jQuery 1.4 发布:你必须知道的15个新特征

Jan 16, 2010 08:07:55 PM | Comments(1) | Category:教程 | Tags:

jQuery 1.4 Released: The 15 New Features you Must Know
原文:http://net.tutsplus.com/tutorial ... ures-you-must-know/

作者: James Padolsey

1. Passing Attributes to jQuery(…)
jQuery 1.4支持传送一个对象作为第2个参数给jquery自身。
在1.4,创建一个元素,可以这样做 jQuery('

', {

    id: 'foo',

    css: {

        fontWeight: 700,

        color: 'green'

    },

    click: function(){

        alert('Foo has been clicked!');

    }

});
复制代码在之前需要这样: jQuery('
')

    .attr('id', 'foo')

    .css({

        fontWeight: 700,

        color: 'green'

    })

    .click(function(){

        alert('Foo has been clicked!');

    });
复制代码第一段代码中,id添加到元素的属性上,为foo;css和click属性调用相应的方法,再比如,创建一个超链接: jQuery('', {

    id: 'foo',

    href: 'http://google.com',

    title: 'Become a Googler',

    rel: 'external',

    text: 'Go to Google!'

});
复制代码超链接是没有text属性的,jQuery1.4在这里就调用了".text()"的方法,"Go to Google!" 作为.text()的参数。
jQuery(…)

2. Everything "until"!
1.4添加了3个新的DOM遍历方法 "nextUntil", "prevUntil" 和 "parentsUntil":朝某个方向遍历直到符合传进这些方法的选择器。
比如一列水果


        
  • Apple


  •     
  • Banana


  •     
  • Grape




  •     
  • Strawberry


  •     
  • Pear


  •     
  • Peach



复制代码要取得"Apple"之后"Strawberry"之前的,可以这样: jQuery('ul li:contains(Apple)').nextUntil(':contains(Pear)');

// Selects Banana, Grape, Strawberry
复制代码prevUntil, nextUntil, parentsUntil

3. Binding Multiple Event Handlers
可以在一次调用中绑定一大堆事件 ,替换掉链式绑定 jQuery('#foo).bind({

    click: function() {

        // do something

    },

    mouseover: function() {

        // do something

    },

    mouseout: function() {

        // do something

    }

})
复制代码".one()"也可以多重绑定
.bind(…)

4. Per-Property Easing
可以对动画的每一个属性设置变换函数,而不再是一个函数对应单独一次动画。
jQuery包含2个变换函数:默认的为swing,还有一个是linear,其他的可以单独下载

可以设置属性为数组,第1个为将改变到的属性值,第2个为使用的函数 jQuery('#foo').animate({

    left: 500,

    top: [500, 'easeOutBounce']

}, 2000);
复制代码See this code in action!
也可以定义可选的options对象属性中"specialEasing" 对象的键/值 jQuery('#foo').animate({

    left: 500,

    top: 500

}, {

    duration: 2000,

    specialEasing: {

        top: 'easeOutBounce'

    }

});
复制代码(这个特性正是作者James Padolsey的主意)
Read more about per-property easing

5. New Live Events!
1.4支持"submit", "change", "focus" 和 "blur" 事件的委派,在使用".live()"方法的时候对大量元素或者新添加元素注册事件耗费资源更少。要注意的是,使用时要用"focusin" 和 "focusout"替换掉"focus" 和 "blur" jQuery('input').live('focusin', function(){

    // do something with this

});
复制代码6. Controlling a Function's Context
jQuery 1.4 在jQuery的命名空间下提供了一个新的代理函数。这个函数有2个参数,作用域 方法名 或者 函数 函数的作用域,我们可以改变this指向到自己先前创建的对象,而不是默认的那个元素上。
例如 var app = {

    config: {

        clickMessage: 'Hi!'

    },

    clickHandler: function() {

        alert(this.config.clickMessage);

    }

};
复制代码在调用的时候this指app app.clickHandler(); // "Hi!" is alerted
复制代码而下面代码调用时候就不起作用了。 Query('a').bind('click', app.clickHandler);
复制代码这种原生的事件模型触发时候handler的上下文指向target元素,要改变的话: jQuery('a').bind(

    'click',

    jQuery.proxy(app, 'clickHandler')

);
复制代码点击链接的时候"Hi!"弹出

proxy函数包装了原函数,把this指向你定义的任何东西。可以用在多种方面,比如把回调函数传到其他jQuery方法或者插件
Read more about jQuery.proxy


7. Delay an Animation Queue

让你在动画之间停止而不需要使用 "setTimeout" jQuery('#foo')

    .slideDown() // Slide down

    .delay(200) // Do nothing for 200 ms

    .fadeIn(); // Fade in
复制代码第一个参数是时间
第2个可选参数传入列名字用来改变默认的"fx" queue
Read more about .delay(…)

8. Check if an Element Has Something
同":has()"的过滤选择器作用一样".has()"用来查看一个或一组元素有没有某种东西,用在程序流程中动态使用 jQuery('div').has('ul');//获取包含UL的div
复制代码"contains"函数重写为第2个参数是否包含第1个参数 jQuery.contains(document.documentElement, document.body);

// Returns true - is within
复制代码.has(…)jQuery.contains(…)


9. Unwrap Elements!
对应".wrap()"方法添加了一个".unwrap()"的新方法,用来去掉任一元素的父元素


    

Foo




复制代码去掉(unwrap)p可以这样: jQuery('p').unwrap();
复制代码变成

Foo


复制代码.unwrap(…)


10. Remove Elements Without Deleting Data

新方法".detach()"同 ".remove()"方法不同在于不会摧毁".data()"添加的数据和移除绑定的事件
这对于从DOM中取出再插入元素很有用 var foo = jQuery('#foo');



// Bind an important event handler

foo.click(function(){

    alert('Foo!');

});



foo.detach(); // Remove it from the DOM



// … do stuff



foo.appendTo('body'); // Add it back to the DOM



foo.click(); // alerts "Foo!"
复制代码.detach(…)



11. index(…) Enhancements
jQuery 1.4 给出了2种使用 ".index()"的新方式,之前只是传入一个元素返回表示位置的数字

一种是不传入参数


        
  • Apple


  •     
  • Banana


  •     
  • Grape




  •     
  • Strawberry


  •     
  • Pear


  •     
  • Peach



复制代码jQuery('li').click(function(){

    alert( jQuery(this).index() );

});
复制代码返回所点击元素的位置(当前元素在它的兄弟siblings中的index)

另外也可以传入一个选择器selector,返回当前元素element在选择器返回的集合中的index。返回-1,则表示不符合

.index(…)


12. DOM Manipulation Methods Accept Callbacks
after
before
append
prepend
addClass
toggleClass
removeClass
wrap
wrapAll
wrapInner
val
text
replaceWith
css
attr
html
这些方法可以传入一个函数。回调函数遍历时候,this指向当前元素,元素在集合中的位置作为第1个参数,其返回值作为相应实际的值 jQuery('li').html(function(i){

    return 'Index of this list item: ' i;

});
复制代码在使用".html()" 或 ".attr('href)"等方法设置值的时候,回调函数第2个参数为当前值 jQuery('a').attr('href', function(i, currentHref){

    return currentHref '?foo=bar';

});
复制代码在使用".css() 或 ".attr()"等方法改变值的时,方法第一个就是要改变的属性。 jQuery('li').css('color', function(i, currentCssColor){

    return i % 2 ? 'red' : 'blue';

});
复制代码13. Determine the Type of Object
"isEmptyObject"根据是不是空对象(没有直接的或是继承的属性)返回一个布尔值
"isPlainObject"根据是不是"{}"或者"new Object()"创建的JavaScript对象 返回一个布尔值 jQuery.isEmptyObject({}); // true

jQuery.isEmptyObject({foo:1}); // false



jQuery.isPlainObject({}); // true

jQuery.isPlainObject(window); // false

jQuery.isPlainObject(jQuery()); // false
复制代码14. Closest(…) Enhancements
".closest()"可以接受一组选择器过滤(遍历父代的时候只选择一定特征的)和第2个参数控制遍历深度
.closest(…)


15. New Events! focusIn and focusOut
上面提到的这两个新委派事件方法用来在当前元素或后代元素获得焦点的时候捕获。注意只有从上到下的捕获过程而没有冒泡过程,也就是说外层的父代的元素比引起事件的目标"target"元素先触发。 jQuery('form')

    .focusin(function(){

        jQuery(this).addClass('focused');

    });

    .focusout(function(){

        jQuery(this).removeClass('focused');

    });
复制代码focusIn and focusOut events.

更多参考

"14 days of jQuery"
API documentation!

PHP排序算法(选择排序)

Jan 13, 2010 06:18:38 AM | Comments(1) | Category:教程 | Tags:

(1)说明:
“选择排序法”(Selection Sort)是从排序的元素中选出最小的一个元素,然后和第一个元素交换。然后从剩下的元素中选出最小的元素和第二个元素交换,重复这种处理的方法,直到最后一个元素为止。
(2)算法:
$arr  = array(1, 4, 2, 3, 6);
$arrSize = count($arr);
for($i = 0; $i < $arrSize - 1; $i ) {
    for($j = $i 1; $i < $arrSize; $i ) {
        if($j < $i) {
            $tmp = $arr[$j];
            $arr[$j] = $arr[$i];
            $arr[$i] = $tmp;
        }
    }
}
(3)运行效率
第一层循环需要运行n-1次,n是全部排序元素的个数,第二层循环根据序为n-1, n-2, n-3,......,1,0,总计为n(n-1)/2次,可以得到其运行效率为O(n平方)

PHP排序算法(插入排序)

Jan 13, 2010 06:01:32 AM | Comments(81) | Category:教程 | Tags:

(1)说明:
“插入排序法”(Insert Sort)是先将排序元素的前两个元素排序,然后将第三个元素插入已经排序好的两个元素中,所以这三个元素仍然是从小到大排序,接着将第四个元素插入,重复操作直到所有元素都排序好。
(2)算法
$arr = array(1, 5, 3, 2, 6);
$arrSize = count($arr);
for($i = 1; $i < $arrSize; $i ) {
    $tmp = $arr[$i]; //存储当前元素
   $j = $i - 1; //前一元素索引
   //如果前面元素(当前元素前面所有的元素)存在并且大于当前元素,则前面的元素依次后移
   while($j >= 0 && $tmp < $arr[$j]) {
        //移动元素
       $arr[$j 1] = $arr[$j];
          $j --;
    }
    $arr[$j 1] = tmp;
}
(3)运行效率
当排序元素有n个时,第二层循环将插入1, 2, 3, 4, 。。。。。。, n-1,合计为n(n-1)/2,其运行效率为O(n平方)

新W3C标准中 AJAX 跨域实现以及隐患

Jan 13, 2010 04:21:18 AM | Comments(1) | Category:教程 | Tags:

标准也很无奈,标准很难做到 Secure By Default。
最新的W3C标准里是这么实现HTTP跨域请求的,

Cross-Origin Resource Sharing
简单来说,就是跨域的目标服务器要返回一系列的Headers,通过这些Headers来控制是否同意跨域。
这些Headers有:

4 Syntax
4.1 Access-Control-Allow-Origin HTTP Response Header
4.2 Access-Control-Max-Age HTTP Response Header
4.3 Access-Control-Allow-Credentials HTTP Response Header
4.4 Access-Control-Allow-Methods HTTP Response Header
4.5 Access-Control-Allow-Headers HTTP Response Header
4.6 Origin HTTP Request Header
4.7 Access-Control-Request-Method HTTP Request Header
4.8 Access-Control-Request-Headers HTTP Request Header
在 Request 包和 Response 包中都有一些。
其中最敏感的就是 Access-Control-Allow-Origin 这个 Header, 他是W3C标准里用来检查该跨域请求是否可以被通过。 (Access Control Check)
跨域实现的过程大致如下:
从 http://www.a.com/test.html 发起一个跨域请求,
请求的地址为: http://www.b.com/test.php
如果 服务器B返回一个如下的header
Access-Control-Allow-Origin: http://www.a.com
那么,这个来自 http://www.a.com/test.html 的跨域请求就会被通过。
在这个过程中, request 还会带上这个header:
Origin: http://www.a.com

不过这里比较要命的是 Access-Control-Allow-Origin 的值可以是通配符 *
如果是 * 的话,就可以接收来自任意source origin的请求。
我已经可以想象到以后这个特性被程序员滥用以及被用来制作后门的可怕后果了!

在 Firefox 3.1 Beta 2 上抓包如下:

GET http://www.b.com/test.php HTTP/1.1
Host: www.b.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2 Paros/3.2.13
Accept: text/html,application/xhtml xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.5
Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Referer: http://www.a.com/test.html
Origin: http://www.a.com
Cache-Control: max-age=0

HTTP/1.1 200 OK
Date: Thu, 15 Jan 2009 06:28:54 GMT
Server: Apache/2.0.63 (Win32) PHP/5.2.6
X-Powered-By: PHP/5.2.6
Access-Control-Allow-Origin: *
Content-Length: 28
Content-Type: text/html

Cross Domain Request Test!

两段代码大致如下:
www.a.com/test.html:


www.b.com/test.php:

header("Access-Control-Allow-Origin: *");

?>

Cross Domain Request Test!

除了这个Header外,还可以通过一些其他的Header 来控制比如 Method, 时间等,可以参考标准,不在此赘述。

出于安全考虑,跨域请求不能访问document.cookie 对象

对于IE8 Beta 2, 则是通过 XDomainRequest 来实现的这个跨域请求

比如类似如下代码就可以实现了:

var request = new XDomainRequest();
request.open("GET", xdomainurl);
request.send();

也要求对方服务器返回这个头才行。

IE的开发者今天公布了一段小视频:
http://ieblog.members.winisp.net/images/XdomainRequest-small.wmv

目前,支持这种跨域实现的要求

Firefox 3.1 Beta2

IE 8 Beta2

等到普及还有一段时间。

最后再加一个Firefox3.1实现跨域的说明文档:
https://developer.mozilla.org/En/HTTP_access_control

Tags - ,

PHP排序算法(冒泡排序)

Jan 13, 2010 02:32:51 AM | Comments(0) | Category:教程 | Tags:

做PHP很少用到算法,把算法都给忘完了,现在重新学习下。,真丢脸!


冒泡排序:
(1),基本思路
后一个数跟前一个数依次比较,每循环一次就把最大的数排到了数组的最后。
注:当排序过一次后,最大的数(位于数组末尾)无需再参与排序
(2),找出数组中的最大数(复习)

$arr = array(1, 5, 8, 2, 7);
$arrSize = count($arr);

//$i < $arrSize - 1 你要问我这个是什么意思?我真想拿砖拍你,后面用到后一个数跟前一个数比较,如果已经到最后一个了,$i 1是不是越界了?
for($i = 0; $i < $arrSize - 1; $i ) {
    //如果后一个数小于前一个数,则交换
    if($arr[$i 1] < $arr[$i]) {
        $tmp = $arr[$i];
        $arr[$i] = $arr[$i 1];
        $arr[$i 1] = $tmp;
    }
}

(3),算法实现
$arr = array(1, 5, 8, 2, 7);
$arrSize = count($arr);

for($i = $arrSize; $i > 1; $i --) {
    for($j = 0; $j < $i - 1; $j ) {
        if($arr[$j 1] < $arr[$j]) {
            $tmp = $arr[$j];
            $arr[$j] = $arr[$j 1];
            $arr[$j 1] = $tmp;
        }
    }
}

(4), 算法优化
    (3)的算法中,第二层循环经过两次交换后,排序已经完成。但外层还一直循环着,我们要设置一个是否交换元素的变量来停止没必要的循环。
$arr = array(1, 5, 8, 2, 7);
$arrSize = count($arr);

for($i = $arrSize; $i > 1; $i --) {
    $exchg = false;
    for($j = 0; $j < $i - 1; $j ) {
        if($arr[$j 1] < $arr[$j]) {
            $tmp = $arr[$j];
            $arr[$j] = $arr[$j 1];
            $arr[$j 1] = $tmp;
            $exchg = true;
        }
    }
    if(! $exchg)
        break;
}
(5),排序效率
这里的效率为最差效率。如果开始时元素使用相反的顺序排列着,无素个数为n个,则后层循环共n-1次,内层循环根据外层循环不断递减,依次为(n-1),(n-2)......2,1,总和为n(n-1)/2次的比较和交换。运行效率为O(n平方)