1

So I have library called Engine.php and what it does basically is running

example.com/controller/method/value

So for example if I have

example.com/category/images

it runs the method called "images". But I don't want to add to the code for every single category. I want the method to be a variable (so that I will make it work with db later).

How can I achieve this without changing the Engine? The problem is - some of the pages don't have categories at all. And I don't want to rewrite the Engine itself.

Can I somehow do this in the controller? For example:

I'm entering controller called "category" and if method is set, it searches for this method within the controller (''category'').

This is what part of my Engine.php looks like:

    if (isset($url_output[1])) {
        if (isset($url_output[2])) {
            if (method_exists($controller,$url_output[1])) {
                $controller->{$url_output[1]}($url_output[2]);
            } else {
                $this->error();
            }
        } else {
            if (method_exists($controller,$url_output[1])) {
                $controller->{$url_output[1]}();
            } else {
                $this->error();
            }
        }
      }

So basically, as you can see:

$controller->{$url_output[1]}();

$url_output[1] = the name of the method in controller named $url_output[0].

What I want is:

public function $category() {
echo $category
}

You know what I mean?

Uchiha Obito
  • 69
  • 1
  • 9

3 Answers3

1

why don't you make url like this

example.com/category/index/images

where index is a predefined function for category controller and images will be passes as first parameter to index function.

Second option, bypass the index function in url.

if (isset($url_output[1])) {
    if (method_exists($controller,'index')) {
        $controller->index($url_output[1]);
    } else {
        $this->error();
    }
}

class Category
{
    function index($category)
    {

    }
}

use like this: example.com/category/images

Waqar Alamgir
  • 9,828
  • 4
  • 30
  • 36
1

You can try using a variable variable.
Warning: This is pretty dangerous from a security point of view, so if you're doing this you should make sure you validate your input!

if (isset($url_output[1])) {
    if (isset($url_output[2])) {
        if (method_exists($controller,$url_output[1])) {
            $controller->{$url_output[1]}($url_output[2]);
        } else {
            $this->error();
        }
    } else {
        if (array_search($allowed_categories, $url_output[1]) !== FALSE) {
            echo ${$url_output[1]};
        } else {
            $this->error();
        }
    }
  }

Basically, if $url_output[1] is image, then ${$url_output[1]} translates to $image, which then outputs the value of the $image variable. The $allowed_categories variable should be an array containing whatever categories you want to handle. This is to prevent a malicious user from entering some category that's gonna output a sensitive variable.

Grampa
  • 1,623
  • 10
  • 25
1

What you need to do is to create a real routing mechanism for your project. I have already covered it in two other answers: this and this. One of which I already linked you to once.

The point is to create regular expression (regexp) against you can match the incoming URLs. If you find a matching pattern, you split it using preg_match() and assign some default values, if non-mandatory part of URL is missing.

You can either make the routing mechanism on your own, or graft it on from some other project (simple or complex).

Also, you should separate the routing part of application from the one, which handles dispatching to the controller. Checking, if there is such a method in the controller or if user is permitted to access it, is not part of the routing process. If you mix them together, you will be violating SRP.

Community
  • 1
  • 1
tereško
  • 58,060
  • 25
  • 98
  • 150
  • Ok, how do you suggest I separate them? Make a new Library? I'm very new with MVC – Uchiha Obito Aug 08 '12 at 20:18
  • I have no idea what you think "library" is. I suggest to create a class, which reads the URI and matches it against list of patterns. When it finds matching pattern, it returns the found segments. And that's all what that class does. Then you can you can use those values for dispatching to the controller. Usually this all happens at the *bootstrap* stage of the application. – tereško Aug 08 '12 at 20:23