2017-02-16 68 views
0

我目前正在編寫一門初級課程,主要關注PHP,在一次練習中我們將代碼從通過普通名稱空間包含模板改爲包含它通過一個函數使我們可以使用輸出緩衝。爲了使它工作,我們正在使用extract(),雖然我理解提取如何工作,但我很難理解爲什麼我們需要使用它來使包括的工作。在通過函數運行之前,我們不需要發送或提取新的變量。有人能夠解釋這背後的原因嗎?在使用輸出緩衝的PHP函數中使用extract()

這裏的功能是什麼樣子:

const TEMPLATE_EXTENSION = '.phtml'; 
const TEMPLATE_FOLDER = 'templates/'; 
const TEMPLATE_PREFIX = 'cart_view_'; 

function display($template, $variables, $extension = TEMPLATE_EXTENSION) { 
    extract($variables); 

    ob_start(); 
    include TEMPLATE_FOLDER . TEMPLATE_PREFIX . $template . $extension; 
    return ob_get_clean(); 
} 

下面是我們如何把它叫做:

<?php echo display('user', ['users' => $users, 'cart' => $cart]); ?> 
<?php echo display('item', ['new_item' => $new_item]); ?> 
<?php echo display('items', ['cart' => $cart]); ?> 

這裏還有什麼是在模板中我們包括:

<h2>New Item</h2> 
    <p><?php printf($new_item['name']);?> is $<?php printf($new_item['price']);?></p> 

<h2>User: <?php printf($cart['user']); ?></h2> 
    <p>ID: <?php printf($users[$cart['user']]['id']); ?></p> 
    <p>Email: <?php printf($users[$cart['user']]['email']); ?></p> 

<h2>Cart</h2> 

<?php foreach ($cart['items'] as $item) { 

    printf("<p>%s is $%d</p>\n", $item['name'], $item['price']); 

} ?> 

的變量是在已經包含在索引中的另一個文件中定義的。 以前使用的功能緩衝區之前,所有我們需要的是這樣的:

<?php include 'templates/cart_view_user.phtml'; ?> 
<?php include 'templates/cart_view_item.phtml'; ?> 
<?php include 'templates/cart_view_items.phtml'; ?> 

回答

0

功能也有自己的變量範圍。因此,當您創建display()函數時,它看不到其外部可用的變量。請參閱Variable Scopes in PHP。您正在使用extract()以便將數組轉換爲您調用它的範圍中的變量,例如:在函數中。

你的第一個解決方案很可能是這樣的(我做了變量):

$users = []; 
$cart = []; 

// you are including the template in the same scope as the variables are defined, aka it will "see"/have access to those variables 
include 'templates/cart_view_user.phtml'; 

現在你已經重構你的代碼和功能的移動包括邏輯。這個函數有它自己的局部範圍。

$users = []; 
$cart = []; 

function display($template, $variables, $extension = TEMPLATE_EXTENSION) { 
    // you don't have access to $users and $cart here as those are defined in the global scope 
    extract($variables); // <-- after this call you will have new variables created in the local function scope based on your $variables array 

    ob_start(); 
    include TEMPLATE_FOLDER . TEMPLATE_PREFIX . $template . $extension; 
    return ob_get_clean(); 
} 

所以,現在你將有兩個選擇,如果你知道你要提供你可以使用global關鍵字的功能裏面有什麼變數,但我不鼓勵使用它,它可能會導致莫名其妙的錯誤,當你不不明白爲什麼你的變量會被改變(ps後面你會轉向使用類,你不會有全局變量的頭痛)。

// you can drop $variables from the function signature 
function display($template, $extension = TEMPLATE_EXTENSION) { 
    global $users, $cart, $new_item; 
    // no extract needed, but please try not using global, it can lead to weird bugs 

    ob_start(); 
    include TEMPLATE_FOLDER . TEMPLATE_PREFIX . $template . $extension; 
    return ob_get_clean(); 
} 

或者您可以使用extract創造功能的範圍內的變量,所以當你包含的文件,他們將有機會獲得這些變量。在這裏要注意的是,extract將使用數組鍵作爲它創建的變量名稱。這就是爲什麼在這次調用後你傳遞display('user', ['users' => $users, 'cart' => $cart]);extract將在函數調用中創建一個$users和一個$cart變量。如果你用不同的數組鍵來調用它,如:display('user', ['u' => $users, 'c' => $cart]);包含的文件會抱怨它無法找到變量$users$cart

我希望這可以幫助,隨時問我是否在任何地方都不清楚。