PHP分类的最新日记
1. 字符串匹配算法简介
参见《 字符串匹配算法研究 》 http://www.yuanma.org/data/2008/0806/article_3128.htm
摘要:随着互联网的日渐庞大,信息也是越来越多,如何在海量的信息中快速查找自己所要的信息是网络搜索研究的热点所在,在这其中,字符串匹配算法起着非常重要的作用,一个高效的字符串匹配算法,可以极大的提高搜索的效率和质量,本文力图阐明字符串匹配算法的发展过程,并介绍了各个算法的特点,并给予了适当的比较和分析。
2. Horspool算法
算法详细解释参考《算法设计与分析基础》第二版195页
这个算法的关键之处是对模式进行预处理,计算模式中每个字符到模式字符串尾的距离。
PHP代码实现如下:
$string = 'afeovfpop';
$pattern = 'vfp';
function shiftTable($pattern){
$length = strlen($pattern);
$table = array();
for($j=0;$j<$length;$j++){
$key = $pattern[$j];
$table[$key] = $length-1-$j;
if($j>$length-2){
$table[$key] = $length;
}
}
return $table;
}function Horspool($string, $pattern){
$table = shiftTable($pattern);
// print_r($table);
$m = strlen($pattern);
$i = $m - 1;
$n = strlen($string);
while($i<=$n-1){
$k=0;
while(($k<=$m-1)&&($pattern[$m-1-$k]==$string[$i-$k])){
$k = $k+1;
}
if($k==$m){
return $i-$m+1;
}else{
$key = $pattern[$k];
$i=$i+$table[$key];
}
}
return 0;
}
echo Horspool($string,$pattern);
echo strpos($string,$pattern);
使用phpDocumentor的好处:
你喜歡寫文件嗎?我不喜歡。尤其是在趕工的時候,哪來的美國時間寫文件;就算有時間也是希望趕快把事情做完閃人,怎樣都輪不到寫文件的時候。
文件需要嗎?雖然不喜歡寫文件,但文件真的是必要的。對自己而言,正當在趕案子兵荒馬亂的時候,突然要某個以前寫過的函式結果不知道放哪去了,這時心情會很糟很糟的去把以前的碼挖出來一份一份看,才能找出所要的函式,這樣更浪費時間。對於他人而言,要是每個人寫出來的東西都可以再讓其它人了解,並且進一步使用其它人早已寫好的元件,可以讓我們再省下時間來多喝幾杯咖啡。
那要怎麼樣讓編寫文件輕鬆又自在? phpDocumentor 就是一個現成好用的工具,只要在寫程式時順手寫上一點點的註解,困難一點的可以再加上一點點的範例。寫完後交給 phpDocumentor 編譯,一下子圖文並茂的程式文件自動就產生了。而且它還不只可以產生 HTML 檔,還可以產生出 PDF, CHM 等文件。就算產生 HTML 檔,還有許多的風格可以選擇。這樣好用的工具放著不用,實在太可惜了。
這份資料裡,只會出現馬上能用的資料,除了這個簡介外,不會廢話太多,所以文件中的文句也冰冷了些。會這樣做的目的是希望文件的每一個部份都能讓讀者快速吸收,任何一個例子複製下來後馬上能用。文件中的每個樣版我都是精心設計過,起碼我以後要用的時候不必再想說要寫一個類別正常需要哪些 Tag ,只要把樣版複製下來以後就直接可以用了。
由於此文件中資料只有使用上最需要的部份(也是一定能用的部份),因此若在使用上想要了解更多,可以到 phpDocumentor 的官方網站 (http://www.phpdoc.org/)上找到所需資料。
——————摘自 《phpDocumentor筆記 0 立即體驗》
http://pkwbim-programming-note.blogspot.com/2008/01/phpdocumentor-0.html#0.4
其实这篇文章已经写的比较简要,但是为了防止哪天这个网站被盾了,我还是抄到自己的blog比较安全。
简而言之,phpDocumentor就适合我这样写过代码就忘了的人,规范的书写注释还能生成文档,多省事。
1.安装
1.1如果没有安装过pear,可以先运行PHP目录下的go-pear.bat安装。
1.2安装过pear之后,使用下面的命令安装phpDocumentor:
\php5\PEAR\pear install -o PhpDocumentor
2.字符编码的问题
看到很多人都说需要改字符编码,但是我下载的phpDocumentor v1.4.2 没有遇到这个问题,也没有
查找到"iso-8859-1"这个字符串。
3.生成文件
步驟
3.1 将範例碼存成 example.php 置於 \project\php_project\下。
3.2 在命令列下用以下指令
phpdoc --parseprivate -o HTML:frames:earthli -f \project\php_project\example.php -t \project\php_project\docs
或
phpdoc --parseprivate -o HTML:Smarty:PHP -d \project\php_project\ -t \project\php_project\docs
3.3 解說
* --parseprivate: 是將私有 (private) 成員函式或私有變數等等也都加入程式文件裡。沒有這參數的話,產生出的文件裡只會有公開的 (public) 和受保護的 (protected) 的成員函式和變數。
* -f : 是指針對某個檔案產生註解文件。
* -d : 針對某個目錄(含其子目錄)產生註解文件。
* -t : 指定要輸出的目錄
* -o : 指定輸出格式,上例的格式有兩種
o HTML:frames:earthli : 是輸出有一種帶有框架 (frame) 的說明文件,所產生出來的文件非常漂亮。Zend Framework 的 API 文件就是採用這種風格。
o HTML:Smarty:PHP : 產生的文件看起來就像是 PHP 網站上或是 phpDocumentor 官網上的的一樣。
待程式結束後,瀏覽剛剛指定產生文件的目錄下,會有一個 index.html 檔,以瀏覽器打開它就可以看到 phpDocumentor 產生出來的程式文件。倘若在產生文件的過程中,有任何的錯誤,這些錯誤會出現在 error.html檔裡。
4.范例
<?php
/**
* phpDocumentor 使用示範
* 這個檔案是一個簡單的示範
* 內容涵蓋了許多常用的註解方式。
* 有任何的問題請和作者連絡
* @package phpDocumentorExample
* @author 多采多姿 <pkwbim.programming@gmail.com>
* @version 0.1b
*/
/**
* 這是 lib.inc.php 的標題
* 這是 lib.inc.php 的描述
*/
include_once('lib.inc.php');
/**
* 圓周率
* 圓周和直徑的比值
*/
define('pi', 3.14159);
/**
* 這是 funtion1 的註解區塊標題
* 這是 funtion1 的描述
* @global int 這是函式內第一個全域變數的註解,就是 $global1 的註解
* @global string 這是函式內第二個全域變數的註解,就是 $global2 的註解
* @param bool $arg1 這是函式參數 $arg1 的註解
* @param int|string $arg2 這裡是函式參數 $arg2 的註解
* @return mixed 傳回值的註解
*/
function function1($arg1, $arg2) {
global $global1, $global2;
return array($arg1, $arg2);
}
/**
* 這是MyClass的標題
*
* 建立簡寫型的清單
* 這裡建立一份無序清單
* - 項目一
* - 項目二,
* 每個項目可以是多行,
* 就像這個項目,
* 這行還在項目二中
* - 項目三
* 清單結束,因為沒縮排
* 這裡建立一份有序清單
* 1 有序的項目一,數字後一定要加一個空白。
* 2 有序的項目二
* 有序清單的另一種寫法
* 1. ordered item 1
* 2. ordered item 2
* 清單在此結束
*
* @package phpDocumentorExample
* @author 多采多姿
* @since 1.0rc1
* @version 0.2b
*
*/
class MyClass {
/**
* 這裡是成員變數的註解
*
* @var string 成員變數的註解
* @access private
*/
private $_variable = "Hello";
/**
* 這是一個公開的成員函式
*
* @param bool $var1 參數1
* @param string|array $var2 參數1
* @return void
* @access public
*/
public function set_vars($var1, $var2) {
}
}
?>
要注意所有的注释都是有两个星号的C-style注释,如下所示
/**
*
*/
语法参考文档: http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_phpDocumentor.quickstart.pkg.html#coding
1.执行查询并返回结果
跳过废话
1.1 使用
Zend_Db_Adapter一旦你得到了一个
Zend_Db_Adapter 实例, 你可以直接
执行sql语句进行查询. Zend_Db_Adapter 传送这些sql语
句到底层的PDO对象,由PDO对象组合并执行他们,在有查询结果的情况
下,返回一个PDOStatement对象以便对结果进行处理。<?php
// 创建一个$db对象,然后查询数据库
// 使用完整的sql语句直接进行查询.
$sql = $db->quoteInto(
'SELECT * FROM example WHERE date > ?',
'2006-01-01'
);
$result = $db->query($sql);
// 使用PDOStatement对象$result将所有结果数据放到一个数组中
$rows = $result->fetchAll();
?>
或者使用fetch开头系列方法获得结果集:
对于每一种 fetch系列 的方法来说,你需
要传送一个select的sql语句;假如你在操作语句中使用指定的占位符,你也可以
传送一个绑定数据的数组对你的操作语句进行处理和替换。 Fetch系列
的方法包括:
fetchAll()fetchAssoc()fetchCol()fetchOne()fetchPairs()fetchRow()
<?php
// 创建一个 $db对象, 然后...
// 取回结果集中所有字段的值,作为连续数组返回
$result = $db->fetchAll(
"SELECT * FROM round_table WHERE noble_title = :title",
array('title' => 'Sir')
);
// 取回结果集中所有字段的值,作为关联数组返回
// 第一个字段作为码
$result = $db->fetchAssoc(
"SELECT * FROM round_table WHERE noble_title = :title",
array('title' => 'Sir')
);
// 取回所有结果行的第一个字段名
$result = $db->fetchCol(
"SELECT first_name FROM round_table WHERE noble_title = :title",
array('title' => 'Sir')
);
// 只取回第一个字段值
$result = $db->fetchOne(
"SELECT COUNT(*) FROM round_table WHERE noble_title = :title",
array('title' => 'Sir')
);
// 取回一个相关数组,第一个字段值为码
// 第二个字段为值
$result = $db->fetchPairs(
"SELECT first_name, favorite_color FROM round_table WHERE noble_title = :title",
array('title' => 'Sir')
);
// 只取回结果集的第一行
$result = $db->fetchRow(
"SELECT * FROM round_table WHERE first_name = :name",
array('name' => 'Lancelot')
);
?>
使用Zend_Db_Select方法是一种不受数据库约束构建select的sql语句的工具 (ares注:用户可以使用该方法生成查询的sql语句,而不需要考虑各种数据 库sql语句的差别)。虽然该方法明显还不完善,但是的确为我们提供一种方 法,帮助我们在不同的后台数据库进行相同的查询工作。除此之外,它还可 以避免sql语句攻击。
创建一个zend_db_select实例最简单的方法就是使用zend_db_adapter::select()方法
<? php//在model中取得连接,并进行相应数据库操作
$this->db = Zend_Registry::get('db');
$select = $this->db->select();
$select->from('link_info', 'link_info.*')
->join('link_tag_collect', 'link_info.linkid=link_tag_collect.linkid')
->where('user_friend.userid=?',$userid)->distinct(link_info.linkid)
?>
->order('link_tag_collect.addtime DESC')
-2007-12-18>limit(10,0);
$sql = $select->__toString();
$result = $this->db->fetchALL($sql);
1.3 使用 Zend_Db_Table
Zend_Db_Table 是Zend Framework的表模块.它通过zend_db_adapter连接到数据库,为数据库模式检查表对象,
并对该表进行操作和查询.
<?php
class RoundTable extends Zend_Db_Table {}
$table = new RoundTable();
$db = $table->getAdapter();
// SELECT * FROM round_table
// WHERE noble_title = "Sir"
// ORDER BY first_name
// LIMIT 10 OFFSET 20
$where = $db->quoteInto('noble_title = ?', 'Sir');
$order = 'first_name';
$count = 10;
$offset = 20;
$rowset = $table->fetchAll($where, $order, $count, $offset);
?>
以上都为废话,从ZF手册中皆能得到。
- 从model中获得数据库连接,然后使用ZEND_DB_SELECT。
<?php
public function getTopTag(){
$select = $this->db->select();
$select->from($this->_name, '*')
->order('TAGTOTAL DESC')
->limit(10,0);
$sql = $select->__toString();
$result = $this->db->fetchALL($sql);
return $result;
}
?>
在TagController.php中
<?php
class TagController extends Zend_Controller_Action
private $tag;
function init() {
parent::init();
Zend_Loader::loadClass('Tag');
$this->tag = new Tag();
}
function topAction(){
$thi->tag->getTopTag();
...
}
?>
- 使用ZEND_DB_TABLE
<?php
class Tag extends Zend_Db_Table
{
protected $_name = "TAG_INFO";
protected $_primary = 'TAGID';
}
?>
在TagController.php中
<?php
class TagController extends Zend_Controller_Action
private $tag;
function init() {
parent::init();
Zend_Loader::loadClass('Tag');
$this->tag = new Tag();
}
function topAction(){
$order = 'TAGTOTAL';
$count = 10;
$offset = 0;
$thi->tag->fetchAll( $order, $count, $offset);
...
}
?>
最好还是选用方法一,能够将对数据的操作都封装在model中。
2.插入数据
无论是DB还是Table类,都使用insert()方法。
对于Oracle来说,如果要使用sequence作为自增的主键的话,需要使用trigger。
比如,有tag表,主键为tagid,其对应的sequence为tag_seq,要插入数据时,需要先新建trigger:
create or replace trigger tag_tri
before insert on tag
for each row
declare
nextid number;
begin
IF :new.tagid IS NULL or :new.tagid=0 THEN
select tag_seq.nextval
into nextid
from sys.dual;
:new.tagid:=nextid;
end if;
end tag_tri;
其余部分和插入其它数据库相同
<?php
$table_name='TAG';
$row = array (
'TAGNAME' => $tagname,
'TAGTOTAL' => '1'
);
$this->db->insert($table_name,$row);
?>
3.更新数据
3.1直接执行update语句,参见文档。
3.2如果update语句中,有包含数据库的特殊关键字时,需要先将数据选出,然后再更新
<?php
$where = $this->db->quoteInto('tagname = ?',$tagname);
$rowset = $this->tag->fetchAll($where);
$count=$rowset->count();
$tag = $rowset->current();
if($count!=0){
$tagid=$tag->TAGID;
//tagtotal+1
$tag->TAGTOTAL ++; //应判断一下当前用户是否
$tag->save();
}
?>
4.删除数据
<?php
//删除已有的collect表中记录
// where条件语句
$where = $this->db->quoteInto('USERID = ?', $userid)
.$this->db->quoteInto('AND LINKID = ?', $linkid);
// 删除数据并得到影响的行数
$rows_affected = $this->collect->delete($where);
?>
总结完毕:
tips:
注意表名、字段名等的大小写!
1.加载配置文件:
require_once 'Zend/Config/Ini.php';
$config['nestSeparator'] = ':';
$config = new Zend_Config_Ini('/path/to/config.ini', 'staging', $config);
另一种加载文件的方法
Zend_Loader::loadClass('AppController','../application/controllers'); //加载基本控制器
// 加载配置
$config= new Zend_Config_Ini('../application/config.ini', 'reader');
2.config.ini文件示例
[general]
db.adapter = PDO_Oci
db.config.username = cat
db.config.password = dog
db.config.dbname = rabbit
[reader]
reader.LIB_CODE_REDRSTS_CANCEL = 0
reader.LIB_CODE_REDRSTS_ENABLE = 1
reader.LIB_CODE_CERTSTS_CANCEL = 0
3.读取配置文件
$redr=$config->reader->redr_lose;
参考资料:http://www.phpeye.com/zf/zend.config.adapters.ini.html
在两天的多次尝试下,终于成功连接到Oracle,记录如下:
1.安装oracle(如果以前有残留的话,要卸载干净,非常重要!)
2.启动extension=php_pdo_oci.dll或extension=php_pdo_oci8.dll
两者的区别在于:
php_pdo_oci8.dll will work with older libraries. Regardless of the
libraries used by PHP, both can be used to connect to databases of other
versions (with some limitations)
3.连接代码示例:
记录之,以防忘记。包括用户登陆、验证用户、退出三个部分的函数。
详细资料请查阅http://www.phpeye.com/zf/zend.auth.html手册部分 。
此配置是在Window环境下,Apache2.0.54,PHP 版本为5.2.2
1.程序结构目录如下:
application/
controllers/
IndexController.php
models/
views/
scripts/
index/
index.phtml
helpers/
filters/
library/
public/
index.php
2.将下载的ZF中的library下的zend目录拷贝到程序的library中
3.配置apache
3.1修改httpd.conf,在末尾加上:
NameVirtualHost 127.0.0.1
<VirtualHost 127.0.0.1>
ServerName mylibrary
DocumentRoot C:\mylibrary
RewriteEngine On
RewriteCond %{REQUEST_URI} !^.*(\.html|\.css|\.pdf|\.ppt|\.chm|\.rar|\.zip|\.js|\.gif|\.png|\.jpg|\.jpeg)$
RewriteRule ^(/.*)$ /index.php
</VirtualHost>
注意 DocumentRoot 中的路径不能包含空格,否则apache无法启动
3.2 开启LoadModule rewrite_module modules/mod_rewrite.so
3.3 修改C盘system32下的hosts ,添加下面一句:
127.0.0.1 mylibrary
4.最后可以通过http://mylibrary访问。
开始做“我的图书馆”,希望能够可扩展、易维护,提供插件式管理, 经建议,选择使用Zend Framework作为框架。于是,开始学习ZF。
参考资料:http://www.phpeye.com/download/listbycat/id/4 《Zend Framework入门教程中文版 》
下一步学习计划:
ZF手册中的Zend Controller,Zend db,Zend View,Zend Config部分。
如果因为字符集而出现一些问题的时候,比如可以成功提交英文变量,但是无法成功提交中文变量时,可以尝试以下几种解决办法:
1.如果页面编码为UTF-8编码,则需要将PHP代码页另存为UTF-8格式。
2.如果受系统限制,无法改变原始页面,可以在PHP脚本中使用转换函数:iconv Functions。
比如:$seachcondition = iconv("UTF-8", "gb2312", "分类号'");
将字符“分类号”从UTF-8编码转换为gb2312。
另外,如果不能正确加载iconv模块的话,请参照下面这篇文章:
http://blog.haloso.com/article.asp?id=326
