正在查看: 标记有标签 php 的文章(第 1 页 / 共 12 篇)

不用持久化Mysql连接(Persistent Connection)的几种情况

一直对PHP提供的持久化连接(Persistent Connection)的使用将信将疑,今天算是彻底做了个research,对其使用和应用场景清晰了很多,特此记录。

今天在CI论坛上有个帖子讨论PHP连接数据库时持久化链接的问题,我在这里做个总结 (就在写这篇文章的时候发现已经有人总结的很好了,于是直接转帖过来,没有必要重复劳动)。

以下内容来自PHP官方站点关于persistent connection的评论

不使用持久化数据库连接的诸多理由和场景:

* When you lock a table, normally it is unlocked when the connection closes, but since persistent connections do not close, any tables you accidentally leave locked will remain locked, and the only way to unlock them is to wait for the connection to timeout or kill the process. The same locking problem occurs with transactions. (See comments below on 23-Apr-2002 & 12-Jul-2003)

* Normally temporary tables are dropped when the connection closes, but since persistent connections do not close, temporary tables aren't so temporary. If you do not explicitly drop temporary tables when you are done, that table will already exist for a new client reusing the same connection. The same problem occurs with setting session variables. (See comments below on 19-Nov-2004 & 07-Aug-2006)

* If PHP and MySQL are on the same server or local network, the connection time may be negligible, in which case there is no advantage to persistent connections.

* Apache does not work well with persistent connections. When it receives a request from a new client, instead of using one of the available children which already has a persistent connection open, it tends to spawn a new child, which must then open a new database connection. This causes excess processes which are just sleeping, wasting resources, and causing errors when you reach your maximum connections, plus it defeats any benefit of persistent connections. (See comments below on 03-Feb-2004, and the footnote at http://devzone.zend.com/node/view/id/686#fn1)

参考:

Persistent Database Connections (PHP.net)

mysql_pconnect (PHP手册)

使用PHP和Python查找100以内的所有质数

质数(Prime Numbers)就是只能被1和它本身整出的自然数。本文描述查找100以内质数的算法分别在PHP和Python中的实现,仅作记录。

PHP版查找100以内的所有质数:

<?php
//script by Saturn @ cnsaturn.com
for($i=2; $i< 100; $i++)
{
  //$count is used to check whether or not the internal loop is exhausted 
  $count = 0;

  for($j = 2; $j < $i; $j++)
  {
    if($i % $j == 0)
    {
      $count ++; 
      echo "$i = $j * " . $i/$j .".\n";
      break;
    }
  }
        
  if($count == 0)
  {
    echo "$i is a prime number. \n";
  }
}

Python版(via)查找100以内的所有质数:

for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print n, 'equals', x, '*', n/x
            break
    else:
       # loop fell through without finding a factor
       print n, 'is a prime number'

可以看到虽然两种语言对质数查找的实现都比较简单,但相比PHP而言,Python更简洁,语义化更明显。

在PHP中数组进行二分法查找

二分法查找(Binary Search)是一种搜索算法(平均的时间复杂度为O(log n)),支持对一个有序列表中的某个元素进行快速查找。更多二分法查找的解释和例子可以参考维基百科的说明

这里我只写出其在PHP中的算法实现,仅作记录。如果你有更好的实现方法,请在下方留言与我交流。

//script by Saturn from cnsaturn.com

function binarySearch($searchArray, $targetValue)
{
    //初始范围为全部数组
    $startIndex = 0;
    $endIndex = count($searchArray) - 1;
    //初始中间位置的元素索引
    $middle = round(($endIndex - $startIndex) / 2);
 
    //如果要搜索的元素在初始开始位置,则直接返回
    if($targetValue == $searchArray[$startIndex])
    {
       return $startIndex;
     }
 
    //如果要搜索的元素在初始结束位置,则直接返回
    if($targetValue == $searchArray[$endIndex])
    {
       return $endIndex;
    }
 
    //循环查找
    while($searchArray[$middle] !== $targetValue && $startIndex < $endIndex)
    {
       //调整搜索起止范围
       if($searchArray[$middle] > $targetValue)
       {
          $endIndex = $middle;
       }
       else if($searchArray[$middle] < $targetValue)
       {
          $startIndex = $middle;
       }
  
      //调整中间位置元素的索引,注意获得索引值的方法
      $middle = round(($endIndex - $startIndex) /2) + $startIndex;   
   }
 
   //返回目标值的索引,如果未找到则返回-1
   return ($searchArray[$middle] == $targetValue) ? $middle : -1;
}

创建一个数组和一个目标值来测试上述查找算法:

$array = array(1,2,3,4,5,6,7,8);

//echo 4;
echo binarySearch($array, 5);

Hello, Stblog

时间过的真快,来墨尔本已经一年多了,而距离我写的上一篇日志也有半年多了。这段时间感悟很多,有一堆东西想写下来,不过还是手懒了。

目前你所看到的这段文字,来自我和CI中国其他几位成员目前正在开发的基于Codeigniter (PHP MVC框架)开发的一套博客程序——Stblog,目前的最新版为 v0.1.2。写这套程序的原因,我写在了这里,就不转载过来了。

正在学习PHP和Codeigniter的朋友,我推荐你们下载和试用这套程序,但目前暂不推荐使用在真实的环境当中,因为它有诸多地方需要完善。待程序和相关文档成熟之后,在使用也不迟。

Stblog开发相关动态:

项目主页:http://code.google.com/p/stblog/

程序下载:http://code.google.com/p/stblog/downloads/list

Bug提交:http://code.google.com/p/stblog/issues/list

安装方法/插件/主题开发教程:http://code.google.com/p/stblog/w/list

注意:STBlog的协作开发和版本控制工具为Git (没有使用SVN),目前被托管在Github.com。请移步 http://github.com/stblog/Stblog  了解最新开发动态,以及checkout最新开发版本。

PHP中插件机制的一种实现方案

这篇文章的出发点是我对插件机制的理解,及其在PHP中的实现。这套插件机制已经在你目前看到的这个博客程序中的重构代码中实现(我定名为STBlog),由于尚未开发完毕,所以目前暂不开发源代码。但文章会涉及到核心思想和部分实现代码。

插件,亦即Plug-in,是指一类特定的功能模块(通常由第三方开发者实现),它的特点是:当你需要它的时候激活它,不需要它的时候禁用/删除它;且无论是激活还是禁用都不影响系统核心模块的运行,也就是说插件是一种非侵入式的模块化设计,实现了核心程序与插件程序的松散耦合。一个典型的例子就是Wordpress中众多的第三方插件,比如Akimet插件用于对用户的评论进行Spam过滤。

一个健壮的插件机制,我认为必须具备以下特点:

  • 插件的动态监听和加载(Lookup)
  • 插件的动态触发
  • 以上两点的实现均不影响核心程序的运行

要在程序中实现插件,我们首先应该想到的就是定义不同的钩子(Hooks);“钩子”是一个很形象的逻辑概念,你可以认为它是系统预留的插件触发条件。它的逻辑原理如下:当系统执行到某个钩子时,会判断这个钩子的条件是否满足;如果满足,会转而先去调用钩子所制定的功能,然后返回继续执行余下的程序;如果不满足,跳过即可。这有点像汇编中的“中断保护”逻辑。

某些钩子可能是系统事先就设计好的,比如之前我举的关于评论Spam过滤的钩子,通常它已经由核心系统开发人员设计进了评论的处理逻辑中;另外一类钩子则可能是由用户自行定制的(由第三方开发人员制定),通常存在于表现层,比如一个普通的PHP表单显示页面中。

可能你感觉上面的话比较无聊,让人昏昏欲睡;但是要看懂下面我写的代码,理解以上的原理是必不可少的。

下面进行PHP中插件机制的核心实现,整个机制核心分为三大块:

  • 一个插件经理类:这是核心之核心。它是一个应用程序全局Global对象。它主要有三个职责:
    • 负责监听已经注册了的所有插件,并实例化这些插件对象。
    • 负责注册所有插件。
    • 当钩子条件满足时,触发对应的对象方法。
  • 插件的功能实现:这大多由第三方开发人员完成,但需要遵循一定的规则,这个规则是插件机制所规定的,因插件机制的不同而不同,下面的显示代码你会看到这个规则。
  • 插件的触发:也就是钩子的触发条件。具体来说这是一小段代码,放置在你需要插件实现的地方,用于触发这个钩子。

原理讲了一大堆,下面看看我的实现方案:

»阅读全文

Tags: php,stblog,插件

使用PHP/gzip压缩网站JS/CSS文档的实例

一些泛WEB 2.0网站为了追求用户体验,可能会大量使用CSS和JS文件。这就导致在服务器带宽一定的情况下,多用户并发访问速度变慢。如何加快网页响应速度?解决办法之一就是:依照Yahoo性能优化小组提出的N条性能优化建议对前端程序进行优化和重构,关于此文的讨论很多,在这里不再赘述。

这篇文章主要分享一下我个人在实际项目中,对于使用PHP对JS和CSS进行压缩的经验,在这里假设服务器仅支持GZIP压缩,不支持.htaccess(符合很多站长的租用的虚拟主机实际情况)。

首先说说对CSS和JS文件进行性能优化的几个小技巧:

  • 将多个CSS/JS文档合并成一个文件,以减少HTTP请求
  • 对合并后的文件进行文档压缩,比如分别使用js compressorCSS compress
  • 如果使用到一些主流的JavaScript框架,比如JQuery, Mootools或者YUI,强烈推荐直接使用Google AJAX Library以外部链接的形式导入基库。
  • 最后,就是本文所提到的,使用GZIP在服务器端对JS/CSS文档进行压缩。

这里提到的方法对系统来说是无侵入式的,也就是说不管你的程序是新编写的,还是已经上线了很久,均适用。

»阅读全文

Tags: php,gzip

PHP设计模式:Singleton单例模式

此文承接之前我在PHP中实现简单工厂抽象工厂的讨论,讨论一个广泛应用在OOP体系中的设计模式——Singleton模式。

Singleton Pattern(中文称单例模式),可以说是最容易理解的设计模式了,也充分体现了DRY (Don't Repeat Yourself)的思想。它的核心思想是:保证一个对象存在且仅允许存在一个实例,并提供一个全局访问方式[via]。

单例模式的运作模型是:当对象第一次被请求时,创建这个对象的实例;之后的每次请求,仅传递已创建实例的句柄。与单例模式相对应的模式叫做Prototype(Java平台下)或者叫SingleCall(.NET平台下),在此种模式下,每次请求一个对象,都将新建一个实例。

在WEB程序中应用单例模式的一个典型例子是数据库连接的创建:通过数据库句柄来连接数据库这一行为是独占的。换言之,在一个句柄尚未关闭之前,你无法第二次创建一个相同名称的句柄。然后在日常编码中,假设你希望在同一页面中操作由数据库传递回来的多组数据。此时如果采用传统的Prototype方式编程,为了程序的安全运行,你可能需要创建多个数据库链接句柄或者重复进行打开/关闭数据库连接的操作。显然,这样的操作会导致程序过度消耗一些不必要的资源。

在此场景下,我们可以运用单例模式来维护和共享同一个数据库句柄。优点有二:

1、提高了程序运行上的安全性。你不必过多的担心和考虑诸如数据库打开/关闭的问题。

2、避免了因创建多个连接导致的不必要资源浪费。垃圾回收机制仅需要对一个链接句柄进行操作。

当然,以上两个问题对于PHP来说并不是问题,PHP的垃圾回收机制就是,当一个页面执行完毕会自动清空所有资源和内存,这里面就包括数据库连接。

至此,可以总结出Singleton单例模式在WEB程序中的运用场合:

1、某些资源本身具有独占性,你不希望在多个地方重复创建对这个独占资源对象的实例。

2、你需要在一个对象的多个实例之间共享这个对象的状态(下面我会将此条规则进行代码举例)。

下面写一段小代码来演示PHP 5中Singleton的实现:

/***************************************************************************
 *              Singleton在PHP5中的实现
 *             
 *   @Author  :    Saturn
 *   @Contact: http://www.cnsaturn.com/
 ***************************************************************************/
class Singleton
{
 //此成员变量用来记录此对象的引用次数
 private $counter = 1;
 //注意这里是private,即禁止外部程序通过解析函数实例化对象
 private function __construct()
 { }
 //禁止克隆这个对象
 private function __clone() 
 { }
 //必须通过此方法得到对象的引用
 public static function getInstance()
 {
  static $instance = null;
  if($instance == null)
  {
   $instance = new Singleton();
  }
  return $instance;
 }
 
 public function getUsedCount()
 {
  return $this->counter++;
 }
 
}
//test test
echo Singleton::getInstance()->getUsedCount();//echo 1
echo Singleton::getInstance()->getUsedCount();//echo 2
echo Singleton::getInstance()->getUsedCount();//echo 3
$obj = new Singleton();//trigger fatal error
?>

此程序演示的是如何通过Singleton模式让多个引用能够同时共享此对象的某个状态,在这里是共享$counter。

注意,我们将解析函数的Scope设置成了private,这样做为了禁止通过解析函数实例化对象,而必须使用对象提供的静态化方法getInstance来获取对象的引用。

这个例子比较简单,但已经初步展示了单例模式的核心思想,仅起抛砖引玉的作用。

PHP设计模式:工厂模式之抽象工厂

上一篇中,我主要记录了工厂模式之一的简单工厂在PHP中的实现,这篇文章主要总结工厂模式的另一种形态:抽象工厂。

简单工厂中,工厂的角色是负责实例化具体对象,而在实际应用中这种情况却不很实用,主要原因是如果我们希望增加或去除这个工厂所能实例化的某个对象,则需要对工厂类进行直接修改,这显然违背了低耦合的宗旨。对于上一篇文章的例子来说,那就是:如果我们需要添加那个汽车工厂所能生成的汽车品牌,则需要修改工厂类的判断逻辑。

如何尽可能的降低耦合,从而达到非侵入式的设计逻辑?这里的非侵入式一次,是我从Spring中借用过来的概念,通俗来讲,就是去除和添加某个工厂的产品对象不影响整个程序的架构。

由此就引入了抽象工厂的思想。抽象工厂将面向接口编程的思想演绎的淋漓尽致,它的核心思想是:抽象工厂仅提供一个产品簇(同一类别的所有对象的接口抽象)的通用接口,而将实例化对象的任务交给遵循其标准的具体工厂来完成;具体工厂还可能生产出多个产品,此时还需要对产品定义一个接口,供具体工厂来生产具体产品。

举个例子,还是关于生产汽车的。汽车工厂经过一段时间的努力,现在已经发展装大了,于是做了两个决定:第一个决定是将生产汽车的过程分拆成两个阶段,分别是生成轮胎和除去轮胎的其他部分。另一个决定是,决定为每个汽车品牌单独建立一个汽车工厂。那么如何管理这些工厂,使他们既遵循第一个决定,又不相互干扰?解决办法就是:汽车总厂提供生产汽车的通用流程(第二条),这个流程两个子工厂都需要严格执行。同时,将具体生产的过程交给两个具体工厂,分别是Benz工厂和Audi工厂。这就是抽象工厂的设计思想的概念。

»阅读全文

PHP设计模式:工厂模式之简单工厂

要写出漂亮的代码,掌握一些常用的设计模式是很有必要的。这篇文章只是我将设计模式应用在OO PHP的系列学习(之前一直是在JAVA里面)笔记之一,如有不妥,就留言一起探讨。

根据设计模式的圣经GoF所写的Design Patterns: Elements of Reusable Object-Oriented Software一书的分类,工厂模式被归类在创建模式(Creational Pattern)之下。工厂模式作为一种创建模式,主要用于处理对象的创建,以适合不同场景[via]。

工厂模式又分为抽象工厂模式和工厂方法模式。

本文所讨论的简单工厂,又称作静态工厂方法,可以看作是工厂方法的一个特例。个人认为它是学习工厂模式最好的切入点。

工厂模式,正如其名,我们在实例化一个对象时,不是直接实例化具体的对象,而是通过工厂这个接口来实现。通俗的说,作为消费者(某个对象A),我们在需要消费(调用)某个具体产品(其他对象B)时,不需要了解这个产品(对象B)的制作过程(实现过程),只需要直接拿这个产品来用即可。而具体的这个产品的生成(对象的实例化)过程,由工厂实现。

可见,工厂模式可以在降低对象间的关联(耦合度降低),并能够隐藏具体产品的实现过程。因为整个调用过程是面向接口的。

»阅读全文

使用PHP编程获取Page Rank (PR)值

衡量一个网站和某个网页权重的两个非常重要的指标,分别是:Google Page Rank (简称PR值)和Alexa排名。虽然它们不是衡量一个网站好坏的绝对标准,但可以从一定程度上说明网站的受欢迎程度,访问流量等基本信息。

与Alexa提供第三方开发者API接口不同,Google本身并不提供API接口让程序员编写查询程序,所以要直截了当的从官方获取一个网站的PR值,唯一的方法可能就是Google工具条了。

现在问题来了,像我们经常查PR值的ChinaZ,123Cha这样的第三方网站的PR信息是从哪获取的?莫非他们与Google有“一腿”,Google单独为他们提供了接口?

事实上没那么神秘。正所谓“魔高一尺,道高一丈”,既然Google Toolbar提供PR值的显示,那么就从工具条上入手吧。事实上,很多先行者很早之前就已经为我们找到了关于这个问题的解决方案。

这个Page Rank Code网站提供的代码就是非常典型的通过破解Google工具栏获取PR值的一例。这个网站上已经提供了很详细的PHP执行PR值查询的函数以及具体使用办法,我这里就不贴了。

具体源代码和演示代码请点击这里查看。

需要特别注意的是:作者在下载页面中特别指出,某些服务器IP(比如我现在博客所在的服务器)如果被Google封掉的话,是查不到正确的PR值的

讲到这里,上面那个问题就自然而然的解决了,第三方查询PR值的核心思想都是破解Google工具条,可能区别就在平台和语言不同罢了。