转到正文

浪淘沙

静观己心,厚积薄发

存档

标签: php

咱们做WEB都知道COOKIE和SESSION这对好基友。他们2个总是如影相随。大部分人也是知道如果客户端禁用COOKIE(发送request的时候不发送COOKIE或者直接unset($_COOKIE)来模拟禁用COOKIE)SESSION还是可以用了。只需要通过GET或者POST的方式传递过来SESSIONID即可。具体的做法如下:


<?php
unset($_COOKIE);//禁用cookie
$sid = isset($_REQUEST['sid']) ? $_REQUEST['sid'] :'';
if ($sid) {//如果将sessionid传递了过来,先设置sessionid 然后 开启session PS:session_id方法必须在session_start()之前调用,否则无效
session_id($sid);
}
session_start();
$sid = session_id();

if (isset($_SESSION['content'])) {
echo 'get session:',$_SESSION['content'],'<br/>';
} else {
$_SESSION['content'] = 'content';
echo 'save session<br/>';
}
echo '<a href="./session.php?sid='.$sid.'">one more</a>';

file_put_contents  这个方法顾名思义就是将一个字符串写入到指定的文件。这个方法需要注意的是:在出现并发事件的时候,file_put_contents可能会出现写入文件失败的情况。直接上测试代码。

</p>
<p>&lt;?php </p>
<p>$index = isset($_GET['index']) ? $_GET['index'] : microtime(true);<br />
$ret = file_put_contents('e:/tmp/file_put_contents.log',$index . PHP_EOL, FILE_APPEND); </p>
<p>if ($ret === false) {<br />
    echo index, ' file_put_contents failure';<br />
} else {<br />
    echo index, ' file_put_contents success';<br />
}</p>
<p>

使用 apache的ab直接做压力测试。

path-to-ab:  ab -n 1000 -c 50 http://local.test.me/file_put_contents.php

PS:意思为 总共访问http://local.test.me/file_put_contents.php这个脚本1000次,50并发同时执行。

最后的到得结果950左右行记录。 也就是说,会有50左右次写失败。

稍微修改代码,在file_put_contents 后面追加参数 LOCK_EX。最终代码如下:

</p>
<p>&lt;?php</p>
<p>$index = isset($_GET['index']) ? $_GET['index'] : microtime(true);<br />
//$ret = file_put_contents('e:/tmp/file_put_contents.log',$index . PHP_EOL, FILE_APPEND); //直接这样有失败的情况</p>
<p>$ret = file_put_contents('e:/tmp/file_put_contents.log',$index . PHP_EOL, LOCK_EX | FILE_APPEND);</p>
<p>if ($ret === false) {<br />
echo index, ' file_put_contents failure';<br />
} else {<br />
echo index, ' file_put_contents success';<br />
}</p>
<p>

再次ab压测,得出结果正常。1000次写入全部成功。

参数 LOCK_EX的意思 php manual 描述如下:Acquire an exclusive lock on the file while proceeding to the writing. (写入文件的时候,添加一个排他锁)。

 

PHP支持OOP编程,这大家都知道。但是PHP的继承和JAVA还是有点区别的。比较致命的一点就是:如果子类(ExtendsB)显示实现构造方法,那么在实例化ExtendsB的时候,系统并不会主动调用父类(ExtendsA)的构造方法

如果必须调用父类构造方法有2种方法:

1、子类(ExtendsB)中不实现构造方法(及时子类不要空实现构造方法)

2、自己手动调用父类构造方法(parent::__construct();)

直接上例子吧。

<?php
class ExtendsA {
    protected $c;

    public function ExtendsA(){
        $this->c = 10;
    }
}

class ExtendsB extends ExtendsA{
    //public function b(){} //这行解注释 就不会打印东西出来。因为ExtendsA构造没有被执行
    public function print_data(){
        echo $this->c;
    }
}

$b = new ExtendsB();
$b->print_data();

而JAVA代码就不是这样的。无论是否实现构造方法,再实例化子类的时候,系统都会递归调用父类构造方法。

public class ExtendsTestMain {

    public static void main(String args[]) {
        ExtendsTestB b = new ExtendsTestB();
        b.printData();
    }
}

class ExtendsTestA {

    protected int c;

    public ExtendsTestA() {
        c = 10;
    }
}

class ExtendsTestB extends ExtendsTestA {

    public ExtendsTestB() {

    }

    public void printData() {
        System.out.println(c);
    }
}

 

gettype获取变量的类型

string gettype ( mixed $var )  返回 PHP 变量的类型 var .

PHP manual 有个大大的warning:

不要使用 gettype() 来测试某种类型,因为其返回的字符串在未来的版本中可能需要改变。此外,由于包含了字符串的比较,它的运行也是较慢的。

使用 is_* 函数代替。

但是有时候 我们又不得不使用gettype这样的功能来判断参数的类型,这个时候我们应该怎么办?O(∩_∩)O哈哈~ 热心的网友已经帮我们重新实现了这个逻辑。代码如下:

 
function get_type($var)
{
    if (is_object($var)) {
        return get_class($var);
    }
    if (is_null($var)) {
        return 'null';
    }
    if (is_string($var)) {
        return 'string';
    }
    if (is_array($var)) {
        return 'array';
    }
    if (is_int($var)) {
        return 'integer';
    }
    if (is_bool($var)) {
        return 'boolean';
    }
    if (is_float($var)) {
        return 'float';
    }
    if (is_resource($var)) {
        return 'resource';
    }
    return 'unknown';
}

另一个版本

/**
 * Returns the type of the var passed.
 *
 * @param mixed $var Variable
 *
 * @return string Type of variable
 */
function myGetType($var)
{
    if (is_array($var)) {
        return "array";
    }
    if (is_bool($var)) {
        return "boolean";
    }
    if (is_float($var)) {
        return "float";
    }
    if (is_int($var)) {
        return "integer";
    }
    if (is_null($var)) {
        return "NULL";
    }
    if (is_numeric($var)) {
        return "numeric";
    }
    if (is_object($var)) {
        return "object";
    }
    if (is_resource($var)) {
        return "resource";
    }
    if (is_string($var)) {
        return "string";
    }
    return "unknown type";
}

 

sscanf

(PHP 4 >= 4.0.1, PHP 5)

sscanf — Parses input from a string according to a format。

其他的就不多说了。就说下。使用sscanf format大数字的情况。


$line = '100004318055950,100';
list($uid, $expendGoldNum) = sscanf($line, '%f,%d');
echo '$uid:',$uid, '&nbsp;&nbsp;&nbsp;$expendGoldNum":',$expendGoldNum;

运行结果为:


$uid:1.0000431805595E+14      $expendGoldNum":100

逗号前面的内容直接显示为使用科学计数法表示。


$line = '100004318055950,100';
list($uid, $expendGoldNum) = sscanf($line, '%s,%d');
echo '$uid:',$uid, '&nbsp;&nbsp;&nbsp;$expendGoldNum":',$expendGoldNum;

运行结果为:


$uid:100004318055950,100   $expendGoldNum":

如果将%f修改为%s 则因为%s将所有的内容全部匹配了,不符合要求。


$line = '100004318055950,100';
list($uid, $expendGoldNum) = sscanf($line, '%[0-9],%d');
echo '$uid:',$uid, '&nbsp;&nbsp;&nbsp;$expendGoldNum":',$expendGoldNum;

运行结果为:


$uid:100004318055950   $expendGoldNum":100

这次正确了。

 

Swift Mailer

12月 10

 

Swift Mailer 是一个面向对象的PHP邮件发送包,不依赖于 PHP 自带的mail() 函数,因为该函数在发送多个邮件时占用的系统资源很高。Swift 直接与 SMTP 服务器通讯,具有非常高的发送速度和效率。

详情请移步:http://swiftmailer.org/

 

原文地址:http://blogread.cn/it/article/6649

PHP的性能一直在提高。然而,若是用的不恰当,或是一个不留神,还是可能会踩到PHP内部实现方面的坑的。我在前几天的一个性能问题上就碰到了。

事情是这样子的,一位同事反馈我们的一个接口每次返回需要5秒之久,我们一起review了代码,“惊喜”的发现居然在循环(大约900次)中调用了一个读缓存的操作,而这个缓存的key并没有改变,因此我们把这段代码移到了循环外面,再测,接口返回时间降到了2秒,呜呼!虽然提升了1倍,但明显不是我们能接受的结果!

出现性能问题的代码量并不大,我们排除了IO问题以后,写了一段测试代码,果然问题很快重现。

<?php
$y="1800";
$x = array();
for($j=0;$j<2000;$j++){
        $x[]= "{$j}";
}

for($i=0;$i<3000;$i++){
        if(in_array($y,$x)){
                continue;
        }
}
?>
shell$ time /usr/local/php/bin/php test.php
real0m1.132s
user0m1.118s
sys0m0.015s

对的,我们用的就是字符串型的数字,从缓存拿出来就是这样子的啦!所以这里是特意转成字符串的(如果直接是数字,并不会出现这个问题 ,各位可以自行验证)。可以看出时间耗掉了1秒,才3000次循环,后面的sys用时也注定我们用strace不会拿到什么有效信息。

shell$ strace -ttt -o xxx /usr/local/php/bin/php test.php
shell$ less xxx

1

我们只看到这两次系统调用之间的延时非常大,却并不知道干了什么?一筹莫展了,幸好,Linux下的调试利器除了strace还有ltrace(当然还有dtrace,ptrace,不在本文讨论范围了,略去)。

引用:strace用来 跟踪一个进程的系统调用或信号产生的情况,而 ltrace用来 跟踪进程调用库函数的情况(via IBM developerworks)。

为了排除干扰因素,我们将$x直接赋值为array(“0″,”1″,”2″,……)的形式,避免过多的malloc调用影响结果。执行

shell$ ltrace -c /usr/local/php/bin/php  test.php

如图2

2

我们看到库函数__strtol_internal的调用非常之频繁,达到了94%,太夸张了,然后我又查了一下这个库函数__strtol_internal是干嘛的,原来是strtol的别名,简单的说就是把字符串转换成长整形,可以猜测PHP引擎已经检测到这是一个字符串型的数字,所以期望将他们转换成长整型来比较,这个转换过程中消耗了太多时间,我们再次执行:

shell$ ltrace -e "__strtol_internal" /usr/local/php/bin/php test.php

可以轻松抓到大量下图这样的调用,到此,问题找到了,in_array这种松比较,会将两个字符型数字串先转换为长整型再进行比较,却不知性能就耗在这上面了。

3

知道了症结所在,我们解决的办法就很多了,最简单的就是为in_array加第三个参数为true,即变为严格比较,同时还要比较类型,这样避免了PHP自作聪明的转换类型,跑起来果然快多了,代码如下:

<?php
$y="1800";
$x = array();
for($j=0;$j<2000;$j++){
        $x[]= "{$j}";
}

for($i=0;$i<3000;$i++){
        if(in_array($y,$x,true)){
                continue;
        }
}
?>
shell$ time /usr/local/php/bin/php test.php
real0m0.267s
user0m0.247s
sys0m0.020s

快了好多倍啊!!!可以看到sys耗时几乎没有太大变化。我们再次ltrace一把,还是要把$x直接赋值,排除malloc调用的干扰,因为我们实际应用中是从缓存里一次拉出来的,所以也不存在示例代码中这样的循环来申请内存的情况。
再次执行

shell$ ltrace -c /usr/local/php/bin/php  test.php

如下图:

4

__ctype_tolower_loc占用了最多的时间!查了一下库函数__ctype_tolower_loc是干嘛的:简单的理解是将字符串转换成小写,那么这说明in_array比较字符串不区分大小写吗?其实这个函数调用已经和我们这个in_array感觉联系不大了,关于in_array的实现,还是去看看PHP的源码,大概理解的更为透彻了,好了,没法往下说了,欢迎与我交流,写的不对的地方请多多斧正。

原文地址:http://blogread.cn/it/article/6649

php一个弱类型语言。一个变量,你可以随便为它赋值,而不需要考虑它原来是什么类型。这样简直是太方便,太爽了。

但是,就是因为这个软类型特性, 使得我们要特别注意变量的比较操作结果。

因为以前没有太在意php变量比较规则,昨天在实现功能的时候就掉进坑里面去了。

代码如下:

$needle = '5';
$haystack = array(5,10,15);
if (in_array($needle, $haystack, true)) {
    echo var_export($needle, 1), ' is in array ', var_export($haystack, 1);
} else {
   echo var_export($needle, 1), ' is not in array ', var_export($haystack, 1);
}

我的本意是 可以进入到if 语句块,但是结果却进入了else语句块。因为in_array使用的严格模式,php认为 数字5 和字符串’5′ 是不相等的。虽然他们的值一样,但是他们的类型是不一样的,一个是数字类型,而另一个却是字符类型。 继续阅读

原文地址:http://news.cnblogs.com/n/174418/

英文原文:10 Principles of the PHP Masters

在 WEB 开发世界里,PHP 是最流行的语言之一,从 PHP 里,你能够很容易的找到你所需的脚本,遗憾的是,很少人会去用“最佳做法”去写一个 PHP 程序。这里,我们向大家介绍 PHP 的 10 种最佳实践,当然,每一种都是经过大师们证明而得出的。

1. 在合适的时候使用 PHP – Rasmus Lerdorf

没有谁比 PHP 的创建者 Rasmus Lerdorf 明白 PHP 用在什么地方是更合理的,他于 1995 年发布了 PHP 这门语言,从那时起,PHP 就像燎原之火,烧遍了整个开发阵营,改变了互联网的世界。可是,Rasmus 并不是因此而创建 PHP 的。PHP 是为了解决 WEB 开发者的实际问题而诞生的。

和许多开源项目一样,PHP 变得流行,流行的动机并不能用正常的哲学来进行解释,甚至流行得有些孤芳自赏。它完全可以作为一个案例,一个解决各种 Web 问题的工具需求所引起的案例,因此当 PHP 刚出现的时候,这种工具需求全部聚焦到 PHP 的身上。

但是,你不能奢望 PHP 可以解决所有问题。Lerdorf 是第一个承认 PHP 只是一种工具的人,并且 PHP 也有很多力所不能及的情况。

根据工作的不同来选择合适的工具。我跑了很多家公司,为了说服他们部署和使用 PHP,但是这并不意味着 PHP 对所有问题都适用。它只是可以一个解决大部分问题的 front-end 脚步语言。

作为一个 web 开发者,尝试用 PHP 解决所有问题是不科学的,同时也会浪费你的时间。当 PHP 玩不转的时候,不要犹豫,试用一下其他的语言吧。  继续阅读

2012年最新的12款超棒jQuery插件

47款超酷超实用的CSS3技巧教程

超全超实用的Javascript类库和jQuery插件大全之二:文字处理,表格和列表处理,实用的javascript开发工具

技术人生:向李林锋学习,写文章不过是用更高层次的语言编程

Clojure Web编程 json格式返回

Java学习之IO流上(字符流: FileReader FileWriter BuffereedReader BufferedWriter 字节流:FileInputStream FileOutputStream BufferedInputStream BufferedOutputS) 继续阅读