【问题标题】:Add Scripts and Show them in runtime添加脚本并在运行时显示它们
【发布时间】:2015-09-15 14:31:06
【问题描述】:

我想做这样的事情:

<?php
function addScript($name, $url) {
   $scripts[$name] = $url;
}

function displayScripts() {
 foreach ($scripts as $name => $url) {
  echo '<!-- Script: '.$name.' -->';
  echo '<script src="'.$url.'"></script>'
 }
}

诀窍是:当用户想在他们的 classes.php 中添加脚本时,他们只需调用 addScript('jQuery','http...');

页面生成时,会调用函数displayScripts();,并将所有Scripts扔到文件头。

出于显而易见的原因,我通常只会传递$scripts 数组,但我不希望用户这样做。还有displayScripts() 怎么知道$scripts 数组呢?

我希望用户只调用 addScript('jQuery','http...'); 而没有来自 my 代码的逻辑。

问题是,数组 $scripts 应该类似于 global,但据我所知,您应该避免使用 global $var

有人知道怎么做吗?

【问题讨论】:

    标签: php


    【解决方案1】:

    这是variable scope 的问题,理论上您可以在全局范围内为您的脚本设置一个数组,然后您的其他函数和整个文件都可以访问该数组:

    <?php
    // globally defined
    $scripts = array();
    
    function addScript($script) {
        global $scripts;
        $scripts[] = $script;
    }
    ...
    

    等等。这显然会污染全局空间,并且所有类型的 ovf 变量都将可用,从而有效地声明这些变量名无法安全使用。

    更好的解决方案是使用某种类型的注册表。理想情况下,您将创建某种容器并跟踪此注册表。但是为了举例,我们只使用标准的单例模式。 see this SO question for more info

    class Scripts
    {
        // static instance tracker
        protected static $instance;
    
        // the registry for the scripts
        protected $scripts = array();
    
        // static function to fetch the instance
        public static function getInstance()
        {
            if (!self::$instance) self::$instance = new Scripts();
            return self::$instance;
        }
    
        // protected constructor, we dont want anybody to create an instance
        protected function __construct() {}
    
        public function addScript($script) {
            $this->scripts[] = $script;
            return $this;
        }
    
        public function getScripts() {
            return $this->scripts;
        }
    
        public function renderTags() {
            foreach ($this->scripts as $script) {
                // render the html <script> tags and return html
            }
        }
    }
    

    现在您有了一个安全的注册表,您可以在其中存储您的脚本,在您包含该类的任何地方都可以使用:

    // somewhere in the code
    Scripts::getInstance()->addScript('jquery.js')->addScript('jquery.ui.js');
    
    // in the view rendering stage:
    echo Scripts::getInstance()->renderTags();
    

    我鼓励您阅读设计模式和单例,因为从长远来看,后者确实会带来一些问题。你可以在this SO question找到更多信息

    【讨论】:

    • 第一:感谢您的回答!你能帮我解决这个问题:getIntance() 是做什么的?为什么我必须像Scripts::getInstance()-&gt;add... 那样称呼它而不像@Rocket Hazmat 所说的$scripts-&gt;add... (在创建$scripts = new...之后)谢谢!
    • 在另一个答案中,您仍然必须处理全局范围内的一个实例,通过使用单例,您可以通过拥有一个跟踪其自己的单个实例的类来避免这种情况。这也是您需要getInstance 方法的原因。 have a look here
    • 我收到此错误:致命错误:Call to undefined method Scripts::getInstance() in /var/www/html/test/classes/scripts.php in line
    • 对不起,我的函数名有错别字... :) 我已经更新了答案
    【解决方案2】:

    您可以在类中执行此操作,因此 $scripts 变量可用于每个方法:

    <?php
    class Scripts{
        public $scripts = array();
    
        function addScript($name, $url) {
            $this->scripts[$name] = $url;
        }
    
        function displayScripts() {
            foreach ($this->scripts as $name => $url) {
                echo '<!-- Script: '.$name.' -->';
                echo '<script src="'.$url.'"></script>'
            }
        }
    }
    

    然后你可以像这样使用它:

    $sm = new Scripts;
    $sm->addScript('jQuery', '...');
    
    $sm->displayScripts();
    

    【讨论】:

    • 感谢您的回答,看起来不错!有什么原因,我可以避开开头的$sm-&gt;
    • 在本例中,$sm-&gt; 是必需的,因为方法是类对象的一部分。如果你正在使用一个类,你不能只做addScript(...)
    猜你喜欢
    • 2010-10-07
    • 2013-07-26
    • 2011-12-11
    • 2017-05-15
    • 1970-01-01
    • 2019-10-08
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多