Jump to content

How to create an intuitive interface for dependency management combined with code includes?


AbayoB

Recommended Posts

Heya,

 

I am building on 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 inside a different scope, so I 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 because the dependency container is defined in a different scope, this object is not visible when working inside an include file.

 

The question that arises is: 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;
    }
}

An include file would look like this:

<?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?

Also, a variable is not standing out into the page, which seems to be what I need here for readability.

 

I have searched in the Laravel Framework, but they use Facades, which I think looks awesome, but is to much work to implement ATM.

Static classes that are stateful, which is what the dependency container would be, are bad practice, is it not?

 

Pure based on readability, this looks great:

App::get('SomeClass');

This does not:

$app->get('SomeClass');

Are there more options to choose from?

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.