dougu1985 2017-02-16 12:34
浏览 30
已采纳

在PHP函数中使用extract(),它使用输出缓冲

I'm currently doing a beginner course in coding, mainly focusing on PHP and in one exercise we're changing our code from including a template through normal namespacing to instead including it via a function so that we can use output buffering. To make it work we are using extract() and although I understand how extract works, I struggle to see why we need to use it to make include work. Before running it via the function, we didn't need to send in or extract new variables. Is someone able to explain the reasons behind this?

Here's what the function looks like:

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

Here's how we call it:

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

And here's what's in the templates we're including:

<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>
", $item['name'], $item['price']);

} ?>

The variables are definied in another file which is already included in the index. Previously before using the function to buffer, all we needed was this:

<?php include 'templates/cart_view_user.phtml'; ?>
<?php include 'templates/cart_view_item.phtml'; ?>
<?php include 'templates/cart_view_items.phtml'; ?>
  • 写回答

1条回答 默认 最新

  • drqvr26084 2017-02-17 09:40
    关注

    Functions do have their own variable scope. So when you created the display() function, it doesn't see what variables are available outside of it. See more on Variable Scopes in PHP. You are using extract() in order to convert an array into variables in the scope where you are calling it from eg: in the function.

    Your first solution was probably something like this (I'm making up the variables):

    $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'; 
    

    Now you have refactored your code and moved the including logic in a function. This function has its own local scope.

    $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();
    }
    

    So now you would have two options if you know what variables you want to make available inside the function you could use the global keyword, but I would discourage using it, it could lead to weird bugs when you don't understand why your variables being changed (ps later you will move onto using classes and you won't have the headache of global variables).

    // 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();
    }
    

    Or you can use the extract to create variables in the function's scope so when you include the files they will have access to those variables. On thing to note here that extract will use the array keys as the variable names it is creating. That's why you are passing in display('user', ['users' => $users, 'cart' => $cart]); after this call, extract will create a $users and a $cart variable inside the function call. If you would call it with different array keys, like: display('user', ['u' => $users, 'c' => $cart]); the included file would complain that it can't find the variables $users and $cart.

    I hope this helped, feel free to ask more if I wasn't clear anywhere.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上
  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解