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.