“X PHP Snippets” type articles abound on the Internet, so why write another one? Well, let’s face it… the PHP snippets in them are generally lame. Snippets that generating a random string or return $_SERVER["REMOTE_ADDR"] for the IP Address of a client really aren’t that interesting and are of modest usefulness. Instead, here’s five snippets that you’ll no doubt find interesting and useful, presented along with the problems that inspired them. I hope the creativity in many of them inspire you to write better and more creative code in your own day-to-day endeavors.
互联网上到处都是“ X PHP代码段”类型的文章,那么为什么还要写另一篇? 好吧,让我们面对现实吧……其中PHP代码片段通常是la脚的。 生成随机字符串或返回客户端IP地址的$_SERVER["REMOTE_ADDR"]片段的确不是那么有趣,并且用处不大。 取而代之的是,这里有五个片段,您无疑会发现它们有趣且有用,并与激发它们的问题一起呈现。 我希望其中许多人的创造力能激发您在日常工作中编写更好,更具创造力的代码。
All too often we see code that attempts to convert a multi-dimensional array of data to CSV that looks like this:
我们经常看到的代码试图将多维数据数组转换为CSV,如下所示:
<?php $csv = ""; foreach ($data as $row) { $csv .= join(",", $row) . "n"; } echo $csv;The problem is that the individual elements are not properly escaped, and a single value with either a quotation mark or comma can throw off a parser that later tries to consume the CSV data. It’s much better to use the built-in fputcsv() function; it should execute faster because it’s implementation is in C code, and it handles the necessary quoting/escaping for you.
问题在于各个元素不能正确地转义,并且带有引号或逗号的单个值会抛出解析器,该解析器以后会尝试使用CSV数据。 最好使用内置的fputcsv()函数。 因为它是用C代码实现的,所以它应该执行得更快,并且可以为您处理必要的引用/转义。
The following code wraps logic to construct CSV output from an array of data. It has optional parameters to allow for header columns and whether to flush the CSV directly to the browser or return the output as a string. The elegance here is the usage of streams with fputcsv() as the function requires an open file handle to operate.
以下代码包装了从数据数组构造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); } }With the toCSV() function in your arsenal, generating CSV becomes easy and fool proof.
借助武器库中的toCSV()函数,生成CSV变得轻松而简单。
Autoloading class files is common place, but maybe you don’t like some of the bloated, heavier autoloader offerings provided by various PHP frameworks, or maybe you just like to roll your own solutions. Luckily, it’s possible to roll your own minimal loader and still be compliant with the PSR-0 standard adopted by the PHP Standards Working Group, which I first demonstrated on my own blog.
自动加载类文件很常见,但是也许您不喜欢各种PHP框架提供的一些provided肿,笨重的自动加载器产品,或者您只是喜欢推出自己的解决方案。 幸运的是,可以滚动使用自己的最小加载程序,并且仍然符合PHP标准工作组采用的PSR-0标准 ,这是我首先在自己的博客上演示的。
The standard doesn’t describe what support functionality must be provided by a PSR-0 compliant autoloader (registration methods, configuration options, etc.). If it can automatically find a class definition in the <Vendor Name>(<Namespace>) pattern, then it’s PSR-0 compliant. Furthermore, it doesn’t specify the parent directory for <Vendor Name>. The extra “fluff” of most autoloader implementations is convenient if you need to specify the location via code, but is unnecessary if you simply use a directory already within PHP’s include path.
该标准未描述兼容PSR-0的自动加载器必须提供哪些支持功能(注册方法,配置选项等)。 如果它可以在<Vendor Name>(<Namespace>)模式中自动找到类定义,则它符合PSR-0。 此外,它没有为<Vendor Name>指定父目录。 如果需要通过代码指定位置,则大多数自动加载器实现中的额外“绒毛”很方便,但如果仅使用PHP的include路径中已经存在的目录,则不必要。
<?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; });The magic here is in the regex which splits the incoming name into its constituent parts; the class name will always be in $match[2], and $match[1] the namespace name which may or may not be an empty string. It’s necessary to identify the parts because the underscore has no special meaning in the namespace portion making a blind replace on underscores and backslashes incorrect.
这里的神奇之处在于正则表达式,它将传入的名称分成其组成部分; 类名将始终位于$match[2] ,而$match[1]则可能是也可能不是空字符串。 由于下划线在名称空间部分中没有特殊含义,因此盲目替换下划线和反斜杠是不正确的,因此有必要标识这些部分。
In today’s modern world filled with XML and JSON, you might think fixed-width formats are extinct… but you’d be wrong. There is still a large amount of fixed-width data, such as some log entries, MARC 21 (bibliographic information), NACHA (financial information), etc. And between you and me, I still have a soft spot for fixed-width data.
在当今充满XML和JSON的现代世界中,您可能会认为固定宽度格式已经不存在了……但是您会错了。 仍然存在大量的固定宽度数据,例如某些日志条目, MARC 21 (书目信息), NACHA (财务信息)等。在您和我之间,我仍然对固定宽度数据情有独钟。
Fixed-width data is relatively easy to work with in languages like C because the data, one loaded into memory, aligns perfectly with the accessing data structure. But for some, working with fixed-data in a dynamic language like PHP can be a struggle; the loose typing of the language makes such memory access impossible. And as a result, we often see code that looks like this:
固定宽度的数据相对容易使用C之类的语言处理,因为将数据加载到内存中后,它与访问的数据结构完全吻合。 但是对于某些人来说,以动态语言(如PHP)使用固定数据可能会很麻烦; 语言的松散类型使得无法进行此类内存访问。 结果,我们经常看到如下代码:
<?php // Parse a NACHA header record $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);You’re probably cringing. It’s okay, I wouldn’t want such code in my application either! It’s verbose and the indexing is error-prone. Luckily, there is a better alternative: unpack().
你可能会畏缩。 没关系,我也不想在我的应用程序中使用这样的代码! 它很冗长,索引很容易出错。 幸运的是,还有一个更好的选择: unpack() 。
The documentation for unpack() in the PHP Manual says: “Unpacks a binary string into an array according to the given format” and show usage examples escaped using binary data. What may not be immediately apparent is that the function can be used to parse fixed-width strings thanks to the format specifier ‘A’ which represents a character (after all, is not a string just a series of bits and bytes?).
PHP手册中的unpack()文档说:“根据给定的格式将二进制字符串unpack()为数组”,并显示使用二进制数据转义的用法示例。 可能不会立即显而易见的是,由于使用表示字符的格式说明符“ A”,该函数可用于解析固定宽度的字符串(毕竟,字符串不只是一系列的位和字节吗?)。
Using unpack(), the above example can be re-written more elegantly like so:
使用unpack() ,可以更优雅地重写上面的示例,如下所示:
<?php // Parse a NACHA header record $row = fread($fp, 94); $header = unpack("A1type/A2priority/A10immDest/A10immOrigin/" . "A6date/A4time/A1sequence/A3size/A2blockFactor/A1format/" . "A23destName/A23originName/A8reference", $row); print_r($header);The format string in this case is simply a series of A’s specifying character data, the character-count for the specific field, and the key name the retrieved data will be assigned in the final array, separated by slashes. A6date for example parses out the 6 characters and makes them available as $header["date"].
在这种情况下,格式字符串只是一系列A的指定字符数据,特定字段的字符数以及检索到的数据的键名,它们将在最终数组中分配,并用斜杠分隔。 例如, A6date解析出6个字符并将它们用作$header["date"] 。
There’s never been much of a consensus about templating in the PHP community. We all agree that keeping HTML and PHP separate is desirable, but clash on the suitability of using template libraries such as Smarty or Twig. Some point out that PHP itself is a template engine, and argue against a library’s speed, syntax, etc. Others claim to have benefited greatly from using the DSL that templating systems provide. One compromise is to template your HTML to keep things clean using a very minimal class written in PHP.
在PHP社区中,关于模板的讨论从未达成共识。 我们都同意将HTML和PHP分开是可取的,但是在使用模板库(如Smarty或Twig)的适用性方面存在冲突。 有人指出PHP本身就是模板引擎,并且反对库的速度,语法等。其他人则声称使用模板系统提供的DSL大大受益。 一种折衷方案是使用最少的用PHP编写的类来为HTML模板化,以保持环境整洁。
<?php class Template { protected $dir; protected $vars; public function __construct($dir = "") { $this->dir = (substr($dir, -1) == "/") ? $dir : $dir . "/"; $this->vars = array(); } public function __set($var, $value) { $this->vars[$var] = $value; } public function __get($var) { return $this->vars[$var]; } public function __isset($var) { return isset($this->vars[$var]); } public function set() { $args = func_get_args(); if (func_num_args() == 2) { $this->__set($args[0], $args[1]); } else { foreach ($args[0] as $var => $value) { $this->__set($var, $value); } } } public function out($template, $asString = false) { ob_start(); require $this->dir . $template . ".php"; $content = ob_get_clean(); if ($asString) { return $content; } else { echo $content; } } }It’s not a full-fledged template engine; rather a succinct helper class that acts as a “bucket” to collects key/value data pairs which you can access in included files designated as templates. First you create an instance of the Template class in your view, optionally passing a directory name used to look up the subsequent template files (allowing you to group related files). Then, provide the values that should populate the templates to either the set() method or as a bare property. Once all the values are specified, you call the out() method to render the template.
它不是一个成熟的模板引擎; 而是一个简洁的帮助程序类,它充当“存储桶”来收集键/值数据对,您可以在指定为模板的包含文件中访问这些键/值数据对。 首先,您在视图中创建Template类的实例,可以选择传递用于查找后续模板文件的目录名(允许您将相关文件分组)。 然后,提供应将模板填充到set()方法或作为裸属性的值。 一旦指定了所有值,就可以调用out()方法来呈现模板。
<?php $t = new Template(); // setting a value as if it were a property $t->greeting = "Hello World!"; // setting a value with set() $t->set("number", 42); // setting multiple values with set() $t->set(array( "foo" => "zip", "bar" => "zap" )); // render template $t->out("mytemplate");The mytemplate.php file for the example might look something like this:
该mytemplate.php文件可能看起来像这样:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> ... </head> <body> <div role="main"> <h1><?=$this->greeting;?></h1> ... </div> </body> </html>Within the template files you have access to the full range of PHP functionality to format values, filter values, etc. as you see fit.
在模板文件中,您可以访问所有PHP功能,以根据需要设置格式值,过滤器值等的格式。
A second, optional parameter to out() can specify to return the template contents as a string instead of flushing it directly to the browser, which you can take advantage of to replace placeholders in one template with the result of a previously filled template.
out()第二个可选参数可以指定以字符串形式返回模板内容,而不是将其直接刷新到浏览器,您可以利用该优势将一个模板中的占位符替换为先前填充的模板。
cURL is robust library for communicating over various protocols. It certainly is very full-featured, and there are times when nothing else will do. If you explicitly need functionality as exposed by cURL to accomplish your task, then use cURL! But the majority of day-to-day cURL usage in PHP revolves around issuing HTTP GET and POST requests, something that can be done easily with built-in PHP functions.
cURL是用于通过各种协议进行通信的强大库。 它的功能当然很全,而且有时候没有其他可做的事情。 如果您明确需要cURL公开的功能来完成任务,请使用cURL! 但是,PHP中日常使用的cURL大部分都与发出HTTP GET和POST请求有关,这可以通过内置PHP函数轻松完成。
The problem with relying on cURL for issuing HTTP requests is two-fold: 1) there of often many options that need to be set, even for the simplest of transactions, and 2) it is an extension that may or may not be available depending on your hosting and installation situation; it is a common extension, but one that is not enabled by default.
依靠cURL发出HTTP请求的问题有两个方面:1)即使是最简单的事务,通常也需要设置许多选项,并且2)它是一个扩展,可能会或可能不会可用,具体取决于您的托管和安装情况; 它是一个常见的扩展名,但默认情况下未启用。
file_get_contents() and stream_context_create() are two native PHP functions that have been available since the 4.3 days. Together, they can be used to perform many of the same types of requests commonly done via cURL.
file_get_contents()和stream_context_create()是自4.3天以来可用的两个本机PHP函数。 它们可以一起用于执行通常通过cURL完成的许多相同类型的请求。
For basic GET requests, file_get_contents() can be used by itself:
对于基本的GET请求,可以单独使用file_get_contents() :
<?php $html = file_get_contents("http://example.com/product/42");For requests where you need to specify HTTP headers, be it GET or any of the other HTTP methods, you can create a context by passing a specially-keyed array to stream_context_create() and then pass the context to file_get_contents().
对于需要指定HTTP标头(例如GET或其他任何HTTP方法)的请求,可以通过将特殊键的数组传递给stream_context_create()来创建上下文,然后将上下文传递给file_get_contents() 。
<?php $context = stream_context_create(array( "http" => array( "method" => "POST", "header" => "Content-Type: multipart/form-data; boundary=--foorn", "content" => "--foorn" . "Content-Disposition: form-data; name="myFile"; filename="image.jpg"rn" . "Content-Type: image/jpegrnrn" . file_get_contents("image.jpg") . "rn" . "--foo--" ) )); $html = file_get_contents("http://example.com/upload.php", false, $context);The example above shows uploading a file via POST, with the context array specifying the necessary information for the transaction using the keys “method”, “header”, and “content”.
上面的示例显示了通过POST上传文件的过程,其中上下文数组使用键“ method”,“ header”和“ content”为事务指定了必要的信息。
When using file_get_contents() for complex requests such as file uploads, it can be helpful to first make a mock web form and run it through Firefox with firebug enabled or something similar and then inspect what was included in the request. From there you can deduce the important header elements to include.
当对复杂请求(例如文件上传file_get_contents()使用file_get_contents() ,首先制作一个模拟Web表单并在启用了Firebug或类似功能的Firefox中运行它,然后检查请求中包含的内容可能会有所帮助。 从那里您可以推断出要包含的重要标题元素。
Hopefully you’ve found the snippets presented in this article interesting. They showcase creative problem solving and using PHP’s built-in functionality to new effect. I hope you find them useful and inspiring. And if you have inspiring snippets of your own, feel free to share in the comments below.
希望您发现本文介绍的摘录很有趣。 他们展示了创造性的问题解决方案,并使用PHP的内置功能取得了新的效果。 我希望您发现它们有用和启发。 如果您有自己的启发性片段,请随时在下面的评论中分享。
Image via Fotolia
图片来自Fotolia
翻译自: https://www.sitepoint.com/5-inspiring-and-useful-php-snippets/
相关资源:jdk-8u281-windows-x64.exe