标签归档:PHP

php学习练习(1)-简单的日历类

追溯到我专职写程序的日子已经是若干年以前了,依稀记得从08年后半年开始,就没有在工作中专职全力写程序了,偶尔写点也是基于验证性的东西。当然不把写程序当作职业中的一部分是有很多借口,但都是借口,虽然年龄已经不小了,但是重新捡起来还是可以的,最近恰逢想要写一个系统,于是开始动手。

有「归零」的心态加上持续的练习是必不可少的,提高写程序的水平唯一方法就是不断的进行编码练习。当然练习是基于获取知识后的实践,再结合项目实际应用,积累一段时间后,自然会重新站起,在自己的博客上记录一下这段时间,今天从一个简单日历类开始。

实现基本的日历类Calendar功能,类向外公开一个display方法用于显示日历,能够按照月、年显示日历信息,简单日历类主要练习PHP的一部分日期时间函数,基于功能,类图如下:

calendar

display方法用于显示日历
weekList方法用于列出日历中的星期
daysList方法用于列出每个月的天数
editDate方法用于改变日历显示
构造方法完成对成员的初始化

类文件名为:calendar.class.php ,测试文件为:test.php ,具体代码如下:

year = isset($_GET['year']) ? $_GET['year'] : date('Y');
    $this->month = isset($_GET['month']) ? $_GET['month'] : date('m');
    $this->daysOfMonth = date('t', mktime(0, 0, 0, $this->month, 1, $this->year));
    $this->dayOfWeek = date('w', mktime(0, 0, 0, $this->month, 1, $this->year));
  }

  function display() {
    echo '';
    $this->editDate();
    $this->weekList();
    $this->daysList();
    echo '
} private function weekList() { $week = array('日','一','二','三','四','五','六'); echo ''; for($i = 0; $i < count($week); $i++) { echo ''. $week[$i] .''; } echo ''; } private function daysList() { echo ''; for($col = 0; $col < $this->dayOfWeek; $col++) echo ' '; for($day = 1; $day <= $this->daysOfMonth; $day++) { $col++; if($day == date('d')) { echo ''. $day .' } else { echo ''. $day .''; } if($col % 7 == 0) { echo ''; } } echo ''; } private function editDate() { echo ''; echo '<<'; echo '<'; echo ''. $this->year . '年'. $this->month .'月'; echo '>'; echo '>>'; echo ''; } private function prevYear($year, $month) { $year--; if($year == 1970) { $year = 1970; } return 'year=' . $year . '&month=' . $month; } private function prevMonth($year, $month) { $month--; if($month<1) { $month = 12; $year--; } return 'year=' . $year . '&month=' . $month; } private function nextMonth($year, $month) { $month++; if($month > 12) { $month = 1; $year++; } return 'year=' . $year . '&month=' . $month; } private function nextYear($year, $month) { $year++; return 'year=' . $year . '&month=' . $month; } } ?>

测试文件test.php,代码如下:

display();
?>

测试结果:
calendar.test

到这里就完成了这个简单的日历类,当然该类是仅仅用于展示日历的一个练习,如果用于实际则需要进一步改进,有几个方面可进一步改进:

1. 日历类一般用于前端,用javascript实现日历类在实际项目中应用应该好于用php这个服务器的脚本语言实现;
2. 如用php则应该非本练习中这样整页面向服务器提交请求,而应该使用AJAX就该日历部分展示与服务器进行异步数据传输;
3. 就功能上可增加输入年跟月来获取日历的方式;
4. 就展现上可采用模板,并用层叠样式表来设定样式;

–EOF–

PDO(PHP Data Object)扩展学习(一)

1、PDO知识学习
(1)了解PDO及建立数据库连接
PDO(PHP Data Object)扩展是一个与数据库通讯交互的扩展,与以往使用的mysql或mysqli类似,旨在解决不同数据库的连接及处理一致性问题,奈何在这个追求个性的时代,各个数据库厂家之间的SQL脚本都有自家的个性,有所差异,目前PDO还未完全解决针对所有数据库交互的一致性。
PDO针对数据库提供了一组相对比较简洁的功能,用于查询及获取数据集。其使用相对也比较简单,首先是一如既往的要跟将要操作的数据库取得联系,然后完成各种操作,与数据库取得联系,一般要创建一个PDO对象,然后核对暗号(DNS),匹配后该PDO对象就打入敌人内部,从而开展各项活动,该向外传递情报就传递,该破坏敌人内部就破坏。以MySQL为例我们来一个示例。

$dbConn = new PDO('mysql:host = localhost; dbname=db', 'dbuser', 'dbpwd');

创建成功后再$dbConn中存储PDO对象,然后就可以该干啥干啥了。
(2)基础查询
先看看基础查询,基础查询主要使用PDO对象的query方法,该方法接受SQL查询语句,返回一个叫PDOStatement的对象,返回的对象的fetch方法或者fetchAll方法就可以获得数据集了,具体如下:

$dbConn = new PDO('mysql:host = localhost; dbname=db', 'dbuser', 'dbpwd');
$stmt = $dbConn->query('SELECT Field1,Field2 FROM table_name');
while($row = $stmt->fetch()) {
    echo $row['field1'] . ' ---' $row['field2'] . "\n";
}

(3)数据提取模式
PDOStatement对象的fetch方法与fetchAll方法可接受相应的参数,该参数用于指定数据提取模式,主要反映在结果数据集格式化的模式,共有四个常量,分别是:FETCH_ASSOC、FETCH_NUM、FETCH_BOTH、FETCH_CLASS,其中FETCH_BOTH为默认值。
FETCH_ASSOC:返回的结果集为数组,以查询字段名作为数组的键值,上面的基础查询中输出中的应用;
FETCH_NUM:返回的结果集为数组,以数字作为数组的键值;
FETCH_BOTH:返回的结果集为数组,包含上两者,既有以字段名作为数组的键值,又有以数字作为数组的键值;
FETCH_CLASS:返回的结果集为一个已经命名的类的对象,以查询列名设置到类对象的属性中;
(4)参数及预处理
PDO扩展还可以对查询脚本参数进行预处理操作,可以在SQL语句中针对查询条件设定参数,可以在执行过程中给参数设定具体的值,等于说将PDOStatement对象的Query分为两步来运行,先传入预处理SQL语句,然后再赋值执行。使用预处理的好处是编译一次,多次执行,能够提高效率,要快于query查询,另外可以有效的防止SQL注入。另外参数也可以用?来代替,需要顺序给参数赋值。预处理还中的参数可以绑定一个值,也可以绑定一个变量。

// 基本操作
$sql = "SELECT * FROM tablename WHERE field = :param";
$stmt = $dbConn->prepare($sql);
$stmt->execute(array("field" => value));
$result = $stmt->fetch();
// 用?代替参数
$sql = "SELECT * FROM tablename WHERE field1 = ? AND field2 = ?";
$stmt = $dbConn->prepare($sql);
$stmt->execute(array(value1,value2));
$result = $stmt->fetch();
// 绑定值、预处理中的变量
$sql = "SELECT * FROM tablename WHERE field1 = :field1 AND field2 = :field2;
$stmt = $dbConn->prepare($sql);
$stmt->bindValue(':field1', value1);
$stmt->bindValue(':field2', value2);
$stmt->execute();
$result = $stmt->fetch();
// 可改变某一参数绑定的值,继续执行
$stmt->bindValue(':field2', value3);
$stmt->execute();
$result2 = $stmt->fetch();
// 还可以给参数绑定变量
$stmt->bindParam(':field2',$value4);
$value4 = value;
$stmt->execute();
$result3 = $stmt->fetch();

(6)数据库操作中的常用操作
(A)获取新插入数据的ID
执行后调用PDO对象的lastInsertId()方法可获得新插入数据的ID。

$sql = "INSERT INTO tablename(field1,field2,field3) VALUES(:field,:field2,:field3)";
$stmt = $dbConn->prepare($sql);
$stmt->execute(array(
        ':field1' => value1,
        ':field2' => value2,
        ':field3' => value3)
);
echo "New insert id : " . $dbConn->lastInsertId();  

(B)获取操作影响的行数
执行后调用PDOStatement对象的rowCount方法获得操作影响到行数,参考数据删除操作影响的行数。
(C)数据删除

$sql = "DELETE FROM tablename WHERE field = :field";
$stmt = $dbConn->prepare($sql);
$stmt->execute(array(":field" => value));
echo $stmt->rowCount() . ' rows deleted';

(7)异常处理
连接数据库失败会抛出PDOException异常,预处理失败会返回false或抛出PDOException,可使用getMessage方法获得抛出异常的原因,执行成功返回true,失败返回false,如果执行失败,可使用PDOStatement对象的errorInfo方法获得错误产生的原因。提取数据错误返回false,同样可以使用errorInfo方法获得错误的信息,需要注意的是提取数据会返回空数组或者其他 依据数据提取模式结果,这是没有错误状态的。

        try {
              $dbConn = new PDO("...");
        } catch (PDOException $e) {
              echo "Could not connect to database";
              exit;        
        }
        $sql = "...";
        try {
              $stmt = $dbConn->prepare($sql);
              if($stmt) {
                   if($stmt->execute(...)) {
                       $result = $stmt->fetch();
                   } else {
                       $error = $stmt->errorInfo();
                       ...
                   }
              }
        } catch(PDOException $e) {
            echo $e->getMessage();
        }

(8)PDO的事务处理
PDO对于事物处理的前提是数据库要支持事务处理,对于MySQL来讲表类型为Inno的支持事务,对于一组SQL语句需要进行事务处理,在任何SQL语句运行前调用PDO对象的beginTransaction方法启动事务,所有SQL语句运行成功后,调用PDO对象的commit方法,在运行中改组SQL语句有一个没运行成功,调用PDO对象的rollback方法回滚。

–未完待续 —

php html解析器Simple HTML Dom

最近在每天工作之余抽取一点小时间做一个小的web应用,中间需要一些原始数据的抓取,用于测试,在网上找到了PHP Simple HTML Dom,是一个简单的HTML DOM解析器,支持PHP5+以上版本,支持无效的HTML,提供了比较简单的方法来处理HTML元素。是一个开源项目。

在使用中基本能够满足目前的需要,相对对于HTML的处理还是比较方便的,就是效率跟占用内存貌似不太理想,可能是对其使用上不是很对路。总来的来说,用这个东西入门还是比较快速的。

1. 开始使用

首先下载解压缩,然后将simple_html_dom.php文件包含进要编写的脚本文件中,加载要处理的html,支持三种模式的html加载,分别是『从url中加载,从字符串中加载,从文件中加载』。

Hello World!');
//从文件中加载
$html = file_get_html('example.htm');

从字符串加载网上文件需要先从网络下下载,使用cURL比较好一些,需要在php配置文件中打开php扩展php_curl。

$url = 'http://www.example.com';
$ci = curl_init();
curl_setopt($ci,CURLOPT_URL,$url);
curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ci, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ci);

2. 查找html元素

使用find函数查找,返回包含对象的数组,常见的查找如下。

//查找超链接元素
$alink = $html->find('a');
//查找第n个连接元素
$alink = $html->find('a',5);
//查找id为main的div
$mainDiv = $html->find('div[id=main]');
//查找所有定义了id的div
$idDiv = $html->find('div[id]');
//查找所有定义了id的元素
$idAll = $html->find('[id]');
//查找样式类为info的元素
$classInfo = $html->find('.info');
//支持嵌套子元素查找
$ret = $html->find('ul li');
//查找多个html元素
$ret = $html->find('a,img,p');
//....

3. 其他

可以使用内置的函数来进行元素的定位,返回父元素parent,返回子元素数组children,返回第一个子元素first_child,返回最后一个子元素last_child,返回前一个相邻元素prev_sibling,返回后一个相邻元素next_sibling等。

提供简单的正则表达式来过滤属性选择器,类似于[attribute]的格式。

每个对象都有4个基本属性:
tag — 返回html标签名
innertext — 返回innerHTML
outertext — 返回outerHTML
plaintext — 返回HTML标签中的文本

返回元素属性值

//返回$alink的href值
$link = $alink->href;

通过设置元素的属性值可以对元素进行添加、修改、删除操作。

//删除url连接
$alink->href = null;
//元素的修改
$ret->outertext = '
';
$ret->outertext = '';
$ret->outertext = $ret->outertext . '
other
';
$ret->outertext = '
Welcome
' . $ret->outertext;

-EOF-

php文件操作基础

在有些场合中需要以文件的形式来对内容进行存储,通常这时候需要对文件进行一系列的操作,PHP中对于文件的操作跟其他计算机程序设计语言对文件的操作类似,对于文件的操作主要包括三个部分,以及围绕这三部分提供的辅助性函数来完成文件操作的工作。

(1)文件的创建与打开;
(2)文件的操作;
(3)文件的关闭;

在PHP中,通过一系列的函数来完成文件的操作,常用的函数及其简要说明罗列如下:

//文件打开,完成文件打开(在文件不存在时可创建文件),依赖于文件中模式的不同而具有不同的操作
resource fopen ( string $filename , string $mode [, bool $use_include_path = false [, resource $context ]] )
//$filename 打开或者要创建文件的路径及文件名,为了便于移植,使用反斜杠/为佳
//$mode 是文件打开的模式,有很多模式,比较常用的r,w,a,同样为了便于移植,建议mode中增加b(二进制)
//通常读文件为 rb ,写文件为 ab,分别表示以二进制读文件及以二进制向文件追加内容
//在文件打开操作过程中出现错误请首先检查文件所在的路径的权限设置

//文件操作函数

//写操作相关函数
//把$string的内容写到文件指针$handle
int fwrite ( resource $handle , string $string [, int $length ] )  
//函数是fwrite的别名函数
fputs() 

//也能完成写操作,不同的是集成了fopen(),fwrite(),fclose(),使用该函数不用再打开关闭文件
int file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] ) 

//读操作相关函数
//逐行读取
string fgets ( resource $handle [, int $length ] ) 
//逐行读,能够过滤标记
string fgetss ( resource $handle [, int $length [, string $allowable_tags ]] ) 
//逐行读,能够根据定界符输出到数组
array fgetcsv ( resource $handle [, int $length = 0 [, string $delimiter = ',' [, string $enclosure = '"' [, string $escape = '\\' ]]]] )
//一次性读取一个文件并将文件内容发送到标准输出,包含了文件打开与文件关闭操作
int readfile ( string $filename [, bool $use_include_path = false [, resource $context ]] )
//先要打开文件,然后将文件指针所指向的文件内容发送到标准输出
int fpassthru ( resource $handle )
//把结果发送到一个数组中
array file ( string $filename [, int $flags = 0 [, resource $context ]] )
//一次读取一个字符
string fgetc ( resource $handle )
//读取任意长度字节的内容
string fread ( resource $handle , int $length )

//文件关闭
bool fclose ( resource $handle )

//文件操作中常用的函数
//检查文件或目录是否存在
bool file_exists ( string $filename )
//获取文件大小,返回文件大小的字节数
int filesize ( string $filename )
//删除文件
bool unlink ( string $filename [, resource $context ] )
//复位文件指针位置
bool rewind ( resource $handle )
//在文件指针中定位
int fseek ( resource $handle , int $offset [, int $whence = SEEK_SET ] )

函数的具体详细的说明在php.net上可以查到,下面练习一下文件的操作,练习名称为『简易日记』,需求如下:

(1)每日记录的内容以年-月-日.txt保存在数据目录下;
(2)首页写日记,并显示以往的记录;
(3)显示单页记录内容;

日记填写界面:

diary

具体代码如下

首页(index.php)



  
    
    简易日记--php文件操作练习
    
  
  
    

我的日记本

写日记

日记主题

日记内容


日记列表


$value" . " | "; } ?>

保存处理页(diaryprocessed.php)

当前不能处理您提交的日志,请稍后再试!

"; echo "返回"; } fwrite($fp,$output); flock($fp,LOCK_UN); fclose($fp); echo '日记提交成功!'; echo "返回";

查看内容页(viewdiary.php)




  
    
    简易日记
    
  
  
    写日记
    

所有源文件下载:diary

-EOF-

用户名与密码正确无法登入wordpress后台

在wordpress部署完毕后,在用户名与密码输入正确后却无法登录入wordpress的仪表盘,上次在安装部署后碰到该问题,通过google寻找到解决方法,这次升级覆盖了文件,又碰到这个问题,索性在这里记录一下,以方便以后快速的查询。

如果您在录入正确的用户及密码后,提交又返回登录页面,可尝试采用这种方法来进行解决。

寻找/wp-includes/pluggable.php文件,定位到wp_set_auth_cookie函数,查找该函数中:

setcookie($auth_cookie_name, $auth_cookie, $expire, ADMIN_COOKIE_PATH, COOKIE_DOMAIN, $secure, true);

将ADMIN_COOKIE_PATH,修改为SITECOOKIEPATH即可,修改后如下:

setcookie($auth_cookie_name, $auth_cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN, $secure, true);

将cookie的作用目录由/wp-admin目录变为wordpress的根目录。这样设置后,解决该问题。