A variable variable
, chỉ là một dạng khác là reflection. Về cơ bản, bạn hỏi "Tại sao bạn lại muốn thay đổi một biến, nếu bạn không biết nó trước khi chạy".
Mặc dù về mặt kỹ thuật không giống nhau, bạn có thể thấy variable variable
là một loại khác nhau của hash table
(hoặc array
trong php). Hầu hết variable variables
có thể được viết lại dưới dạng hash table
và bạn sẽ không ngạc nhiên. Nhưng nếu bạn cần phải làm việc với một biến trước và sau khi chạy, thì hash table
thậm chí có thể còn tồi tệ hơn để làm việc.
Trường hợp sử dụng đơn giản có thể là cài đặt có thể được thay đổi bởi người dùng. Hãy ghi nhớ ví dụ sau là không an toàn như vậy, nhưng chứng tỏ đó là mục đích.
<?php
/*
Simple way, if you have a limited amount of settings
*/
$settings = array();
$settings["allowAccess"] = 1;
$settings["allowModify"] = 1;
$settings["allowDelete"] = 0;
if ($result = $mysqli->query("SELECT `allowAccess`, `allowModify`, `allowDelete` FROM `user_settings` LIMIT 1"))
{
$row = $result->fetch_array(MYSQLI_ASSOC);
$settings["allowAccess"] = $row["allowAccess"];
$settings["allowModify"] = $row["allowModify"];
$settings["allowDelete"] = $row["allowDelete"];
}
/*
Now consider you have a thousand settings and you dont want to write out every setting manually.
*/
if ($result = $mysqli->query("SELECT * FROM `user_settings` LIMIT 1"))
{
$row = $result->fetch_array(MYSQLI_ASSOC);
foreach($row as $key => $val) {
$settings[$key] = $val;
}
}
/*
Both options work, but everytime you want to use a setting you have to use something like below
*/
if ($settings["allowAccess"] && $settings["allowModify"] && $settings["allowDelete"]) {
unlink($somefile);
}
/*
Perhaps you would rather write
*/
if ($allowAccess && $allowModify && $allowDelete) {
unlink($somefile);
}
/*
Then you can use
*/
if ($result = $mysqli->query("SELECT * FROM `user_settings` LIMIT 1"))
{
$row = $result->fetch_array(MYSQLI_ASSOC);
foreach($row as $key => $val) {
//if you use extract, all columns are extracted, unless you drop them first. But perhaps you need those for something else.
//now I extract the columns that start with allow and keep the columns like id, created, modified, etc. without the need to specify each column manually, which makes it easier if you ever decide to add another setting column. You don't need to update this part of the code.
if (substr($key,0,5)=='allow') {
$$key = $val; //$key = 'allowAccess', $$key == $allowAccess = $val;
}
}
}
?>
Đây chỉ là một ví dụ, tôi tìm thấy một ví dụ khác trong số XHTML sanitizer for MediaWiki
bởi Brion Vibber
. Ông sử dụng rất nhiều mảng trong mã của mình và tại một thời điểm, ông cần phải lật tất cả chúng. Anh ấy đã sử dụng mã bên dưới:
<?php
$vars = array('htmlpairs', 'htmlsingle', 'htmlsingleonly', 'htmlnest', 'tabletags',
'htmllist', 'listtags', 'htmlsingleallowed', 'htmlelements');
foreach ($vars as $var) {
$$var = array_flip($$var);
}
?>
Bây giờ rõ ràng là anh ấy có thể viết mã bên dưới, nhưng thực sự dễ đọc hơn?
<?php
$htmlpairs = array_flip($htmlpairs);
$htmlsingle = array_flip($htmlsingle);
$htmlsingleonly = array_flip($htmlsingleonly);
$htmlnest = array_flip($htmlnest);
$tabletags = array_flip($tabletags);
$htmllist = array_flip($htmllist);
$listtags = array_flip($listtags);
$htmlsingleallowed = array_flip($htmlsingleallowed);
$htmlelements = array_flip($htmlelements);
?>
Trường hợp nào cũng giới thiệu trường hợp sử dụng khác: Nếu tôi muốn tự động quyết định mảng nào sẽ lật? Theo cách variable variable
, tôi chỉ có thể đẩy các mục vào mảng và lật chúng khi thời gian đến, theo cách "bình thường", tôi sẽ cần switch
hoặc if
để lặp qua mảng và sau đó thêm từng tùy chọn theo cách thủ công.
Chúng thường được gọi là biến số biến; và chỉ vì chúng tồn tại, không có nghĩa là bạn phải sử dụng chúng ... thường tôi khuyên bạn không nên sử dụng chúng, bởi vì luôn luôn có cách thay thế tốt hơn –
Dường như với tôi cũng rất khó đọc/theo dõi . –
Dựa trên rất nhiều câu hỏi ở đây, nơi mọi người đang cố gắng tìm ra cách sử dụng các biến biến, họ thường nên đặt tên cho các khóa mảng thay vì tạo các biến riêng biệt. –