天天看點

5個鼓舞人心(且有用)PHP代碼段

“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"]

片段的确不是那麼有趣,并且用處不大。 取而代之的是,這裡有五個片段,您無疑會發現它們有趣且有用,并與激發它們的問題一起呈現。 我希望其中許多人的創造力能激發您在日常工作中編寫更好,更具創造力的代碼。

1.生成CSV (1. Generating CSV)

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變得輕松而簡單。

2.自動加載類 (2. Autoloading Classes)

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]

則可能是也可能不是空字元串。 由于下劃線在名稱空間部分中沒有特殊含義,是以盲目替換下劃線和反斜杠是不正确的,是以有必要辨別這些部分。

3.使用unpack()解析固定寬度的資料 (3. Parsing Fixed-Width Data with unpack())

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"]

4.模闆化HTML (4. Templating HTML)

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 >
 <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()

第二個可選參數可以指定以字元串形式傳回模闆内容,而不是将其直接重新整理到浏覽器,您可以利用該優勢将一個模闆中的占位符替換為先前填充的模闆。

5.使用file_get_contents作為cURL替代 (5. Using file_get_contents as a cURL Alternative)

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中運作它,然後檢查請求中包含的内容可能會有所幫助。 從那裡您可以推斷出要包含的重要标題元素。

摘要 (Summary)

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/