0

I am learning oop and trying to implement php standards PSR-0 & PSR-1 along the way. I have started by creating a small MVC framework based on Swiftlet.

I am trying to call functions from my base View controller within the Controller that I am calling from the url and I get 'Call to a member function set() on a non-object in'.

All the classes load ok. So in my controller I call $this->view->set('helloWorld', 'Hello world!'); but I get an error. I had some trouble trying to get the namespace structure right so maybe this is the cause?

Here is the file structure:

index.php

lib/bootstrap.php

lib/view.php

lib/controller.php

app/controllers/index.php

and here is the code for each:

index.php

<?php

namespace MVC;

    // Bootstrap the application
    require 'lib/Bootstrap.php';

    $app = new lib\Bootstrap;

    spl_autoload_register(array($app, 'autoload'));

    $app->run();
    $app->serve();

bootstrap.php

namespace MVC\lib;

class Bootstrap 
{
    protected
        $action     = 'index',
        $controller,
        $hooks      = array(),
        $view
        ;

    /**
     * Run the application
     */

    function run() 
    {
               ... Code that gets controller and the action form the url

        $this->view = new \lib\View($this, strtolower($controllerName));

        // Instantiate the controller
        $controllerName = 'app\Controllers\\' . basename($controllerName);

        $this->controller = new $controllerName();                      

        // Call the controller action
        $this->registerHook('actionBefore');

        if ( method_exists($this->controller, $this->action) ) {
            $method = new \ReflectionMethod($this->controller, $this->action);

            if ( $method->isPublic() && !$method->isFinal() && !$method->isConstructor() ) {
                $this->controller->{$this->action}();
            } else {
                $this->controller->notImplemented();
            }
        } else {
            $this->controller->notImplemented();
        }

        return array($this->view, $this->controller);

    }


<?php

namespace MVC\lib;

class Bootstrap 
{
    protected
        $action     = 'index',
        $args       = array(),
        $config     = array(),
        $controller,
        $hooks      = array(),
        $plugins    = array(),
        $rootPath   = '/',
        $singletons = array(),
        $view
        ;

    /**
     * Run the application
     */

    function run() 
    {
        // Determine the client-side path to root
        if ( !empty($_SERVER['REQUEST_URI']) ) {
            $this->rootPath = preg_replace('/(index\.php)?(\?.*)?$/', '', $_SERVER['REQUEST_URI']);

            if ( !empty($_GET['route']) ) {
                $this->rootPath = preg_replace('/' . preg_quote($_GET['route'], '/') . '$/', '', $this->rootPath);
            }
        }

        // Extract controller name, view name, action name and arguments from URL
        $controllerName = 'Index';

        if ( !empty($_GET['route']) ) {
            $this->args = explode('/', $_GET['route']);

            if ( $this->args ) {
                $controllerName = str_replace(' ', '/', ucwords(str_replace('_', ' ', str_replace('-', '', array_shift($this->args)))));
            }

            if ( $action = $this->args ? array_shift($this->args) : '' ) {
                $this->action = str_replace('-', '', $action);
            }
        }

        if ( !is_file('app/Controllers/'. $controllerName . '.php') ) {
            $controllerName = 'Error404';
        }

        $this->view = new \lib\View($this, strtolower($controllerName));

        // Instantiate the controller
        $controllerName = 'app\Controllers\\' . basename($controllerName);

        $this->controller = new $controllerName();                      

        // Call the controller action
        $this->registerHook('actionBefore');

        if ( method_exists($this->controller, $this->action) ) {
            $method = new \ReflectionMethod($this->controller, $this->action);

            if ( $method->isPublic() && !$method->isFinal() && !$method->isConstructor() ) {
                $this->controller->{$this->action}();
            } else {
                $this->controller->notImplemented();
            }
        } else {
            $this->controller->notImplemented();
        }

        $this->registerHook('actionAfter');

        return array($this->view, $this->controller);

    }

<?php

namespace MVC\lib;

class Bootstrap 
{
    protected
        $action     = 'index',
        $args       = array(),
        $config     = array(),
        $controller,
        $hooks      = array(),
        $plugins    = array(),
        $rootPath   = '/',
        $singletons = array(),
        $view
        ;

    /**
     * Run the application
     */

    function run() 
    {
        // Determine the client-side path to root
        if ( !empty($_SERVER['REQUEST_URI']) ) {
            $this->rootPath = preg_replace('/(index\.php)?(\?.*)?$/', '', $_SERVER['REQUEST_URI']);

            if ( !empty($_GET['route']) ) {
                $this->rootPath = preg_replace('/' . preg_quote($_GET['route'], '/') . '$/', '', $this->rootPath);
            }
        }

        // Extract controller name, view name, action name and arguments from URL
        $controllerName = 'Index';

        if ( !empty($_GET['route']) ) {
            $this->args = explode('/', $_GET['route']);

            if ( $this->args ) {
                $controllerName = str_replace(' ', '/', ucwords(str_replace('_', ' ', str_replace('-', '', array_shift($this->args)))));
            }

            if ( $action = $this->args ? array_shift($this->args) : '' ) {
                $this->action = str_replace('-', '', $action);
            }
        }

        if ( !is_file('app/Controllers/'. $controllerName . '.php') ) {
            $controllerName = 'Error404';
        }

        $this->view = new \lib\View($this, strtolower($controllerName));

        // Instantiate the controller
        $controllerName = 'app\Controllers\\' . basename($controllerName);

        $this->controller = new $controllerName();                      

        // Call the controller action
        $this->registerHook('actionBefore');

        if ( method_exists($this->controller, $this->action) ) {
            $method = new \ReflectionMethod($this->controller, $this->action);

            if ( $method->isPublic() && !$method->isFinal() && !$method->isConstructor() ) {
                $this->controller->{$this->action}();
            } else {
                $this->controller->notImplemented();
            }
        } else {
            $this->controller->notImplemented();
        }

        $this->registerHook('actionAfter');

        return array($this->view, $this->controller);

    }

lib/view.php

namespace lib;

class View 
{
    protected
        $app,
        $variables = array()
        ;

    public
        $name
        ;

    /**
     * Constructor
     * @param object $app
     * @param string $name
     */
    public function __construct($app, $name)
    {
        $this->app  = $app;
        $this->name = $name;
    }


    /**
     * Set a view variable
     * @param string $variable
     * @param mixed $value
     */
    public function set($variable, $value = null)
    {
        $this->variables[$variable] = $value;
    }

and finally app/controllers/index.php

namespace app\Controllers;

class index extends \lib\Controller

{

    public function test()

    {
           // This gets the error
                   $this->view->set('helloWorld', 'Hello world!');  
    }

}
tereško
  • 58,060
  • 25
  • 98
  • 150
Keith Power
  • 13,891
  • 22
  • 66
  • 135
  • Ermm. You never set $this->view in the controller - so it's null... I think you're missing something in your bootstrap (you posted 3 of them btw). You set $this->view in Bootstrap but never pass it on to the controller. – akimsko Feb 17 '13 at 11:50

1 Answers1

0

If that is all of the code in your controller, then $this->view is not an object.
Try running the following code:

namespace app\Controllers;

class index extends \lib\Controller
{
    public function test()
    {
           var_dump( $this->view );
           exit;
           $this->view->set('helloWorld', 'Hello world!');  
    }

}

You also should know, that in PHP, the __construct() methods are not inherited.
I must have suffered some brain injury.

Oh .. and I fail to see, why this question has tag. While you are trying to write MVC-like thing, the issue itself has no relation to MVC as architectural pattern.

tereško
  • 58,060
  • 25
  • 98
  • 150