首页 > 后端开发 > php教程 > PHP主| 5启发性(有用)PHP片段

PHP主| 5启发性(有用)PHP片段

Joseph Gordon-Levitt
发布: 2025-02-26 08:41:09
原创
293 人浏览过

PHP Master | 5 Inspiring (and Useful) PHP Snippets

网络上充斥着各种“X个PHP代码片段”类型的文章,为什么还要再写一篇呢?原因很简单:大多数文章中的代码片段都乏善可陈。生成随机字符串或返回$_SERVER["REMOTE_ADDR"]获取客户端IP地址之类的片段实在缺乏趣味性和实用性。本文将分享五个实用且有趣的PHP代码片段,并介绍它们背后的灵感来源。希望这些富有创意的代码片段能启发您在日常编程中编写更出色、更具创意的代码。

关键要点

  • 本文介绍了五个实用的PHP代码片段,包括使用内置fputcsv()函数生成CSV数据、使用PSR-0标准自动加载类、使用unpack()函数解析定长数据、使用一个简单的PHP类进行HTML模板化以及使用file_get_contents作为cURL的替代方案来发出HTTP GET和POST请求。
  • 作者强调了使用PHP内置函数和创建自定义解决方案来执行常见任务(例如生成CSV数据或自动加载类)的重要性,这可以提高编码效率和创造力。
  • 作者还讨论了使用PHP代码片段的益处和潜在风险,建议虽然它们可以极大地提高生产力并提高代码可读性,但应谨慎使用,在安全的环境中进行测试,并从可信的来源获取,以避免潜在的问题或安全风险。

1. 生成CSV

我们经常看到这样的代码,试图将多维数组数据转换为CSV:

<?php
$csv = "";
foreach ($data as $row) {
    $csv .= join(",", $row) . "\n";
}
echo $csv;
?>
登录后复制
登录后复制
登录后复制

问题在于各个元素没有正确转义,单个值中包含引号或逗号都可能导致后续解析CSV数据时出错。最好使用内置的fputcsv()函数;它的实现是用C代码编写的,因此执行速度更快,并且会为您处理必要的引用/转义。以下代码封装了从数据数组构造CSV输出的逻辑。它包含可选参数,允许使用标题列,以及是否将CSV直接刷新到浏览器或将输出作为字符串返回。其巧妙之处在于将流与fputcsv()一起使用,因为该函数需要打开的文件句柄才能操作。

<?php
function toCSV(array $data, array $colHeaders = array(), $asString = false) {
    $stream = ($asString)
        ? fopen("php://temp/maxmemory", "w+")
        : fopen("php://output", "w");

    if (!empty($colHeaders)) {
        fputcsv($stream, $colHeaders);
    }

    foreach ($data as $record) {
        fputcsv($stream, $record);
    }

    if ($asString) {
        rewind($stream);
        $returnVal = stream_get_contents($stream);
        fclose($stream);
        return $returnVal;
    } else {
        fclose($stream);
    }
}
?>
登录后复制
登录后复制
登录后复制

有了toCSV()函数,生成CSV变得简单且可靠。

2. 自动加载类

自动加载类文件很常见,但您可能不喜欢各种PHP框架提供的那些臃肿、重量级的自动加载器,或者您可能只是喜欢自己编写解决方案。幸运的是,您可以编写自己的最小加载器,并且仍然符合PHP标准工作组采用的PSR-0标准,我曾在自己的博客上首次演示了这一点。该标准并未描述PSR-0兼容的自动加载器必须提供的支持功能(注册方法、配置选项等)。如果它能够自动在<vendor name>(<namespace>)模式中找到类定义,那么它就是PSR-0兼容的。此外,它没有指定<vendor name>的父目录。大多数自动加载器实现的额外“填充”如果您需要通过代码指定位置则很方便,但如果您只是使用PHP的include路径中已有的目录,则没有必要。

<?php
$csv = "";
foreach ($data as $row) {
    $csv .= join(",", $row) . "\n";
}
echo $csv;
?>
登录后复制
登录后复制
登录后复制

这里的巧妙之处在于正则表达式,它将传入的名称拆分为其组成部分;类名始终位于$match[2]中,$match[1]是命名空间名称,它可能是空字符串。必须识别这些部分,因为下划线在命名空间部分中没有任何特殊含义,因此对下划线和反斜杠进行盲目替换是不正确的。

3. 使用unpack()解析定长数据

在当今充斥着XML和JSON的现代世界中,您可能会认为定长格式已经灭绝……但您错了。仍然存在大量的定长数据,例如某些日志条目、MARC 21(书目信息)、NACHA(财务信息)等。老实说,我对定长数据仍然情有独钟。

在C等语言中,定长数据相对容易处理,因为数据一旦加载到内存中,就会与访问数据结构完美对齐。但是对于某些人来说,在PHP等动态语言中处理定长数据可能是一场斗争;该语言的松散类型使得这种内存访问变得不可能。因此,我们经常看到这样的代码:

<?php
function toCSV(array $data, array $colHeaders = array(), $asString = false) {
    $stream = ($asString)
        ? fopen("php://temp/maxmemory", "w+")
        : fopen("php://output", "w");

    if (!empty($colHeaders)) {
        fputcsv($stream, $colHeaders);
    }

    foreach ($data as $record) {
        fputcsv($stream, $record);
    }

    if ($asString) {
        rewind($stream);
        $returnVal = stream_get_contents($stream);
        fclose($stream);
        return $returnVal;
    } else {
        fclose($stream);
    }
}
?>
登录后复制
登录后复制
登录后复制

您可能感到不适。没关系,我也不想在我的应用程序中使用这样的代码!它冗长且索引容易出错。幸运的是,有一个更好的替代方案:unpack()

PHP手册中unpack()的文档指出:“根据给定的格式将二进制字符串解包到数组中”,并显示了使用二进制数据转义的用法示例。可能并非立即显而易见的是,由于格式说明符“A”表示字符(毕竟,字符串不只是一系列位和字节吗?),因此该函数可用于解析定长字符串。

使用unpack(),上述示例可以更优雅地改写如下:

<?php
spl_autoload_register(function ($classname) {
    $classname = ltrim($classname, "\");
    preg_match('/^(.+)?([^\]+)$/U', $classname, $match);
    $classname = str_replace("\", "/", $match[1])
        . str_replace(["\", "_"], "/", $match[2])
        . ".php";
    include_once $classname;
});
?>
登录后复制
登录后复制

在这种情况下,格式字符串只是一系列A,指定字符数据、特定字段的字符数以及检索到的数据将在最终数组中分配的键名,用斜杠分隔。例如,A6date会解析出6个字符,并将其作为$header["date"]提供。

4. HTML模板化

在PHP社区中,关于模板化一直没有达成太多共识。我们都同意将HTML和PHP分开是可取的,但在使用Smarty或Twig等模板库的适用性上存在冲突。一些人指出PHP本身就是一个模板引擎,并反对库的速度、语法等。其他人声称从使用模板系统提供的DSL中获益匪浅。一种折衷方案是使用用PHP编写的非常小的类来模板化您的HTML以保持代码简洁。

<?php
$csv = "";
foreach ($data as $row) {
    $csv .= join(",", $row) . "\n";
}
echo $csv;
?>
登录后复制
登录后复制
登录后复制

它不是一个成熟的模板引擎;而是一个简洁的辅助类,充当“存储桶”,收集键/值数据对,您可以在指定为模板的包含文件中访问这些数据对。首先,您在视图中创建一个Template类的实例,可以选择传递一个目录名称来查找后续的模板文件(允许您对相关文件进行分组)。然后,将应填充模板的值提供给set()方法或作为裸属性。一旦指定所有值,您就可以调用out()方法来呈现模板。

<?php
function toCSV(array $data, array $colHeaders = array(), $asString = false) {
    $stream = ($asString)
        ? fopen("php://temp/maxmemory", "w+")
        : fopen("php://output", "w");

    if (!empty($colHeaders)) {
        fputcsv($stream, $colHeaders);
    }

    foreach ($data as $record) {
        fputcsv($stream, $record);
    }

    if ($asString) {
        rewind($stream);
        $returnVal = stream_get_contents($stream);
        fclose($stream);
        return $returnVal;
    } else {
        fclose($stream);
    }
}
?>
登录后复制
登录后复制
登录后复制

示例的mytemplate.php文件可能如下所示:

<?php
spl_autoload_register(function ($classname) {
    $classname = ltrim($classname, "\");
    preg_match('/^(.+)?([^\]+)$/U', $classname, $match);
    $classname = str_replace("\", "/", $match[1])
        . str_replace(["\", "_"], "/", $match[2])
        . ".php";
    include_once $classname;
});
?>
登录后复制
登录后复制

在模板文件中,您可以访问PHP功能的全部范围,以根据需要格式化值、过滤值等。

out()的第二个可选参数可以指定将模板内容作为字符串返回,而不是直接将其刷新到浏览器,您可以利用它来用先前填充的模板的结果替换一个模板中的占位符。

5. 使用file_get_contents作为cURL的替代方案

cURL是一个用于通过各种协议进行通信的强大库。它确实功能非常强大,有时没有其他方法可以做到。如果您明确需要cURL公开的功能来完成您的任务,那么请使用cURL!但是,PHP中日常cURL使用的大部分内容都围绕发出HTTP GET和POST请求,这可以使用PHP内置函数轻松完成。

依赖cURL发出HTTP请求的问题有两个:1)即使是最简单的交易,也经常需要设置许多选项,以及2)它是一个扩展,根据您的托管和安装情况,它可能可用也可能不可用;它是一个常见的扩展,但默认情况下未启用。

file_get_contents()stream_context_create()是自4.3版本以来一直可用的两个原生PHP函数。结合使用,它们可以执行许多与cURL通常执行的相同类型的请求。

对于基本的GET请求,可以使用file_get_contents()本身:

<?php
// 解析NACHA报头记录
$row = fread($fp, 94);
$header = array();
$header["type"] = substr($row, 0, 1);
$header["priority"] = substr($row, 1, 2);
$header["immDest"] = substr($row, 3, 10);
$header["immOrigin"] = substr($row, 13, 10);
$header["date"] = substr($row, 23, 6);
$header["time"] = substr($row, 29, 4);
$header["sequence"] = substr($row, 33, 1);
$header["size"] = substr($row, 34, 3);
$header["blockFactor"] = substr($row, 37, 2);
$header["format"] = substr($row, 39, 1);
$header["destName"] = substr($row, 40, 23);
$header["originName"] = substr($row, 63, 23);
$header["reference"] = substr($row, 86, 8);
print_r($header);
?>
登录后复制

对于需要指定HTTP标头的请求(无论是GET还是其他任何HTTP方法),您可以通过将一个特殊键控数组传递给stream_context_create()来创建一个上下文,然后将上下文传递给file_get_contents()

<?php
// 解析NACHA报头记录
$row = fread($fp, 94);
$header = unpack("A1type/A2priority/A10immDest/A10immOrigin/"
    . "A6date/A4time/A1sequence/A3size/A2blockFactor/A1format/"
    . "A23destName/A23originName/A8reference", $row);
print_r($header);
?>
登录后复制

上面的示例显示了通过POST上传文件,上下文数组使用键“method”、“header”和“content”指定事务所需的信

息。

当将file_get_contents()用于复杂的请求(例如文件上传)时,首先创建一个模拟Web表单并通过启用了firebug的Firefox或类似工具运行它,然后检查请求中包含的内容可能会有所帮助。从那里您可以推断出要包含的重要标头元素。

总结

希望您觉得本文中介绍的代码片段很有趣。它们展示了创造性的问题解决方法以及将PHP的内置功能用于新的效果。我希望您发现它们有用且鼓舞人心。如果您有自己鼓舞人心的代码片段,请随时在下面的评论中分享。

(图片来自Fotolia)

(关于PHP代码片段的常见问题)

(此处省略了FAQ部分,因为原文FAQ部分内容与代码片段本身关系不大,属于补充说明,可以根据实际需求自行添加或修改。)

以上是PHP主| 5启发性(有用)PHP片段的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板