5

I am building a PHP CMS system that parses template files and replaces tags with content. Sometimes this content is a HTML, CSS or JS snippet, but it can also be a code include.

Most code includes use dependencies, already set in the main scope: the app class, where the start() function resides and all needed domain objects are loaded. Some of these objects are: site, URL, page, etc..

The PHP scripts are included in a different scope, so I am can't access the dependencies the way I want -> from the app class.

I am thinking about Dependency Injection using a dependency container class, but of course, this is not visible when working inside an include.

How do I keep the dependencies accessible in an intuitive way?

Code example:

class app {

    protected $dependencyContainer;

    function __construct() {
        $this->dependencyContainer = new dependencyContainer();
    }

    // Called by index.php
    public function start() {

        // Load in navigator that contains routing information
        $this->dependencyContainer->set('navigator', new navigator($_SERVER['REQUEST_URI'], $_SERVER['HTTP_HOST']));

        // Load site data 
        $domainController = new domainController();
        $site = $domainController->loadSite($this->dependencyContainer->get('navigator'));
        $this->dependencyContainer->set('site', $site);

        $pageController = new pageController();
        $page = $pageController->loadPage($this->dependencyContainer->get('navigator'));
        $this->dependencyContainer->set('page', $page);

        // Etc...
        // Etc...

        $templatePath = $site->getTemplate();
        $this->renderDocument($templatePath);
    }

    private function renderDocument($templatePath) {       
        $template = file_get_contents($templatePath);

        $lines = explode("\n", $template);

        foreach($lines as $line) {                    
            // If a tag is found, the dependencies are asked if it contains data for this 
            if($tag = $this->filter($line)) {
                $fragments = $this->dependencyContainer->output($tag);

                foreach($fragment as $fragment) {
                    if($fragment->needDependencies()) {


                        // AT THIS POINT I TRAVERSE INTO AN OBJECT AND 
                        // INCLUDE A PHP SCRIPT

                        $fragment->render($this->dependencyContainer);
                    } else {
                        $fragment->render();
                    }
                }
            // Process lines, echo the ones that are plain HTML
            } else {
                echo $line;
            }
         }
    }
}

The fragment object that the dependencies are passed to:

class dependencyFragment {
    protected $data;
    const NEEDSDEPENDENCIES = true;

    // THIS IS THE LOCAL SCOPE OF THE INCLUDE:
    public function render($dependencies) {
        return include __PATH__ . $this->data;
    }
}

A script file that gets included:

<?php

// Do I comment in every script file that the variable $dependencies is set and is usable?
// And just call it like this?
$dependencies->get('page')...

I have the feeling this is very hard to understand without first understanding how and where the dependencies are set and injected?

Is this usual way to go?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.