PHP 日本會議 2024

parse_str

(PHP 4, PHP 5, PHP 7, PHP 8)

parse_str將字串解析成變數

描述

parse_str(字串 $string, 陣列 &$result): void

解析 string,如同它是透過 URL 傳遞的查詢字串,並在目前作用域中設定變數(或在提供了 result 時設定在陣列中)。

參數

string

輸入字串。

result

如果存在第二個參數 result,則變數將儲存在此變數中,作為陣列元素。

警告

從 PHP 7.2 開始,不使用 result 參數使用此函式是高度不建議已棄用的。從 PHP 8.0.0 開始,result 參數是強制性的。

回傳值

不回傳任何值。

變更日誌

版本 描述
8.0.0 result 不再是可選的。
7.2.0 不使用第二個參數的情況下使用 parse_str() 現在會發出 E_DEPRECATED 通知。

範例

範例 #1 使用 parse_str()

<?php
$str
= "first=value&arr[]=foo+bar&arr[]=baz";

// 建議用法
parse_str($str, $output);
echo
$output['first']; // value
echo $output['arr'][0]; // foo bar
echo $output['arr'][1]; // baz

// 不建議用法
parse_str($str);
echo
$first; // value
echo $arr[0]; // foo bar
echo $arr[1]; // baz
?>

因為 PHP 中的變數名稱不能包含點號和空格,這些會被轉換為底線。如果使用帶有 result 參數的此函式,則對應的鍵名稱也會套用相同的規則。

範例 #2 parse_str() 名稱處理

<?php
parse_str
("My Value=Something");
echo
$My_Value; // Something

parse_str("My Value=Something", $output);
echo
$output['My_Value']; // Something
?>

備註

注意:

所有建立的變數(或如果設定了第二個參數,則回傳到陣列中的值)都已經經過 urldecode() 處理。

注意:

若要取得目前的 QUERY_STRING,您可以使用變數 $_SERVER['QUERY_STRING']。此外,您可能需要閱讀關於來自外部來源的變數的章節。

參見

新增註解

使用者貢獻的註解 31 則註解

Evan K
17 年前
值得一提的是,當涉及到重複欄位時,parse_str 內建函式並不會以 CGI 標準方式處理查詢字串。如果查詢字串中存在多個同名的欄位,其他所有網頁處理語言都會將它們讀取到陣列中,但 PHP 會靜默地覆寫它們。

<?php
# 無聲地未能處理多個值
parse_str('foo=1&foo=2&foo=3');

# 上述會產生:
$foo = array('foo' => '3');
?>

相反地,PHP 使用非標準的慣例,在欄位名稱中包含括號來達到相同的效果。

<?php
# 奇怪的 PHP 特有行為
parse_str('foo[]=1&foo[]=2&foo[]=3');

# 上述會產生:
$foo = array('foo' => array('1', '2', '3') );
?>

對於任何習慣 CGI 標準的人來說,這可能會造成混淆,所以請記住這一點。作為替代方案,我使用「正確」的查詢字串解析器函式。

<?php
function proper_parse_str($str) {
# 結果陣列
$arr = array();

# 以最外層的分隔符號分割字串
$pairs = explode('&', $str);

# 迴圈處理每個配對
foreach ($pairs as $i) {
# 分割成名稱和值
list($name,$value) = explode('=', $i, 2);

# 如果名稱已存在
if( isset($arr[$name]) ) {
# 將多個值放入陣列
if( is_array($arr[$name]) ) {
$arr[$name][] = $value;
}
else {
$arr[$name] = array($arr[$name], $value);
}
}
# 否則,直接放入純量值
else {
$arr[$name] = $value;
}
}

# 返回結果陣列
return $arr;
}

$query = proper_parse_str($_SERVER['QUERY_STRING']);
?>
Roemer Lievaart
2 年前
如果你需要保留鍵名,並且不希望空格或 . 或不匹配的 [ 或 ] 被替換為底線,但又想要 parse_str() 的所有其他好處,例如將匹配的 [] 轉換為陣列元素,你可以使用此程式碼作為基礎。

<?php
const periodPlaceholder = 'QQleQPunT';
const
spacePlaceholder = 'QQleQSpaTIE';

function
parse_str_clean($querystr): array {
// 不會將空格和點等轉換為底線。
$qquerystr = str_ireplace(['.','%2E','+',' ','%20'], [periodPlaceholder,periodPlaceholder,spacePlaceholder,spacePlaceholder,spacePlaceholder], $querystr);
$arr = null ; parse_str($qquerystr, $arr);

sanitizeKeys($arr, $querystr);
return
$arr;
}

function
sanitizeKeys(&$arr, $querystr) {
foreach(
$arr as $key=>$val) {
// 將值還原為原始值
$newval = $val ;
if (
is_string($val)) {
$newval = str_replace([periodPlaceholder,spacePlaceholder], ["."," "], $val);
}

$newkey = str_replace([periodPlaceholder,spacePlaceholder], ["."," "], $key);

if (
str_contains($newkey, '_') ) {

// 將點、空格或 [ 或 ] 轉換為 _。使用查詢字串還原。
$regex = '/&('.str_replace('_', '[ \.\[\]]', preg_quote($newkey, '/')).')=/';
$matches = null ;
if (
preg_match_all($regex, "&".urldecode($querystr), $matches) ) {

if (
count(array_unique($matches[1])) === 1 && $key != $matches[1][0] ) {
$newkey = $matches[1][0] ;
}
}
}
if (
$newkey != $key ) {
unset(
$arr[$key]);
$arr[$newkey] = $newval ;
} elseif(
$val != $newval )
$arr[$key] = $newval;

if (
is_array($val)) {
sanitizeKeys($arr[$newkey], $querystr);
}
}
}

?>

例如

parse_str_clean("code.1=printr%28hahaha&code 1=448044&test.mijn%5B%5D%5B2%5D=test%20Roemer&test%5Bmijn=test%202e%20Roemer");

產生

array(4) {
["code.1"]=>
string(13) "printr(hahaha"
["code 1"]=>
string(6) "448044"
["test.mijn"]=>
array(1) {
[0]=>
array(1) {
[2]=>
string(11) "test Roemer"
}
}
["test[mijn"]=>
string(14) "test 2e Roemer"
}

而如果你將相同的查詢字串提供給 parse_str,你將會得到

array(2) {
["code_1"]=>
string(6) "448044"
["test_mijn"]=>
string(14) "test 2e Roemer"
}
shagshag
12 年前
描述中沒有提到,但 max_input_vars 指令會影響此函數。如果字串上的輸入變數多於此指令指定的數量,則會發出 E_WARNING,並且請求中的其他輸入變數將被截斷。
zweibieren at yahoo dot com
9 年前
如果提供了 arr 參數,則會移除其所有現有元素。
alxcube at gmail dot com
8 年前
如果你需要自訂的參數分隔符號,可以使用此函數。它會以關聯陣列的形式返回已解析的查詢。

<?php

/**
* 將 HTTP 查詢字串解析為陣列
*
* @author Alxcube <alxcube@gmail.com>
*
* @param string $queryString 要解析的字串
* @param string $argSeparator 查詢參數分隔符
* @param integer $decType 解碼類型
* @return array
*/
function http_parse_query($queryString, $argSeparator = '&', $decType = PHP_QUERY_RFC1738) {
$result = array();
$parts = explode($argSeparator, $queryString);

foreach (
$parts as $part) {
list(
$paramName, $paramValue) = explode('=', $part, 2);

switch (
$decType) {
case
PHP_QUERY_RFC3986:
$paramName = rawurldecode($paramName);
$paramValue = rawurldecode($paramValue);
break;

case
PHP_QUERY_RFC1738:
default:
$paramName = urldecode($paramName);
$paramValue = urldecode($paramValue);
break;
}


if (
preg_match_all('/\[([^\]]*)\]/m', $paramName, $matches)) {
$paramName = substr($paramName, 0, strpos($paramName, '['));
$keys = array_merge(array($paramName), $matches[1]);
} else {
$keys = array($paramName);
}

$target = &$result;

foreach (
$keys as $index) {
if (
$index === '') {
if (isset(
$target)) {
if (
is_array($target)) {
$intKeys = array_filter(array_keys($target), 'is_int');
$index = count($intKeys) ? max($intKeys)+1 : 0;
} else {
$target = array($target);
$index = 1;
}
} else {
$target = array();
$index = 0;
}
} elseif (isset(
$target[$index]) && !is_array($target[$index])) {
$target[$index] = array($target[$index]);
}

$target = &$target[$index];
}

if (
is_array($target)) {
$target[] = $paramValue;
} else {
$target = $paramValue;
}
}

return
$result;
}

?>
php at voodoolabs dot net
17 年前
這可能是一個比下面更好的解決方案。第一行確保檔案不存在,然後第二行將所有請求導向一個腳本。使用此方法也不需要輸出 200 標頭。

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
kent at nospam dot ioflux dot com
19 年前
您可能需要將查詢字串解析為陣列。

<?php
/**
* 類似於 parse_str。如果查詢字串或 URL 為空,則返回 false。因為我們不是解析到變數,而是解析到陣列的鍵值條目,這個函式會「正確地」處理 ?[]=1&[]=2。
*
* @return array 類似於 PHP 自動產生的 $_GET 格式。
* @param string $url 查詢字串或 URL
* @param boolean $qmark 尋找並移除字串中問號之前的所有內容
*/
function parse_query_string($url, $qmark=true)
{
if (
$qmark) {
$pos = strpos($url, "?");
if (
$pos !== false) {
$url = substr($url, $pos + 1);
}
}
if (empty(
$url))
return
false;
$tokens = explode("&", $url);
$urlVars = array();
foreach (
$tokens as $token) {
$value = string_pair($token, "=", "");
if (
preg_match('/^([^\[]*)(\[.*\])$/', $token, $matches)) {
parse_query_string_array($urlVars, $matches[1], $matches[2], $value);
} else {
$urlVars[urldecode($token)] = urldecode($value);
}
}
return
$urlVars;
}

/**
* parse_query_string 的實用函式。給定一個結果陣列、一個起始鍵和一組格式如 "[a][b][c]" 的鍵,以及最終的值,使用正確的 PHP 陣列鍵更新結果陣列。
*
* @return void
* @param array $result 要從查詢字串填入的結果陣列
* @param string $k 要在 $result 中填入的起始鍵
* @param string $arrayKeys 要解析的鍵列表,格式為 "[][a][what%20ever]"
* @param string $value 要放在目標陣列鍵中的值
*/
function parse_query_string_array(&$result, $k, $arrayKeys, $value)
{
if (!
preg_match_all('/\[([^\]]*)\]/', $arrayKeys, $matches))
return
$value;
if (!isset(
$result[$k])) {
$result[urldecode($k)] = array();
}
$temp =& $result[$k];
$last = urldecode(array_pop($matches[1]));
foreach (
$matches[1] as $k) {
$k = urldecode($k);
if (
$k === "") {
$temp[] = array();
$temp =& $temp[count($temp)-1];
} else if (!isset(
$temp[$k])) {
$temp[$k] = array();
$temp =& $temp[$k];
}
}
if (
$last === "") {
$temp[] = $value;
} else {
$temp[urldecode($last)] = $value;
}
}

/**
* 將字串分解為一對,用於通用的解析函式。
*
* 如果找到字串對,則會將傳入的字串截斷為左半部分,右半部分(如果有的話)則會被返回。
*
* 以下是一個使用範例:
* <code>
* $path = "Account.Balance";
* $field = string_pair($path);
*
* $path 為 "Account"
* $field 為 "Balance"
*
* $path = "Account";
* $field = string_pair($path);
*
* $path 為 "Account"
* $field 為 false
* </code>
*
* @return string 如果找到分隔符,則返回字串的「右」部分。
* @param string $a 要分解為一對的字串。如果找到分隔符,則此處返回字串的「左」部分。
* @param string $delim 用於分隔字串對的字元
* @param mixed $default 如果在字串中找不到分隔符,則返回的值
* @desc
*/
function string_pair(&$a, $delim='.', $default=false)
{
$n = strpos($a, $delim);
if (
$n === false)
return
$default;
$result = substr($a, $n+strlen($delim));
$a = substr($a, 0, $n);
return
$result;
}

?>
Olivier Mengué
18 年前
Vladimir:這個函式在處理 &amp; 方面沒問題。
&amp; 只能在 HTML/XML 資料中輸出 URL 時使用。
您應該問問自己,當您將 URL 傳遞給 parse_str 時,為何 URL 中會有 &amp;。
Tore Bj?lseth
19 年前
從 PHP 5 開始,您可以使用 http_build_query() 來執行完全相反的操作。請記得使用可選的陣列輸出參數。

如果您想要重複使用搜尋字串 URL,但又想稍微修改它,這是一個非常有用的組合。

範例
<?
$url1 = "action=search&interest[]=sports&interest[]=music&sort=id";
$str = parse_str($url1, $output);

// 修改條件
$output['sort'] = "interest";

$url2 = http_build_query($output);

echo "<br>url1: ".$url1;
echo "<br>url2: ".$url2;
?>

結果為
url1: action=search&interest[]=sports&interest[]=music&sort=id
url2: action=search&interest[0]=sports&interest[1]=music&sort=interest

(會自動建立陣列索引。)
tobsn at php dot net
16 年前
關於以上範例的溫馨提醒
?var[]=123 - [] 必須經過 URL 編碼。
變數名稱和變數值 - 都必須經過 URL 編碼!
avi at amarcus dot com
19 年前
如果您嘗試保留複雜的陣列,serialize 函式可能會比 http_build_query 或其他建立查詢字串的方法更好。
helpmepro1 at gmail dot com
16 年前
<?
//by shimon doodkin

$url_form=url_to_form($url);
echo '<form action="'.$url_form['action'].'" method="get">';
echo $url_form['hidden'];
echo '<input name="otherfiled" type="text">';
echo '<input type="submit">';
echo '</form>';

function url_to_form($url)
{
$url=split('\?',$url,2);
$action=$url[0];
$hidden="";
if(isset($url[1]))
{
$pairs=split('&',$url[1]);
foreach($pairs as $pair)
{
$pair=split('=',$pair,2);
$name=$pair[0];
if(isset($pair[1]))
$value=$pair[1];
else
$value='';
$name=$name;
$value=htmlspecialchars($value);
if($name!='')
$hidden.='<hidden name="'.$name.'" value="'.$value.'">';
}
}
return array('action'=>$action,'hidden'=>$hidden);
}

?>
jgbreezer at gmail dot com
17 年前
Vladimir Kornea 在 2006 年 9 月 8 日寫道
「這個函式會因為與號 (&) 被編碼為 HTML 實體 (&amp;) 而感到困惑」

嗯,的確會這樣 - 它不應該傳遞 HTML 實體,那是不同的編碼方式。不過,這個函式會正確地為您解碼 URL 編碼的參數(使用 rawurlencode 而不是 urlencode,也就是說 '+' 會被轉換為空格)。
jrgns at jadeit dot co dot za
12 年前
在呼叫函式之前,不需要定義要填入的陣列。

<?php
error_reporting
(E_ALL | E_STRICT);
parse_str('var=value', $array);
?>

這不會產生通知。
PEPE_RIVAS at repixel dot net
18 年前
將任何格式化的字串轉換為變數

我開發了一個線上信用卡付款解決方案,使用商家,而該商家會像這樣返回我交易狀態的答案

estado=1,txnid=5555444-8454445-4455554,monto=100.00

對我來說,將所有資料放入變數中應該是可以的!所以我使用了 str_replace(),問題是這個函式會使用 & 字元來識別每一組變數...而我的值是以逗號分隔的...所以我將逗號替換為 &

<?php
$string
= "estado=1,txnid=5555444-8454445-4455554,monto=100.00";
$string = str_replace(",","&",$string);
parse_str($string);
echo
$monto; // 輸出 100.00
?>
StanE
9 年前
請注意,字元 "." 和 " " (空白字元) 會被轉換為 "_"。字元 "[" 和 "]" 具有特殊含義:它們代表陣列,但似乎有一些奇怪的行為,我不太明白。

<?php
// 注意: "[" = %5B, "]" = %5D

/*
"v][=a" 會產生 ( "[" 被替換為 "_" ):
Array
(
[v]_] => a
)
*/
parse_str("v%5D%5B=a", $r);
print_r($r);

/*
"v][[=a" 會產生 (第一個 "[" 被替換為 "_",但並非所有後續的 "[" ):
Array
(
[v]_[] => a
)
*/
parse_str("v%5D%5B%5B=a", $r);
print_r($r);

?>
mike dot coley at inbox dot com
17 年前
這裡有一個小函式可以執行與 parse_str 函式相反的操作。它會接收一個陣列並從中建立一個查詢字串。

<?php

/* 將參數陣列轉換為要附加到 URL 的查詢字串。
*
* @return string : 要附加到 URL 的查詢字串。
* @param array $array : 要附加到查詢字串的參數陣列。
* @param string $parent : 此參數應保留空白 (它會在函式內部使用)。
*/
function append_params($array, $parent='')
{
$params = array();
foreach (
$array as $k => $v)
{
if (
is_array($v))
$params[] = append_params($v, (empty($parent) ? urlencode($k) : $parent . '[' . urlencode($k) . ']'));
else
$params[] = (!empty($parent) ? $parent . '[' . urlencode($k) . ']' : urlencode($k)) . '=' . urlencode($v);
}

$sessid = session_id();
if (!empty(
$parent) || empty($sessid))
return
implode('&', $params);

// 如果需要,將 Session ID 附加到查詢字串。
$sessname = session_name();
if (
ini_get('session.use_cookies'))
{
if (!
ini_get('session.use_only_cookies') && (!isset($_COOKIE[$sessname]) || ($_COOKIE[$sessname] != $sessid)))
$params[] = $sessname . '=' . urlencode($sessid);
}
elseif (!
ini_get('session.use_only_cookies'))
$params[] = $sessname . '=' . urlencode($sessid);

return
implode('&', $params);
}

?>

請注意,如果需要,該函式也會將 Session ID 附加到查詢字串。
chris at mcfadyen dot ca
17 年前
我不應該發布原始版本,因為它只適用於最基本的查詢字串。

此函式會為變數和類似 PHP 的有序和關聯陣列解析一個 HTML 安全的類查詢 URL 字串。它會像 parse_str 一樣將它們放入全域範圍,並為資料庫插入新增最少的斜線,而不會產生 magic quotes 可能導致的三重斜線問題 (這是我必須編寫它的原因)。如果您不需要斜線,它們很容易移除。

<?php
function parse_query($str) {

// 分隔所有名稱-值對
$pairs = explode('&', $str);

foreach(
$pairs as $pair) {

// 取出名稱和值
list($name, $value) = explode('=', $pair, 2);

// 解碼變數名稱並尋找陣列
list($name, $index) = preg_split('/\[\]/', urldecode($name));

// 陣列
if(isset($index)) {

// 宣告或新增到 $name 定義的全域陣列
global $$name;
if(!isset($
$name)) $$name = array();

// 關聯陣列
if($index != "") {
${
$name}[$index] = addslashes(urldecode($value));

// 有序陣列
} else {
array_push($$name, addslashes(urldecode($value)));
}

// 變數
} else {

// 宣告或覆寫 $name 定義的全域變數
global $$name;
$
$name = addslashes(urldecode($value));
}
}
}
?>
chris at mcfadyen dot ca
17 年前
如果您想要一個沒有 magic quotes 的 parse_str 版本,可以使用以下方法

<?php
function parse_query($str) {
$pairs = explode('&', $str);

foreach(
$pairs as $pair) {
list(
$name, $value) = explode('=', $pair, 2);
global $
$name;
$
$name = $value;
}
}
?>
mortoray at ecircle-ag dot com
19 年前
在 Kent 的解決方案中,如果您想擺脫加號 '+' 轉換為空格 ' ' 的 [惱人] 轉換,您可能需要將 "urldecode" 切換為 "rawurldecode"。
kawewong at gmail dot com
3 年前
警告:`parse_str()` 可能會導致「輸入變數超過 1000」的錯誤 (1000 是 `max_input_vars` 的預設 php.ini 設定)。

測試程式碼。

<?php

$inputString
= 'first=firstvalue';

for (
$i = 1; $i <= 1100; $i++) {
$inputString .= '&arrLoopNumber[]=' . $i;
}
unset(
$i);

echo
'input string: <code>' . $inputString . '</code><br>' . PHP_EOL;
echo
'<h5>doing <code>parse_str()</code></h5>' . PHP_EOL;

$output = [];
parse_str($inputString, $output);
// errors!!
?>
twiddly
6 年前
proper_parse_str 運作良好,而且我喜歡它不會將空格取代為底線,但是應該要對 $value 進行 urldecode
Will Voelcker
14 年前
如果您需要一個功能類似於 parse_str,但不會將空格和點轉換為底線的函式,請嘗試以下方法:

<?php
function parseQueryString($str) {
$op = array();
$pairs = explode("&", $str);
foreach (
$pairs as $pair) {
list(
$k, $v) = array_map("urldecode", explode("=", $pair));
$op[$k] = $v;
}
return
$op;
}
?>

可能需要調整以處理各種邊緣情況。
motin at demomusic dot nu
18 年前
當您有腳本透過命令列執行時(例如透過 cron 本地執行),您可能希望能夠使用 _GET 和 _POST 變數。將此程式碼放在您排程任務檔案的頂部

<?
parse_str ($_SERVER['argv'][1], $GLOBALS['_GET']);
parse_str ($_SERVER['argv'][2], $GLOBALS['_POST']);
?>

並透過以下方式呼叫您的腳本

/usr/local/bin/php /path/to/script.php "id=45&action=delete" "formsubmitted=true"

乾杯!
Michal Zalewski
17 年前
Vladimir Kornea
嘗試使用 html_entity_decode()

$str = 'first=value&amp;arr[]=foo+bar&amp;arr[]=baz';
parse_str(html_entity_decode($str), $output);
print_r($output);

Array
(
[first] => value
[arr] => Array
(
[0] => foo bar
[1] => baz
)

)
lenix.de
17 年前
如果您想要使用 php/apache 取得良好的 URL 配置,並想在中央 php 腳本中處理所有請求,這有一個簡單的解決方案/技巧

在您的「basedir」中建立一個 .htaccess,其中您有您的主要腳本(在本範例中為 index.php),包含如下的行

"ErrorDocument 404 /index.php"

在 index.php 中,您現在可以執行

<?php
$virtual_path
= substr(
$_SERVER['REQUEST_URI'],
strlen( dirname( $_SERVER['PHP_SELF'] ) ) + 1
);
if( (
$pos = strpos( $virtual_path, '?' )) !== false ) {
parse_str( substr( $virtual_path, $pos + 1 ), $_GET );
$_REQUEST = array_merge( $_REQUEST, $_GET );
$virtual_path = substr( $virtual_path, 0, $pos );
}

// some code checking for a valid location, etc...
header( 'HTTP/1.1 200 OK' );
header( 'Content-Type: text/plain' );

echo
$virtual_path."\n\n";
print_r( $_REQUEST );
?>

// guido 'lenix' boehm
kerosuppi
19 年前
這並未如預期運作。

<?php
class someclass
{
var
$query_string;
function
someclass($a_query_string)
{
$this->query_string = $a_query_string;
parse_str($this->query_string);
}
function
output()
{
echo
$this->action;
}
}

$a_class = new someclass("action=go");
$a_class->output();
?>

請改用此方法。

<?php
class someclass
{
var
$arr;
function
someclass($a_query_string)
{
parse_str($a_query_string, $this->arr);
}
function
output()
{
echo
$this->arr['action'];
}
}

$a_class = new someclass("action=go");
$a_class->output();
?>
markc
11 年前
請注意,在具有以引用傳遞變數的函式中使用 parse_str。似乎 parse_str 實際上會建立新的變數,即使存在相同名稱的變數也是如此。如果您以引用傳遞的變數與正在解析的查詢字串中的變數名稱相同,則會建立新的 LOCAL 版本,並且您不會將任何值傳遞回呼叫者(與 Maikel 在下面提到的內容有關)

一個不切實際的範例(與我發現這個問題時正在執行的操作略有相關)...

function get_title($query,&$title)
{
parse_str($query);
$title=str_replace("_"," ",$title);
}

$title="foo";
$query = "context=something&title=Title_of_Something";
get_title($query,$title);

echo $title .... "foo"
Vladimir Kornea
17 年前
parse_str() 會被編碼為 HTML 實體 (&amp;) 的 & 符號 (&) 搞混。如果您從 HTML 頁面(抓取)中提取查詢字串,這會很相關。解決方案是在透過 parse_str() 執行字串之前,先透過 html_entity_decode() 執行字串。

(編輯者:我最初的評論是一個警告,其解決方案是顯而易見的,但它已經導致了三個回覆(「那又怎樣?」、「如預期的那樣」和「這是修復方法」)。請刪除之前處理此問題的四篇文章 (69529, 70234, 72745, 74818),並僅保留上述摘要。這個問題太瑣碎,不值得收到這麼多評論。)
anatilmizun at gmail dot com
20 年前
我撰寫了一對使用 parse_str() 的函式,可將陣列中的值寫入文字檔案,反之亦然,將這些值從文字檔案讀回陣列。如果您需要儲存大量資料但無法存取 SQL,這非常有用。

透過呼叫 cfg_save($filename,$array) 來儲存陣列,並使用 $array=cfg_load($filename) 將其載入回來

<?php
$newline
="?";

function
cfg_load($cfgfile){
global
$newline;
$setting="";
if(
file_exists($cfgfile)){
$setting=fopen($cfgfile, "r");
$ookk="";
while(
$ook=fgets($setting)){
#移除註解
$commt=strpos($ook,"##");
if(
$commt!==false) $ook=substr($ook,0,$commt);
#附加
if($ook!="") $ookk=$ookk."&". str_replace($newline,"\n",str_replace("&","%26",trim($ook)));
}
fclose($setting);
parse_str($ookk, $setting);
}
return
$setting;
}

function
cfg_save($cfgfile,$setting){
global
$intArray;
$intArray="";
for(
$i=0;$i<2000;$i++)
$intArray[]=$i;
if(
is_array($setting)){
$allkeys=array_keys($setting);
foreach(
$allkeys as $aKey)
cfg_recurse($setting[$aKey], $aKey, $outArray);
}
$cfgf=fopen($cfgfile,"w");
foreach(
$outArray as $aLine)
fputs($cfgf,stripslashes($aLine)."\r\n");
fclose($cfgf);
}

function
cfg_recurse($stuffIn, $keysofar, &$toAppend){
global
$intArray, $newline;
if(
is_array($stuffIn)){
$allkeys=array_keys($stuffIn);
if(
array_slice($intArray,0,sizeof($allkeys))==$allkeys)
$nokey=true;
else
$nokey=false;
foreach(
$allkeys as $aKey){
if(!
$nokey) $toKey=$aKey;
cfg_recurse($stuffIn[$aKey], $keysofar."[".$toKey."]", $toAppend);
}
}else
$toAppend[]=$keysofar."=".str_replace("\n",$newline,$stuffIn);
}
?>

請注意,這些函式支援無限層級的巢狀陣列 ;)
Benjamin Garcia
12 年前
類似 parse_str 的函式,但不會將 $_GET 和 $_POST 中的空格和點轉換為底線

/**
* 包含點等的 GET 和 POST 輸入。
*/
function getRealREQUEST() {
$vars = array();

$input = $_SERVER['REDIRECT_QUERY_STRING'];
if(!empty($input)){
$pairs = explode("&", $input);
foreach ($pairs as $pair) {
$nv = explode("=", $pair);

$name = urldecode($nv[0]);
$nameSanitize = preg_replace('/([^\[]*)\[.*$/','$1',$name);

$nameMatched = str_replace('.','_',$nameSanitize);
$nameMatched = str_replace(' ','_',$nameMatched);

$vars[$nameSanitize] = $_REQUEST[$nameMatched];
}
}

$input = file_get_contents("php://input");
if(!empty($input)){
$pairs = explode("&", $input);
foreach ($pairs as $pair) {
$nv = explode("=", $pair);

$name = urldecode($nv[0]);
$nameSanitize = preg_replace('/([^\[]*)\[.*$/','$1',$name);

$nameMatched = str_replace('.','_',$nameSanitize);
$nameMatched = str_replace(' ','_',$nameMatched);

$vars[$nameSanitize] = $_REQUEST[$nameMatched];
}
}

return $vars;
}
To Top