1

Im using PHP MVC for my site and I have an issue with routing.

When I go to the index (front page), I use http://www.example.com or http://www.example.com/index.

When I go to the contact page, I use http://www.example.com/contact.

When I go to the services or about pages, I use http://www.example.com/content/page/services or http://www.example.com/content/page/about.

My index and contact pages have their own controllers because they are static pages. But the services and about pages are pulled from my db, thus dynamic. So I created a controller, named it content and just pass the parameters needed to get whatever page I want.

I want to make my URLs more consistent. If I go to the services or about pages, I want to use http://www.example.com/services or http://www.example.com/about.

How can I change my routing to meet this requirement? I ultimately would like to be able to create pages in my db, and then pull the page with a URL that looks like it has its own controller. Instead of having to call the content controller to get it to work.

Below are my controllers and what methods they contain, as well as my routing code.

Controllers:

IndexController
  function: index

ContentController
  function: page
  function: sitemap

ContactController
  function: index
  function: process

Routing

class Application
{
// @var mixed Instance of the controller
private $controller;

// @var array URL parameters, will be passed to used controller-method
private $parameters = array();

// @var string Just the name of the controller, useful for checks inside the view ("where am I ?")
private $controller_name;

// @var string Just the name of the controller's method, useful for checks inside the view ("where am I ?")
private $action_name;

// Start the application, analyze URL elements, call according controller/method or relocate to fallback location
public function __construct()
{
    // Create array with URL parts in $url
    $this->splitUrl();

    // Check for controller: no controller given ? then make controller = default controller (from config)
    if (!$this->controller_name) {
        $this->controller_name = Config::get('DEFAULT_CONTROLLER');
    }

    // Check for action: no action given ? then make action = default action (from config)
    if (!$this->action_name OR (strlen($this->action_name) == 0)) {
        $this->action_name = Config::get('DEFAULT_ACTION');
    }

    // Rename controller name to real controller class/file name ("index" to "IndexController")
    $this->controller_name = ucwords($this->controller_name) . 'Controller';

    // Check if controller exists
    if (file_exists(Config::get('PATH_CONTROLLER') . $this->controller_name . '.php')) {

        // Load file and create controller
        // example: if controller would be "car", then this line would translate into: $this->car = new car();
        require Config::get('PATH_CONTROLLER') . $this->controller_name . '.php';
        $this->controller = new $this->controller_name();

        // Check for method: does such a method exist in the controller?
        if (method_exists($this->controller, $this->action_name)) {
            if (!empty($this->parameters)) {
                // Call the method and pass arguments to it
                call_user_func_array(array($this->controller, $this->action_name), $this->parameters);
            } else {
                // If no parameters are given, just call the method without parameters, like $this->index->index();
                $this->controller->{$this->action_name}();
            }
        } else {
            header('location: ' . Config::get('URL') . 'error');
        }
    } else {
        header('location: ' . Config::get('URL') . 'error');
    }
}

// Split URL
private function splitUrl()
{
    if (Request::get('url')) {

        // Split URL
        $url = trim(Request::get('url'), '/');
        $url = filter_var($url, FILTER_SANITIZE_URL);
        $url = explode('/', $url);

        // Put URL parts into according properties
        $this->controller_name = isset($url[0]) ? $url[0] : null;
        $this->action_name = isset($url[1]) ? $url[1] : null;

        // Remove controller name and action name from the split URL
        unset($url[0], $url[1]);

        // rebase array keys and store the URL parameters
        $this->parameters = array_values($url);
        }
    }
}
1
  • I advice against this, since you'd need to map each of those URLs to your content controller, which goes against your overall routing scheme. Commented Feb 13, 2015 at 20:59

1 Answer 1

1

In order to do this you should map your urls to controllers, check following example:

// route mapping 'route' => 'controller:method'
$routes = array(
   '/service' => 'Content:service'
);

also controller can be any php callable function.

Answer Version 2:

Brother in the simplest mode, let's say you have an entity like below:

uri: varchar(255), title: varchar(255), meta_tags: varchar(500), body: text

and have access to StaticPageController from www.example.com/page/ url and what ever it comes after this url will pass to controller as uri parameter

public function StaticPageController($uri){
  // this can return a page entity
  // that contains what ever a page needs.
  $page = $pageRepository->findByUri($uri)

  // pass it to view layer
  $this->renderView('static_page.phtml', array('page' => $page));
}

I hope this helps.

Sign up to request clarification or add additional context in comments.

5 Comments

How would this integrate into what I have? Do I need a new class? I understand what your saying, but can you give me some more input on where to add this change?
Ok, so after alot of researching I found out about URL mapping like you suggest. If what I found is identical to your example I dont know how that helps me. Your example is statically creating a route to the controller/action from a shortened url or any url for that matter. Adding a routes array, and all of the code to iterate through it would take time. And at the end, I can just create a services controller. So I view your solution the same as my problem. Either a static controller of static route array. Thanks for at least looking into my issue. I did learn some things.
I'm going to work, when back I will explain in details how you can have it in your system.
i appreciate your help. I assure you i dont want the solution coded for me. I just need an example or somewhere to research more. Thanks again.
after pondering your input for a few days I figured it out. I ended up adding a function to build my db array that contains controllers and actions of dynamic pages. Then in my routing code, if the url didnt match my static controllers, it checks the url against the dynamic array. If that returns as true it splits the url and routes to a controller I set aside for dealing with dynamic pages. All of it works as it needs to. Thanks again for your help.

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.