2
\$\begingroup\$

I am attempting to refactor my app using the MVC paradigm.

My site displays charts. The URLs are of the form

  • app.com/category1/chart1
  • app.com/category1/chart2
  • app.com/category2/chart1
  • app.com/category2/chart2

I am using Apache Rewrite to route all requests to index.php, and so am doing my URL parsing in PHP.

I am working on the enduring task of adding an active class to my navigation links when a certain page is selected. Specifically, I have both category-level navigation, and chart-level sub-navigation. My question is, what is the best way to do this while staying in the spirit of MVC?

Before my refactoring, since the nav was getting relatively complicated, I decided to put it into an array:

$nav = array(
  '25th_monitoring' => array(
    'title'    => '25th Monitoring',
    'charts' => array(
      'month_over_month' => array(
        'default' => 'month_over_month?who=total&deal=loan&prev='.date('MY', strtotime('-1 month')).'&cur='.date('MY'),
        'title'   => 'Month over Month'),
      'cdu_tracker' => array(
        'default' => 'cdu_tracker',
        'title'   => 'CDU Tracker')
    )
  ),
  'internet_connectivity' => array(
    'title'   => 'Internet Connectivity',
    'default' => 'calc_end_to_end',
    'charts' => array(
      'calc_end_to_end' => array(
        'default' => 'calc_end_to_end',
        'title' => 'calc End to End'),
      'quickcontent_requests' => array(
        'default' => 'quickcontent_requests',
        'title' => 'Quickcontent Requests')
    )
  )
);

Again, I need to know both the current category and current chart being accessed. My main nav was

<nav>
  <ul>
    <?php foreach ($nav as $category => $category_details): ?>
    <li class='<?php $current_category == $category ? null : 'active'; ?>'>
      <a href="<?php echo 'http://' . $_SERVER['SERVER_NAME'] . '/' . $category . '/' . reset(reset($category_details['monitors'])); ?>"><?php echo $category_details['title']; ?></a>
    </li>
    <?php endforeach; ?>
  </ul>
</nav>

and the sub-nav was something similar, checking for current_chart instead of current_category.

Before, during parsing, I was exploding $_SERVER['REQUEST_URI'] by /, and breaking the pieces up into $current_category and $current_monitor. I was doing this in index.php. Now, I feel this is not in the spirit of the font controller. From references like Symfony 2's docs, it seems like each route should have a controller. But then, I find myself having to define the current category & monitor multiple times, and either within the template files themselves (which doesn't seem to be in the spirit of MVC), or in an arbitrary function in the model.

What is the best practice here?

Update: Here's what my front controller looks like:

// index.php
<?php
// Load libraries
require_once 'model.php';
require_once 'controllers.php';

// Route the request
$uri = str_replace('?'.$_SERVER['QUERY_STRING'], '', $_SERVER['REQUEST_URI']);
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && (!empty($_GET)) && $_GET['action'] == 'get_data') {

  $function = $_GET['chart'] . "_data";
  $dataJSON = call_user_func($function);
  header('Content-type: application/json');
  echo $dataJSON;

} elseif ( $uri == '/' ) {
  index_action();

} elseif ( $uri == '/25th_monitoring/month_over_month' ) {
  month_over_month_action();

} elseif ( $uri == '/25th_monitoring/cdu_tracker' ) {
  cdu_tracker_action();

} elseif ( $uri == '/internet_connectivity/intexcalc_end_to_end' ) {
  intexcalc_end_to_end_action();

} elseif ( $uri == '/internet_connectivity/quickcontent_requests' ) {
  quickcontent_requests_action();

} else {
  header('Status: 404 Not Found');
  echo '<html><body><h1>Page Not Found</h1></body></html>';   
}

?>

It seems like when month_over_month_action() is called, for instance, since the controller knows the current_chart is month_over_month, it should just pass that along. This is where I'm getting tripped up.

\$\endgroup\$
3
  • \$\begingroup\$ it is ideal situation when you need 1-to-1 route-to-controller. Real life case can be more complicated and I would use one controller to handle this identical operations \$\endgroup\$
    – Serg
    Commented Jan 30, 2013 at 12:41
  • \$\begingroup\$ You reference Symfony2 documentation. Are you using Symfony2? \$\endgroup\$ Commented Jan 30, 2013 at 23:17
  • \$\begingroup\$ I started, but then decided I should step back and really understand OOP first. I'm trying to figure out the routing stuff first, since I'm going back and refactoring my projects, and that seems like me to be the first step. \$\endgroup\$ Commented Jan 31, 2013 at 3:05

1 Answer 1

1
\$\begingroup\$

You could try urls like this:

/category/1/chart/1
/category/1/chart/2
/category/2/chart/1

Where your application controller structure looks like this:

+-Application/
   +-Category/
     +-Controller/
        +-ChartController.php

You could think of "Category" as a module (or in Symfony, a bundle).

The route pattern would be: /category/{category}/chart/{chart} and ChartController might look like this:

class ChartController
{
    showAction($category, $chart)
    {
        //look up the category and chart to display
    }
}

Have a look at the symfony2 routing documentation. Also, symfony2's routing is a stand alone routing component that you could use in your index.php/front controller.

\$\endgroup\$
1
  • \$\begingroup\$ I have built something else that looks like this, but I'd like to have some more flexibility in my urls. Ultimately, I just want to know the right way to do it, in a way that is robust. \$\endgroup\$ Commented Jan 31, 2013 at 18:07

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.