文章列表
 
您正在查看 "php学习笔记" 分类下的文章

2012/01/10 11:54 P.M.

HDWIKI 版本:5.0

环境:win + php5.2

问题:出现uc_url_unreachable错误

问题所在代码  /api/uc_client/client.php

原因:uc_client代码较久有问题,更新uc_fopen函数为:

function uc_fopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE) {
    $return = '';
    $matches = parse_url($url);
    !isset($matches['host']) && $matches['host'] = '';
    !isset($matches['path']) && $matches['path'] = '';
    !isset($matches['query']) && $matches['query'] = '';
    !isset($matches['port']) && $matches['port'] = '';
    $host = $matches['host'];
    $path = $matches['path'] ? $matches['path'].($matches['query'] ? '?'.$matches['query'] : '') : '/';
    $port = !empty($matches['port']) ? $matches['port'] : 80;
    if($post) {
        $out = "POST $path HTTP/1.0\r\n";
        $out .= "Accept: */*\r\n";
        //$out .= "Referer: $boardurl\r\n";
        $out .= "Accept-Language: zh-cn\r\n";
        $out .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
        $out .= "Host: $host\r\n";
        $out .= 'Content-Length: '.strlen($post)."\r\n";
        $out .= "Connection: Close\r\n";
        $out .= "Cache-Control: no-cache\r\n";
        $out .= "Cookie: $cookie\r\n\r\n";
        $out .= $post;
    } else {
        $out = "GET $path HTTP/1.0\r\n";
        $out .= "Accept: */*\r\n";
        //$out .= "Referer: $boardurl\r\n";
        $out .= "Accept-Language: zh-cn\r\n";
        $out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
        $out .= "Host: $host\r\n";
        $out .= "Connection: Close\r\n";
        $out .= "Cookie: $cookie\r\n\r\n";
    }

    if(function_exists('fsockopen')) {
        $fp = @fsockopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout);
    } elseif (function_exists('pfsockopen')) {
        $fp = @pfsockopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout);
    } else {
        $fp = false;
    }

    if(!$fp) {
        return '';
    } else {
        stream_set_blocking($fp, $block);
        stream_set_timeout($fp, $timeout);
        @fwrite($fp, $out);
        $status = stream_get_meta_data($fp);
        if(!$status['timed_out']) {
            while (!feof($fp)) {
                if(($header = @fgets($fp)) && ($header == "\r\n" ||  $header == "\n")) {
                    break;
                }
            }

            $stop = false;
            while(!feof($fp) && !$stop) {
                $data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit));
                $return .= $data;
                if($limit) {
                    $limit -= strlen($data);
                    $stop = $limit <= 0;
                }
            }
        }
        @fclose($fp);
        return $return;
    }
}

 

 
2009/09/13 11:46 A.M.
静态缓存和动态缓存的比较
1、    静态缓存:是在新内容发布的同时就立刻生成相应内容的静态页面,比如:2003年3月22日,管理员通过后台内容管理界面录入一 篇文章后,就立刻生成http://www.chedong.com/tech/2003/03/22/001.html这个静态页面,并同步更新相关索 引页上的链接。
2、    动态缓存:是在新内容发布以后,并不预先生成相应的静态页面,直到对相应内容发出请求时,如果前台缓存服务器找不到相应缓存,就向后台内容管 理服务器发出请求,后台系统会生成相应内容的静态页面,用户第一次访问页面时可能会慢一点,但是以后就是直接访问缓存了。

注:以上内容来源于:http://www.chedong.com/tech/cache.html


静态缓存因为其复杂的触发更新机制所以比较麻烦,而动态缓存因为其大大减少了设计相关页面更新触发器的需要所以就相对简单一些。
常见的动态缓存设计大概就是这样的:


无论是静态缓存还是动态缓存都有一个命中的问题,命中必然有一个查询的过程,而这个查询就往往是问题所在。攻击者可以发送很多非法的URL,这样在缓存中就无法命中,简单的动态缓存设计中,这时候就要查询数据库了。
很多系统在考虑压力负载时时考虑到缓存可以承载很大的流量的,当这些流量流向数据库时,数据库肯定是不堪重担的。
解决方法也是比较简单的,就是要解决这个命中的问题,如果这个命中过程消耗很小,且不动用数据库,就可以承载一定的流量了。通常在设计静态缓存时,是要把生产的页面放在文件系统中,如果你使用的是nginx的话,能够承载的流量也是很客观的。动态缓存中,我们如果是文章系统,完全可以再添加文章时把文章ID保存在一个存储系统中,命中操作就在这里命中好了,至于存储系统就可以各显神通了。

-----------------------------------------我是美丽的分割线--------------------------------------------------------------
大家有什么好的建议,一起交流啊。
 
2009/08/24 5:12 P.M.
    注:具体使用可查看帮助文档。


Zend Framework框架中 Zend_Db的设计是极为精巧的,不仅极大的减少了编码量,提高了安全性能,而且其基于适配器(Adapter)的设计使你如果有更换数据库的需求几乎不需要怎么修改程序。好处多多呀!好吧我们花点时间研究研究它吧,在这篇文章中暂时不包括Zend_Db_Table的分析(我不是太喜欢它^_^)。


Zend Framework版本:1.9.0

让我们看一下Zend_Db的结构,上图:


一、源码目录
Adapter文件夹下是适配器:我们可以看见里面有 Db2,Mysqli,Oracle,Sqlsrv ,可见Zend Framework是支持这么多数据库,当然你也可以使用Pdo。
Profiler:可以用来debug,分析sql语句执行效率。
Statement:In addition to convenient methods such asfetchAll() andinsert(), you can use a statement object to gain more options for running queries and fetching result sets。就是可以用这个类实现更多的功能方法。

Select.php :专注于select查询的类,用来组装select查询sql语句的。

这些都是最最核心的。

二、结构分析
我们以mysqli为类,看看整个过程.
1、 首先是创建适配器

$db = Zend_Db::factory(' Mysqli ', $params);
在 Zend/Db.php文件的244行:
$adapterName= strtolower($adapterNamespace.'_'.$adapter);
执行完后,$adapterName的值为 zend_db_adapter_mysqli。
在 Zend/Db.php文件的260行:
$dbAdapter=new$adapterName($config);
这就创建了MySQLi的适配器了。

在Zend/Db/Adapter文件夹下,Abstract.php中 Zend_Db_Adapter_Abstract是抽象类,它声明了一些方法并实现了部分方法,Mysqli.php文件中Zend_Db_Adapter_Mysqli类继承Zend_Db_Adapter_Abstract,实现了抽象类中的部分方法,比如 _connect()方法。因为每个数据库的连接方式都有不同,所以就在这里实现了。

2、 构造查询对象,查询数据

在这里我们要做一个select查询。
示例:
    $db = Zend_Db::factory('Mysqli', $params);
$select = $db->select();
$select->from('round_table', '*');
$select->where('noble_title = ?', 'Sir');
$select->order('first_name');
$select->limit(10,20);
$result = $db->fetchAll($select);


首先是要组装出SQL语句,Zend_Db_Select 可以组装出强大的SQL语句,这个类设计的很精巧,不过这里也没法修饰,大家可以看源码。

然后执行Zend_Db_Adapter_Abstract 中的fetchAll()函数,该函数在Zend/Db/Adapter.php的701行:

public function fetchAll($sql, $bind = array(), $fetchMode = null)
{
if ($fetchMode === null) {
$fetchMode = $this->_fetchMode;
}
$stmt = $this->query($sql, $bind);
$result = $stmt->fetchAll($fetchMode);
return $result;
}

$stmt = $this->query($sql, $bind);   会调用自身的445行的public function query($sql,$bind=array())函数。

在这个函数中 如果$sql变量是 Zend_Db_Select 对象的话,就由 Zend_Db_Select 处理,然后返回sql语句。
当然最关键的是要看467行的 $stmt=$this->prepare($sql);
因为Zend_Db_Adapter_Mysqli类继承Zend_Db_Adapter_Abstract,所以这会调用Zend_Db_Adapter_Mysqli中的370行的prepare($sql)函数:
       public function prepare($sql)
{
$this->_connect();
if ($this->_stmt) {
$this->_stmt->close();
}
$stmtClass = $this->_defaultStmtClass;
if (!class_exists($stmtClass)) {
require_once 'Zend/Loader.php';
Zend_Loader::loadClass($stmtClass);
}
$stmt = new $stmtClass($this, $sql);
if ($stmt === false) {
return false;
}
$stmt->setFetchMode($this->_fetchMode);
$this->_stmt = $stmt;
return $stmt;
}


其中:$stmtClass = $this->_defaultStmtClass;
这行代码中$stmtClass = ‘Zend_Db_Statement_Mysqli’;

$stmt = new $stmtClass($this, $sql); $stmt就是一个 Zend_Db_Statement_Mysqli对象了。

回到fetchAll()函数,这里该执行 $result=$stmt->fetchAll($fetchMode); 代码了,当然这里fetchAll()函数就是Zend_Db_Statement_Mysqli中的函数了。

好了,返回结果。


这篇文章分析的很粗浅,具体的大家可以阅读源码,会有很大收获的。
 
2009/07/15 10:53 A.M.
如果你是使用的Linux系统,并对性能有一定要求请看这里

         该客户端是用php写的,因为php的 php-mogilefs 模块只能在Linux下使用,所以为方便开发测试,我参考 mediawiki代码库改造了一个php语言的客户端,如下:

        
注:此代码性能较低,只做开发测试用。

文件: mogilefs.php

<?php
/**
* 该类用于分布式文件系统mogilefs相关处理
*/
class MogilefsPhpClient {
   
    /**
    * 对象
    */
    public $socket;
    /**
    * 配置
    */
    public $config;
    /**
    * domain
    *
    * @var unknown_type
    */
    public $domain;
   
    /**
    * 错误消息
    */
    public $error;
    /**
    * 构造函数,返回对象
    * @author lengfeng
    * @return bool
    */
    public function __construct($type) {
        /*加载配置文件*/
        require_once ('mogilefs_config.php');
        $this->config = $mogilefs_config [$type];
        $this->connect ();
    }
    /**
    * 连接
    * @return bool
    */
    private function connect() {
        //连接多个traker
        foreach ( $this->config as $value ) {
            $host = $value ['MOGILEFS_HOST']; //traker 地址
            $port = $value ['MOGILEFS_PORT']; //port
            $domain = $value ['MOGILEFS_DOMAIN']; //domain
           

            $this->domain = $domain;
            $this->hosts = $host;
           
            $this->socket = fsockopen ( $host, $port );
            if ($this->socket) {
                break;
            }
        }
        return $this->socket;
    }
    /**
    * Send a request to mogilefsd and parse the result.
    * @private
    */
    private function doRequest($cmd, $args = array()) {
        $params = ' domain=' . urlencode ( $this->domain );
        foreach ( $args as $key => $value )
            $params .= '&' . urlencode ( $key ) . "=" . urlencode ( $value );
       
        if (! $this->socket) {
            $this->connect ();
        }
        fwrite ( $this->socket, $cmd . $params . "\n" );
        $line = fgets ( $this->socket );
        $words = explode ( ' ', $line );
        if ($words [0] == 'OK') {
            parse_str ( trim ( $words [1] ), $result );
        } else {
            $result = false;
            $this->error = join ( " ", $words );
        }
        return $result;
    }
    /**
    * Get an array of paths
    */
    public function getPaths($key) {
        $res = $this->doRequest ( "GET_PATHS", array ("key" => $key ) );
        unset ( $res ['paths'] );
        return $res;
    }
   
    /**
    * 插入文件
    * @var string $file 文件路径或文件内容
    * @var string $key    文件key
    * @var bool   $type 类型,false=>数据流 ,true=>文件路径
    * @var string $class class
    * @return bool
    *
    */
    public function put($filename, $key, $class = null, $type = true) {
       
        if (empty ( $class ))
            $class = $this->config [0] ['MOGILEFS_CLASS']; //class
       

        $res = $this->doRequest ( "CREATE_OPEN", array ("key" => $key, "class" => $class ) );
       
        if (! $res)
            return false;
       
        if (preg_match ( '/^http:\/\/([a-z0-9.-]*):([0-9]*)\/(.*)$/', $res ['path'], $matches )) {
            $host = $matches [1];
            $port = $matches [2];
            $path = $matches [3];
           
            // $fout = fopen( $res['path'], 'w' );
            $fin = fopen ( $filename, 'r' );
            $ch = curl_init ();
            curl_setopt ( $ch, CURLOPT_PUT, 1 );
            curl_setopt ( $ch, CURLOPT_URL, $res ['path'] );
            curl_setopt ( $ch, CURLOPT_VERBOSE, 0 );
            curl_setopt ( $ch, CURLOPT_INFILE, $fin );
            curl_setopt ( $ch, CURLOPT_INFILESIZE, filesize ( $filename ) );
            curl_setopt ( $ch, CURLOPT_TIMEOUT, 4 );
            curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
            if (! curl_exec ( $ch )) {
                $this->error = curl_error ( $ch );
                curl_close ( $ch );
                return false;
            }
            curl_close ( $ch );
           
            $closeres = $this->doRequest ( "CREATE_CLOSE", array ("key" => $key, "class" => $class, "devid" => $res ['devid'], "fid" => $res ['fid'], "path" => urldecode ( $res ['path'] ) ) );
            if ($closeres === false) {
                return false;
            } else {
                return true;
            }
        }
    }
   
    /**
    * 读取文件内容
    * @var string $key    文件key
    * @return bool
    */
    public function getContent($key) {
        $paths = $this->getPaths ( $key );
        if ($paths == false)
            return false;
        foreach ( $paths as $path ) {
            $fh = fopen ( $path, 'r' );
            $contents = '';
           
            if ($fh) {
                while ( ! feof ( $fh ) ) {
                    $contents .= fread ( $fh, 8192 );
                }
                fclose ( $fh );
                return $contents;
            }
        }
        return false;
    }
    /**
    * 删除文件
    * @var string $key    文件key
    * @return bool
    */
    public function del($key) {
        $res = $this->doRequest ( "DELETE", array ("key" => $key ) );
        if ($res === false)
            return false;
        return true;
    }
    /**
    * 重命名
    * @var string $from    文件旧key
    * @var string $to      文件新key
    * @return bool
    */
    public function rename($from, $to) {
        $res = $this->doRequest ( "RENAME", array ("from_key" => $from, "to_key" => $to ) );
        if ($res === false)
            return false;
        return true;
    }
    /**
    * getClient
    * @return object
    */
    public function getClient() {
        return $this->socket;
    }
    /**
    * getDomains
    * @return array
    */
    public function getDomains() {
        $res = $this->doRequest ( 'GET_DOMAINS' );
        if (! $res) {
            return false;
        }
        $domains = array ();
        for($i = 1; $i <= $res ['domains']; $i ++) {
            $dom = 'domain' . $i;
            $classes = array ();
            for($j = 1; $j <= $res [$dom . 'classes']; $j ++) {
                $classes [$res [$dom . 'class' . $j . 'name']] = $res [$dom . 'class' . $j . 'mindevcount'];
            }
            $domains [] = array ('name' => $res [$dom], 'classes' => $classes );
        }
        return $domains;
    }
}

配置文件:mogilefs_config.php

$mogilefs_config = array(
    'test' =>array(
        array(
            'MOGILEFS_HOST' =>ip,
            'MOGILEFS_PORT' =>6001,
            'MOGILEFS_DOMAIN'=>'test_domain',   
            'MOGILEFS_CLASS' =>'test_class',
            'MOGILEFS_DEVICE_COUNT'=>1
            )
    )
);

大家如果把这个类改造的性能更好的话,不要忘记告诉我啊
 
2009/06/04 8:06 P.M.
        我的数据都是用UTF-8编码的,发送邮件时,邮件主体内容可以正确发送,但邮件的标题却不可以发送,查阅了相关资料原来是邮件标头必须是纯粹的ASCII的编码。许多邮件传输代理会丢弃ASCII范围之外的字符。

         但好在标头可以包括一些在RFC 1342 上的定义为编码字。可以用base64编码(昨天上课刚学的,哈哈)。这个编码可以用个函数来实现:


/**
* 将邮件标题格式改为RFC 1342 定义的编码
*
* @param unknown_type $text
* @return unknown
*/
function email_escape($text) {
    if (preg_match ( '/[^a-z ]/i', $text )) {
        $text = preg_replace ( '/([^a-z ])/ie', 'sprintf("=%02x",
       ord(StripSlashes("\\1")))', $text );
        $text = str_replace ( ' ', '_', $text );
        return "=?utf-8?Q?$text?=";
    }
    return $text;
}


注:RFC1324称任何单独的便那起长度最长不得超过75个字符。

后记:这个函数是我在《构建可扩展的web站点》上查到的,这本书很不错,强烈推荐。
 
   
 
 
文章存档
 
     
 
最新文章评论
  

回复leilei0091:这些年一直用git了,没有用svn了
 

我也想知道为什么 你好几年前的问题了
 

今天打开webalizer已经不是乱码了,是不是rm usr/share/locale/zh/LC_MESSAGES/webal
 

回复zcmsgk:这个文件就在usr/share/locale/zh/LC_MESSAGES/webalizer.mo,但是删除
 

回复莫贻敏:Centos 下加EPEL源,然后用yum安装
   
帮助中心 | 空间客服 | 投诉中心 | 空间协议
©2012 Baidu