Novice to Ninja book {error} while using XAMPP

While trying to develop my framework (to ease my development time), I run into this problem Fatal error: Uncaught Error: Method name must be a string in C:\xampp\htdocs\mywebsites\gbenga\classes\General\EntryPoint.php:47 Stack trace: #0 C:\xampp\htdocs\mywebsites\gbenga\public\index.php(8): General\EntryPoint->run() #1 {main} thrown in C:\xampp\htdocs\mywebsites\gbenga\classes\General\EntryPoint.php on line 47 and I can’t find any solution to work for me even here on stackover.

This is run method

public function run() {

        $routes = $this->routes->getRoutes();   

        $authentication = $this->routes->getAuthentication();

        if (isset($routes[$this->route]['login']) && !$authentication->isLoggedIn()) {
            header('location: /login/error');
        }
        else if (isset($routes[$this->route]['permissions']) && !$this->routes->checkPermission($routes[$this->route]['permissions'])) {
            header('location: /login/permissionserror');    
        }
        else {
            $controller = isset($routes[$this->route][$this->method]['controller']);
            $action = !empty($routes[$this->route][$this->method]['action']);
            $page = $controller->$action();

            $title = $page['title'];

            if (isset($page['variables'])) {
                $output = $this->loadTemplate($page['template'], $page['variables']);
            }
            else {
                $output = $this->loadTemplate($page['template']);
            }

            echo $this->loadTemplate('layout.html.php', ['loggedIn' => $authentication->isLoggedIn(),
                                                         'output' => $output,
                                                         'title' => $title
                                                        ]);

        }

    }
}

And this is the index page

<?php
try {
    include __DIR__ . '/../includes/autoload.php';

    $route = ltrim(strtok($_SERVER['REQUEST_URI'], '?'), '/');

    $entryPoint = new \Ninja\EntryPoint($route, $_SERVER['REQUEST_METHOD'], new \Ijdb\IjdbRoutes());
    $entryPoint->run();
}
catch (PDOException $e) {
    $title = 'An error has occurred';

    $output = 'Database error: ' . $e->getMessage() . ' in ' .
    $e->getFile() . ':' . $e->getLine();

    include  __DIR__ . '/../templates/layout.html.php';
}

Where I think the problem is, is this line which is inside the run method

$page = $controller->$action();
And I can’t figure out what is wrong with the code

I don’t know if anybody has experienced it using XAMPP

empty always returns a boolean hence the error from $controller->$action.

Same problem with $controller.

Simplify your code.

without the isset or empty functions, the line 45 and 46 return Undefined Functions. And these are the lines

 $controller = isset($routes[$this->route][$this->method]['controller']);
            $action = !empty($routes[$this->route][$this->method]['action']);

Did the code you are showing with things like $this->route and $this->method really come from the book? If so then time for a new book.

If not then take a step back and try to look at the posted code through the eyes of someone who has never seen it before. How exactly would they have any idea what all the $this stuff is supposed to be?

Wrong reason to write a framework, since writing one takes a lot of time initially, plus you will also need to maintain it, which costs even more time. If it’s really to ease development time you should get a framework of the shelf (like symfony, laravel or zend), learn how to work with it properly, and gain speed from that.

There are several reasons for creating your own framework, such as for educational purposes, but development speed certainly isn’t one of them.

2 Likes

yeah, it actually comes from the book. You can check page 403 upward

Truly sorry to hear that. Like I said before, time for a new book. Just think about the title. Ninjas are supposed to be sneaky, unpredictable and dangerous. Good code should be straight forward, boring and safe.

I had a bit of a look around the github source code repository for that book, presuming you mean the sixth edition of PHP & MySQL Novice to Ninja, and there are lots and lots of files called Entrypoint.php. But, presuming I’ve got the correct one (in the Final-Website code branch), the code for run() isn’t the same as in the first post on here. In particular the lines that you think are causing the problem are different.

I read it as:

public function run() { 
33  
34 		$routes = $this->routes->getRoutes();	 
35  
36 		$authentication = $this->routes->getAuthentication(); 
37  
38 		if (isset($routes[$this->route]['login']) && !$authentication->isLoggedIn()) { 
39 			header('location: /login/error'); 
40 		} 
41 		else if (isset($routes[$this->route]['permissions']) && !$this->routes->checkPermission($routes[$this->route]['permissions'])) { 
42 			header('location: /login/permissionserror');	 
43 		} 
44 		else { 
45 			$controller = $routes[$this->route][$this->method]['controller']; 
46 			$action = $routes[$this->route][$this->method]['action']; 
47 			$page = $controller->$action(); 
48  
49 			$title = $page['title']; 
50  
51 			if (isset($page['variables'])) { 
52 				$output = $this->loadTemplate($page['template'], $page['variables']); 
53 			} 
54 			else { 
55 				$output = $this->loadTemplate($page['template']); 
56 			} 
57  
58 			echo $this->loadTemplate('layout.html.php', ['loggedIn' => $authentication->isLoggedIn(), 
59 			                                             'output' => $output, 
60 			                                             'title' => $title 
61 			                                            ]); 
62  
63 		} 

which makes much more sense given that both isset() and empty() return Booleans as @ahundiak said earlier.

The code I’m looking at is here: https://github.com/spbooks/phpmysql6/blob/Final-Website/classes/Ninja/EntryPoint.php

It may well be that the code has been corrected since the book was published, hence the practice of making the code available elsewhere so that amendments can be made.

1 Like

without the isset and empty functions, those two lines above returned undefined index.

$controller = $routes[$this->route][$this->method]['controller']; 
$action = $routes[$this->route][$this->method]['action'];

after google search, I discovered it will returned the above error(undefined error)if it is not inside the isset and empty functions. That is why I included the isset and empty functions in the code.

You can try it yourself

Ah, so the isset() and empty() sections aren’t from the book as you described earlier?

The thing is, you have to use them correctly. Use them to check whether those entries exist, sure, but then don’t use the result of them - whether they come back as false or true, the result will not be what you want. Those two functions return Boolean results - true or false - so you can’t just then use those results in place of the original code. Sure, do a check to see if they exist prior to using them, but then just don’t call the next line if they do not. I don’t know what the code does, but if it doesn’t already have a check in place, it suggests that it should not be possible for them to not exist.

even without the use of isset() and empty() functions, it still returns the errors. You can try it yourself.

Looking at your code, you’re on the CMS-EntryPoint-Namespaces-Router sample

The issue is this line:

$action = !empty($routes[$this->route][$this->method]['action']);

The book never has !empty around this line, and the addition of the empty check is the cause of your problem. empty() will return true or false. So you’re essentially doing $controller->true() and there is no method (and cant be a method) with the value true as a name.

Remove empty so it’s like the book:

$action = $routes[$this->route][$this->method]['action'];

Then var_dump the $action variable to check it contains the relevant value, it should be a string, the name of the method to call in the controller. If it’s not a string (or you get undefined index) then double check the $routes array.

2 Likes

If you want, go ahead and var_dump($routes) right after you get them and post the results. It’s just a big array. Might also dump out $this->route and $this->method.

This all just learning the basics of arrays. Would not be surprised at all if $routes ends up being empty.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.