1

While i was working on a school project I ran into a problem.

I have made an Router class where it get the right files, but I am getting the following error:

Fatal error: Method mvc\App::__toString() must not throw an exception, caught Error: Call to a member function getHTML() on string in /opt/lampp/htdocs/School/testPHP/mvc/public/index.php on line 0

The echo returns the correct file path so that is not the issue I'm running into.

I think the issue is because I try to execute an function into a string.

Does anyone know how I can fix my issue?

App Class:

<?php
namespace mvc;

class App{
    private $router;

    public function __construct(){
        $this->router = new \mvc\Router();
    }


    public function __toString(){
        try {
            echo $this->router->getView(); //this returns the correct file path 
            return $this->router->getView()->getHTML();
        } catch (Exception $e) {
            return $e.getMessage;
        }
    }
}
?>

Router.php:

<?php
namespace mvc;

class Router{

private $route;
private $view;
private $controller;
private $model;

public function __construct(){
    require_once(LOCAL_ROOT. "php/Routes.php");
    if (isset($_GET['route'])){
        $this->route = explode("/" , $_GET['route']);
    }
    $route = isset($routes[$this->getRoute()])? $this->getRoute() : DEFAULT_ROUTE;
    $this->controller = "\\controllers\\". $routes[$route]['controller'];
    $this->view = "\\views\\". $routes[$route]['view'];
    // $model = "\\models\\". $routes[$route]['model'];
}

private function getRoute(){
    return count($this->route) > 0 ? $this->route[0] : DEFAULT_ROUTE;
}
public function getView(){
    return $this->view;
}
}
?>

Routes.php

<?php
define("DEFAULT_ROUTE", "home");
$routes = array(
"home" => array(
    "view" => "HomeView",
    "controller" => "HomeController",
),
"form" => array(
    "view" => "FormView",
    "controller" => "FormController",
),
"test" => array(
    "view" => "TestView",
    "controller" => "TestController",
),
)
?>

TestView.php

<?php
namespace views;

class TestView extends \mvc\View{
public function getHTML(){
    // return 'dit is testView';
    $klik = $this->controller->getGetData("klik");
    $output = "";
    $output .= "<h1>".$klik++ ."</h1>";
    $output .= "<a href=\"test?klik=$klik\">klik</a>";
    $output .= "<br>";
    return $output;
}
}

?>
5
  • 2
    You can't throw exception from a __toString() method. You can do it in PHP version PHP 7.4. Commented Feb 7, 2020 at 11:16
  • 1
    We need to see the code from the Router class, specifically the getView() and getHTML() methods. Commented Feb 7, 2020 at 11:16
  • @MarkOverton i have added some code hope its what you need Commented Feb 7, 2020 at 11:29
  • Short answer: You cannot call methods on PHP strings like in JavaScript since they are primitives. You can pass strings as arguments to functions instead. Commented Feb 7, 2020 at 11:49
  • return $e.getMessage; in your App class does not do what you want it to do; correct syntax would be return $e->getMessage();. While this won't solve the root cause, fixing this sounds like a good first step. Commented Feb 7, 2020 at 11:57

1 Answer 1

1

The Problem:

Okay so the problem is that you're making a call to a function from a string.

This is the getView method in the Router class:

public function getView(){
    return $this->view;
}

This method returns a string:

$this->view = "\\views\\". $routes[$route]['view'];

You are then trying to call a method from this string:

return $this->router->getView()->getHTML();

The Potential Solution:

Obviously you're trying to access the getHTML method in the TestView class, so without knowing more about your setup, it's hard to get exact, but I'll take a guess at the following and you can guide me in the right direction in the comments.

If you change the constructor in your App class to this:

public function __construct(){
    $this->router = new \mvc\Router();
    $this->testView = new \views\TestView();
}

Then you can change your __toString method to the following:

echo $this->router->getView(); //this returns the correct file path 
return $this->testView->getHTML();

I'm not sure why you'd echo and then return, usually it's one or the other, but if you elaborate more on your expected output I can help you some more, or hopefully my explanation has given you enough to work from.


Solution:

After reading your comments, it looks like you want to instantiate the class from the result of the getView method, you can do this by setting the result into a variable and calling a new class from that string and THEN calling the method from that class.

$class = $this->router->getView();
$class = new $class;

return $class->getHTML();
Sign up to request clarification or add additional context in comments.

4 Comments

Yes, this wil work but my problem is that i made my program so that it will pick the last part of my url and finds the proper class with it FE : at testPHP/mvc/test the echo $this->router->getView(); will return \views\TestView and at estPHP/mvc/home the echo $this->router->getView(); will return \views\HomeView
What are you expecting return $this->router->getView()->getHTML(); to do?
It needs to get the right view class and than execute the function getHTML() on that view class
Please see revised answer above on how to do this

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.