简体   繁体   中英

Have PHP child classes add items to a shared array which is stored on the parent class

Have PHP child classes add items to a shared array which is stored on the parent class.

Then at the end of load, have the parent class access all the items in that array that are added to it from all its child classes.

IN human terms, a Plugin system will allow Plugin classes to extend a parent abstract Plugin class which allows them to add JavaScript files to an array and at the end will load all the JS files from all the plugins into a page.

<?php

class BookmarksPlugin extends Plugins{

    public function __construct(){        
        // add 2 JS files to array property on parent Plugins class
        $this->enqueue_js_file('file-key1', 'fdg/dgdfg/jas-file-1.js', 1);
        $this->enqueue_js_file('file-key2', 'fdg/dgdfg/js-file-2.js', 7);

        //parent::enqueue_js_file('file-key1', 'fdg/dgdfg/jas-file-1.js', 1);
        //parent::enqueue_js_file('file-key2', 'fdg/dgdfg/js-file-2.js', 7);
    }
}

class SnippetsPlugin extends Plugins{

    public function __construct(){        
        // add 2 JS files to array property on parent Plugins class
        $this->enqueue_js_file('file-key3', 'fdg/dgdfg/jas-file-3.js', 1);
        $this->enqueue_js_file('file-key4', 'fdg/dgdfg/js-file-4.js', 7);

        //parent::enqueue_js_file('file-key3', 'fdg/dgdfg/jas-file-3.js', 1);
        //parent::enqueue_js_file('file-key4', 'fdg/dgdfg/js-file-4.js', 7);
    }
}




abstract class Plugins{

    private $_js_files = array();

    public function __construct(){
    }


    public function load_js_script_files(){
        $html = '';
        usort($this->_js_files, array($this, 'sortJSFiles'));

        foreach ($this->_js_files as $obj => $jsScript) {
          //$jsScript->script_key = $script_key;
          //$jsScript->file_source = $file_source;
          $html .= '<script type="text/javascript" src="'.$jsScript->file_source.'"></script>\n';
          $html .= 'script type="text/javascript" src="'.$jsScript->file_source.'"></script>\n';
        }
        return $html;
    }


    public function enqueue_js_file($script_key, $file_source, $load_order = 0){
        $jsScript = new \stdClass;
        $jsScript->load_order = $load_order;
        $jsScript->script_key = $script_key;
        $jsScript->file_source = $file_source;
        $this->_js_files[$script_key] = $jsScript;
    }

    public function sortJSFiles($a, $b)
    {
        if ($a->load_order == $b->load_order) {
            return 0;
        }
        return ($a->load_order < $b->load_order) ? -1 : 1;
    }


}




$bookmarksPlugin = new BookmarksPlugin;

$snippetsPlugin = new SnippetsPlugin;


// this function is in the core plugin class to include all the JS files that 
// are added to the array property from the other plugins.
// 
// Of course it doesnt work as it is flawed and that is where I am asking for help
// How can I make all my plugins add JS files to a single shared array and when done
// have it load all those JS files declared by all the plugins?
echo $plugin->load_js_script_files();


?>

How about this using traits or a variant thereof. Basically merge the scripts from each plugin before rendering them.

class JsScript
{
    public $name;
    public $src;
    public $order;

    public function __construct($name, $src, $order)
    {
        $this->name  = $name;
        $this->src   = $src;
        $this->order = $order;
    }
}

trait JsLoader
{
    protected $scripts;

    public function getScripts()
    {
        return $this->_js_scripts;
    }

    public function enqueJs(JsScript $script)
    {
        $this->_js_scripts[] = $script;
    }

    public function renderScripts()
    {
        usort($this->_js_scripts, array($this, 'sortScripts'));
        foreach($this->_js_scripts as $script)
        {
            echo $script->src;
        }

    }

    protected function sortScripts($a, $b)
    {
        if ($a->order == $b->order) {
            return 0;
        }

        return ($a->order < $b->order) ? -1 : 1;
    }
}

class PluginRenderer
{
    use JsLoader
    {
        renderScripts as jsLoaderRenderScripts;
    }

    protected $plugins;

    public function __construct(array $plugins)
    {
        $this->plugins = $plugins;
    }

    public function renderScripts()
    {
        $scripts = array();
        foreach($this->plugins as $plugin) {
            $scripts = array_merge($scripts, $plugin->getScripts());
        }
        $this->_js_scripts = $scripts;
        $this->jsLoaderRenderScripts();
    }
}

class BookmarkPlugin {
    use JsLoader;
}
class SnippetsPlugin {
    use JsLoader;
}

Example use:

$bPlugin = new BookmarkPlugin;
$bPlugin->enqueJs(new JsScript('foo', 'foo/bar/baz', 99));
$bPlugin->enqueJs(new JsScript('big', 'big/fat/mama', 2));

$sPlugin = new SnippetsPlugin;
$sPlugin->enqueJs(new JsScript('y', 'y/u/no', 2));

$renderer = new PluginRenderer(array($bPlugin, $sPlugin));
$renderer->renderScripts();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM