PHP flock文件锁定之独占操作测试

 更新时间:2016年11月25日 15:44  点击:1972
在php中对于文件的操作我们多半会使用文件锁定来为避免多用户同时操作时冲突了,下面小编与大家一起来测试一下文件锁定独占操作一些实例分析。

flock – 轻便的咨询文件锁定

flock()函数原型

bool flock ( int handle, int operation [, int &wouldblock] )

PHP 支持以咨询方式(也就是说所有访问程序必须使用同一方式锁定, 否则它不会工作)锁定全部文件的一种轻便方法


operation 可以是以下值之一:

要取得共享锁定(读取的程序),将 operation 设为 LOCK_SH(PHP 4.0.1 以前的版本设置为 1)。
要取得独占锁定(写入的程序),将 operation 设为 LOCK_EX(PHP 4.0.1 以前的版本中设置为 2)。
要释放锁定(无论共享或独占),将 operation 设为 LOCK_UN(PHP 4.0.1 以前的版本中设置为 3)。
如果不希望 flock() 在锁定时堵塞,则给 operation 加上 LOCK_NB(PHP 4.0.1 以前的版本中设置为 4)。
flock() 允许执行一个简单的可以在任何平台中使用的读取/写入模型(包括大部分的 Unix 派生版和甚至是 Windows)。如果锁定会堵塞的话(EWOULDBLOCK 错误码情况下),可选的第三个参数会被设置为 TRUE。锁定操作也可以被 fclose() 释放(代码执行完毕时也会自动调用)。

如果成功则返回 TRUE,失败则返回 FALSE。

注意:
在 Windows 下 flock() 将会强制执行。flock() 操作的 handle 必须是一个已经打开的文件指针。
由于 flock() 需要一个文件指针, 因此可能不得不用一个特殊的锁定文件来保护打算通过写模式打开的文件的访问(在 fopen() 函数中加入 “w” 或 “w+”)。
flock() 不能用于 NFS 以及其它一些网络文件系统。flock() 不支持旧的文件系统,如 FAT 以及它的派生系统。因此,此环境下总是返回 FALSE(尤其是对 Windows)详细资料查看自己操作系统的文档。
在部分操作系统中 flock() 以进程级实现。当用一个多线程服务器 API(比如 ISAPI)时,可能不可以依靠 flock() 来保护文件,因为运行于同一服务器实例中其它并行线程的 PHP 脚本可以对该文件进行处理。

独占测试:

下列两个文件都差不多,区别在于写入的东西不一样,先运行a.php文件,保持不关闭状态,接着运行b.php文件,然后去查看写入的文件内容,你会发现b.php文件的内容并没有写入成功!

 代码如下 复制代码

<?php
// a.php
if ( ! ($f = @fopen("flock.log","ab"))) exit;
flock($f, LOCK_EX);
while(TRUE)
{
 fwrite($f, "an");
}
?>

<?php
// b.php
if ( ! ($f = @fopen("flock.log","ab"))) exit;
flock($f, LOCK_EX);
while(TRUE)
{
 fwrite($f, "bn");
}
?>

比如我们有两个文件,如下。

flocka.php

 

 代码如下 复制代码
$file = 'temp.txt';
    $fp = fopen($file,'a');
 
    for($i = 0;$i < 5;$i++)
    {
        fwrite($fp, "11111111n");
        sleep(1);
    }
 
    fclose($fp);

flockb.php

 代码如下 复制代码
$file = 'temp.txt';
    $fp = fopen($file,'a');
 
    for($i = 0;$i < 5;$i++)
    {
        fwrite($fp, "22222222n");
    }
 
    fclose($fp);

先运行flocka.php,然后马上运行flockb.php。
结果:
11111111
22222222
22222222
22222222
22222222
22222222
11111111
11111111
11111111
11111111
说明不加文件锁时,两个文件会同时对txt文件进行写入操作。
下面修改一下两个php文件的代码。
flocka.php

 

 代码如下 复制代码
     $file = 'temp.txt';
    $fp = fopen($file,'a');
 
    if(flock($fp,LOCK_EX))
    {
        for($i = 0;$i < 5;$i++)
        {
            fwrite($fp, "11111111n");
            sleep(1);
        }
        flock($fp,LOCK_UN);
    }
    fclose($fp);


flockb.php

 代码如下 复制代码
$file = 'temp.txt';
    $fp = fopen($file,'a');
 
    if(flock($fp,LOCK_EX))
    {
        for($i = 0;$i < 5;$i++)
        {
            fwrite($fp, "22222222n");
        }
         flock($fp,LOCK_UN);
    }
 
    fclose($fp);

同样先运行flocka.php,然后马上运行flockb.php。
会发现在flocka.php运行结束前,flockb.php一直处于等待状态,只有当flocka.php运行结束后,flockb.php才会继续执行。
输出结果:
11111111
11111111
11111111
11111111
11111111
22222222
22222222
22222222
22222222
22222222
另外,在执行flock时,文件锁会自动释放

在做PHP程序时,经常会遇到设计多级菜单的编程,比如我们常见的三级菜单,首先展示产品的第一级分类,然后展示二级分类,最后再展示产品,这样就构成了三级结构,如果在后台没有一个很好的分类菜单支持,那么去更改数据时是很麻烦的。


最近在做一个内容管理的项目,客户硬要来一个多级分类,其实在许多的开源后台都是无限级的分类,比如111cn.net的后台,而这些分类的数据仅仅只保存到了一个数据表里,只是用源代码进行了关联而已。

而这些关联的数据并不复杂,其实一个优秀的后台设计,应该是无限的分类,这样,在进行二次开发时,不用再单独进行编程了,只要是功能一样,后台添加一个分类就可以了,这样就达到了功能共享了。

一个更简单的无限级分类菜单代码,我就把上面的原理简单实现一下,这个程序的关键就在于数据表的设计很有特色,不用递归,依靠个简单SQL语句就能列出菜单,看看这个数据表怎么设计的:

数据库字段大概如下:
———————————————————————————–
id 编号

fid 父分类编号

name 分类名

path 分类路径,以 id 为节点,组成类似 ,1,2,3,4, 这样的字符串
———————————————————————————-

可以假设有如下的数据

id fid name path
—————————————————-
1 0 分类1 ,1,

2 0 分类2 ,2,

3 1 分类1-1 ,1,3,

4 1 分类1-2 ,1,4,

5 2 分类2-1 ,2,5,

6 4 分类1-2-1 ,1,4,6,
—————————————————-
实现的PHP全部代码用类封装的,不是必要,而是自己也想熟悉一下OO,呵呵!,来看看页面代码:

 代码如下 复制代码

<?php
/**************************************
页面:menu.php
作者:www.111cn.net
功能:定义数据库操作及生成菜单列表类

**************************************/
class menu{
//创建构造函数,作用:数据库连接并选择相应数据库
public function __construct(){
$dbhost = "localhost";
$dbuser = "root";
$dbpassword = "7529639";
$dbname = "menu";
mysql_connect($dbhost,$dbuser,$dbpassword) or die("error!");
mysql_query("SET NAMES 'GBK'");
mysql_select_db($dbname);
}

//执行SQL语句函数
private function query($sql){
return mysql_query($sql);
}

//取得111cn.net结果集数组函数
private function loop_query($result){
return mysql_fetch_array($result);
}
//列出菜单列表函数
public function menulist(){
$sql="select * from list order by path";
$result=$this->query($sql);
while($rows=$this->loop_query($result)){
if(substr_count($rows['path'],',')>2){
for($i=0;$i<(substr_count($rows['path'],',')-2);$i++)
echo ' ';
}
echo $rows['name'].'<br>';
}
}

//创建析构函数,作用:关闭数据库连接
public function __destruct(){
return mysql_close();
}
}
$db=new menu();//生成实例
$db->menulist();//调用方法生成菜单
?>

小提示:这样就生成了一个无限级的分类菜单,当然,不仅仅只是应用在菜单上,而且可以应用在产品的分类以及地市区的分类上面,后台的增删改查需要自己小小的去写一下

原文来自:04ie.com

因为服务器上安装了安全狗这个功能,我们直接的sql是不能使用的,下面我来给各位同学介绍介绍一下phpmyadmin把sql语句改为base64传输来解决这个问题。

1.首先 修改 libraries/header.inc.php

将 js base64 的函数 粘贴到 第 61 行

2.然后 修改 js/sql.js

找到 $("#sqlqueryform.ajax").live("submit",function(a){ 这一段

改为下面这样,

 代码如下 复制代码

$("#sqlqueryform.ajax").live("submit",function(a){
  a.preventDefault();
  var b=$(this);
  if(!checkSqlQuery(b[0]))return false;
  $(".error").remove();
  var c=PMA_ajaxShowMessage(),e=$("#sqlqueryresults");
  PMA_prepareForAjaxRequest(b);
  $('#sqlquery').val( Base64.encode( $('#sqlquery').val() )  );
  $.post(b.attr("action"),b.serialize(),function(d){

 
3.最后修改 import.php


import.php 文件第24行 插入

 代码如下 复制代码


$sql_query=base64_decode($sql_query);


ok 现在 如果是通过点击 sql 输入的查询 全部会通过base64编码后 再进行传输了 ,可以躲过安全狗之类的安全防御软件的拦截

在php5中为我提供了两个函数,json_encode和json_decode可以实现json与数组互转了,但在中文上可以支持不好,下面介绍一个经过处理支持中文数组与json互转函数。
 代码如下 复制代码


<?php
/**
 * json 生成,分析 支持中文
 */
class Json_Helper {
 /**
  * 生成json
  */
 public static function encode($str){
  $json = json_encode($str);
  //linux
        return preg_replace("#\u([0-9a-f]{4})#ie", "iconv('UCS-2BE', 'UTF-8', pack('H4', '\1'))", $json);
        //windows
        //return preg_replace("#\u([0-9a-f]{4})#ie", "iconv('UCS-2LE', 'UTF-8', pack('H4', '\1'))", $json);
 }

 /**
  * 分析json
  */
 public static function decode($str) {
        return json_decode($str);
 }
}
?>

在php中设置也删除cookie我们都是使用setcookie来设置,过期了就自动删除了,但在ff下你可能会碰到cookie无法过期了。

首先我们看一下php手册中关于删除cookie的说明

bool setcookie ( string name [, string value [, int expire [, string path [, string domain [, bool secure]]]]] )

要删除 cookie 需要确保它的失效期是在过去,才能触发浏览器的删除机制。
下面的例子说明了如何删除刚才设置的 cookie: 例子 2. setcookie() 删除
例子

 代码如下 复制代码

// 将过期时间设为一小时前

setcookie("TestCookie", "", time() - 3600);
setcookie("TestCookie", "", time() - 3600, "/~rasmus/", ".utoronto.ca", 1);

等储存用户的登录信息,然后利用

 代码如下 复制代码

setcookie("username", "", time()-3600);

做 退出,在IE下测试没有任何问题。既然做网站,就要兼容尽可能多的浏览器,呵呵。于是在 Firefox 中测试,登陆一切正常,当推出时,遇到了麻烦。怎么也不会退出,用户总是在登录状态。于是查看了 IE、Firefox 中cookie记录的区别,经过测试,才恍然大悟。

原来如果没有指定 setcookie() 的第四个参数(合法路径参数),默认会把当前目录作为合法路径,而我测试的路径为:http://127.0.0.1/php/rss2fla/data /log.php ,所以导致登陆和退出时 所设置的 cookie 路径不同。

IE比Firefox要人性化,呵呵,当美指定路径时,会覆盖当前 IP 下的同名Cookie变量,而FireFox比较严格了,导致又重新建了个变量……

来看几个例子: 

简单的: 

 代码如下 复制代码

SetCookie("MyCookie", "Value of MyCookie"); 

带失效时间的: 

 代码如下 复制代码

SetCookie("WithExpire", "Expire in 1 hour", time()+3600);//3600秒=1小时 

什么都有的: 

 代码如下 复制代码

SetCookie("FullCookie", "Full cookie value", time()+3600, "/forum", ".111cn.net", 1); 

最后一种是兼容所有浏览器的哦。

综上,在php中操作cookie时最好使用下面的方式:

 代码如下 复制代码
if(isset($_COOKIE["sid"]) && !empty($_COOKIE["sid"])){
  // 这样可以保证Cookie存在且在有效期内
  ……
}
[!--infotagslink--]

相关文章

  • php读取zip文件(删除文件,提取文件,增加文件)实例

    下面小编来给大家演示几个php操作zip文件的实例,我们可以读取zip包中指定文件与删除zip包中指定文件,下面来给大这介绍一下。 从zip压缩文件中提取文件 代...2016-11-25
  • iPhone输错密码导致手机锁定怎么办 iPhone输错密码手机锁定解决方法

    如果反复输错屏幕密码,手机就会进入锁定模式,也就是永久停用状态,只能抹掉数据以解除锁定状态和清除锁屏密码...2022-09-14
  • Jupyter Notebook读取csv文件出现的问题及解决

    这篇文章主要介绍了JupyterNotebook读取csv文件出现的问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2023-01-06
  • 解决@SpringBootTest 单元测试遇到的坑

    这篇文章主要介绍了解决@SpringBootTest 单元测试遇到的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-14
  • Photoshop打开PSD文件空白怎么解决

    有时我们接受或下载到的PSD文件打开是空白的,那么我们要如何来解决这个 问题了,下面一聚教程小伙伴就为各位介绍Photoshop打开PSD文件空白解决办法。 1、如我们打开...2016-09-14
  • C#操作本地文件及保存文件到数据库的基本方法总结

    C#使用System.IO中的文件操作方法在Windows系统中处理本地文件相当顺手,这里我们还总结了在Oracle中保存文件的方法,嗯,接下来就来看看整理的C#操作本地文件及保存文件到数据库的基本方法总结...2020-06-25
  • 解决python 使用openpyxl读写大文件的坑

    这篇文章主要介绍了解决python 使用openpyxl读写大文件的坑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-13
  • C#实现HTTP下载文件的方法

    这篇文章主要介绍了C#实现HTTP下载文件的方法,包括了HTTP通信的创建、本地文件的写入等,非常具有实用价值,需要的朋友可以参考下...2020-06-25
  • SpringBoot实现excel文件生成和下载

    这篇文章主要为大家详细介绍了SpringBoot实现excel文件生成和下载,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-02-09
  • php无刷新利用iframe实现页面无刷新上传文件(1/2)

    利用form表单的target属性和iframe 一、上传文件的一个php教程方法。 该方法接受一个$file参数,该参数为从客户端获取的$_files变量,返回重新命名后的文件名,如果上传失...2016-11-25
  • php批量替换内容或指定目录下所有文件内容

    要替换字符串中的内容我们只要利用php相关函数,如strstr,str_replace,正则表达式了,那么我们要替换目录所有文件的内容就需要先遍历目录再打开文件再利用上面讲的函数替...2016-11-25
  • PHP文件上传一些小收获

    又码了一个周末的代码,这次在做一些关于文件上传的东西。(PHP UPLOAD)小有收获项目是一个BT种子列表,用户有权限上传自己的种子,然后配合BT TRACK服务器把种子的信息写出来...2016-11-25
  • AI源文件转photoshop图像变模糊问题解决教程

    今天小编在这里就来给photoshop的这一款软件的使用者们来说下AI源文件转photoshop图像变模糊问题的解决教程,各位想知道具体解决方法的使用者们,那么下面就快来跟着小编...2016-09-14
  • C++万能库头文件在vs中的安装步骤(图文)

    这篇文章主要介绍了C++万能库头文件在vs中的安装步骤(图文),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
  • Zend studio文件注释模板设置方法

    步骤:Window -> PHP -> Editor -> Templates,这里可以设置(增、删、改、导入等)管理你的模板。新建文件注释、函数注释、代码块等模板的实例新建模板,分别输入Name、Description、Patterna)文件注释Name: 3cfileDescriptio...2013-10-04
  • php文件上传你必须知道的几点

    本篇文章主要说明的是与php文件上传的相关配置的知识点。PHP文件上传功能配置主要涉及php.ini配置文件中的upload_tmp_dir、upload_max_filesize、post_max_size等选项,下面一一说明。打开php.ini配置文件找到File Upl...2015-10-21
  • ant design中upload组件上传大文件,显示进度条进度的实例

    这篇文章主要介绍了ant design中upload组件上传大文件,显示进度条进度的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-29
  • C#使用StreamWriter写入文件的方法

    这篇文章主要介绍了C#使用StreamWriter写入文件的方法,涉及C#中StreamWriter类操作文件的相关技巧,需要的朋友可以参考下...2020-06-25
  • php实现文件下载实例分享

    举一个案例:复制代码 代码如下:<?phpclass Downfile { function downserver($file_name){$file_path = "./img/".$file_name;//转码,文件名转为gb2312解决中文乱码$file_name = iconv("utf-8","gb2312",$file_name...2014-06-07
  • mysql锁定单个表的方法

    mysql锁定单个表的方法 复制代码 代码如下:mysql>lock table userstat read; mysql>unlock tables; 页级的典型代表引擎为BDB。 表级的典型代表引擎为MyISAM,MEMORY以及很久以前的ISAM。 行级的典型代表引擎为INN...2014-05-31