background
A little over a year ago I was given the creative freedom to develop on the side of my primary responsibilities. I want to move into development, but am not currently in that role. I was given the resources to develop a PHP application that handled a lot of the reporting functions for our business.
My problem is that I have been building upon my (inexperienced) design over the last year and it is becoming cumbersome to maintain and I know I'm duplicating a lot of work (copy, pasting) and I'm looking for pointers and on where to go from here.
I expect criticism from this because even I am not happy with this design, but it has been very effective overall for my division.
The website is a HTML/JS based with PHP as the server side scripting. I use several libraries, but for the most part, I hand code a lot of the extra features. I didn't have the concept of a framework down when I first built this.
code review
Note: Please pardon the lack of documentation, I literally just created this specific example and it's the reason I'm posting on here. Because I want to fix this.
I have an index.php that is the router that dynamically pulls another php file, like the one below and displays in a div, based on the url.
index.php
<?php // require_once to have HTML headers. require_once('inc/header.php'); // require_once for wrapper, this is the menu bar located underneath the logo. require_once('inc/wrapper.php'); // start main div. echo "<div id='main'> "; // conditional to check if $_GET for file is valid. if (!empty($_GET['p'])) { $access = ms_escape_string($_GET['p']); } // prepares the query for access_level_control and stores it in an array. $sql = "SELECT access_level FROM test.dbo.users_access_control WHERE filename='$access'"; $result = sqlsrv_query($msdb, $sql); $row = sqlsrv_fetch_array($result); // uses the above array to pull a case/switch with access_level to arrange content for website, an an access level. if (!isset($_GET['p'])) { ?> <script type='text/javascript'> //<![CDATA[ document.title = 'test'; $(document).ready(function () { document.getElementById('subpagetitle').innerHTML = 'Main'; }); //]]> </script> Please choose from the menu on the left.</br> <?php } elseif ($_SESSION['accesslevel'] < $row['access_level']) { echo "You are not authorized to use this tool."; // if access level is insufficient. } else { $access = ms_escape_string($_GET['p']); $sql = "SELECT name FROM test.dbo.users_access_control WHERE filename='$access'"; $result = sqlsrv_query($msdb, $sql); $row = sqlsrv_fetch_array($result); ?> <script type='text/javascript'> //<![CDATA[ document.title = 'test - <?php echo $row['name'] ?>'; $(document).ready(function () { document.getElementById('subpagetitle').innerHTML = '<?php echo $row['name'] ?>'; }); //]]> </script> <?php require_once($access . ".php"); // opens the php file based on request. } // end main.div. echo "</div>"; // require_once footer. require_once("inc/footer.php"); ?>
Here is an example of how just ONE of the reports functions. After calling index.php?p=datadump, the main div html is updated with the following php file.
datadump.php
<h3>Data Dump</h3> <form id='filterform'> <table class='data'> <tr> <th class='center'>Option</th> <th class='center'>Date Range</th> </tr> <tr> <td class='center'> <select id='option'> <?php $sql = "SELECT call_type_group_id id, call_type_group_name name FROM test.dbo.call_type_groups"; $result = sqlsrv_query($msdb, $sql); while ($row = sqlsrv_fetch_array($result)) { echo "<option value=" . $row['id'] . ">" . $row['name'] . "</option>"; } ?> </select> </td> <td> <input type='text' size='8' name='sdate' id='sdate' name='sdate' readonly='1' value=''/> - <input type='text' size='8' name='sdate' id='edate' name='edate' readonly='1' value=''/> </td> </tr> <tr> <th class='center' colspan='4'><input type='button' id='run' onclick="pullDataDump();" value='Run'/></th> </tr> </table> </form> </br> <div id="container"></div> <script type='text/javascript'> addTooltip(); // found in functions.js dateRange(); // found in functions.js enableEnter(); // found in functions.js </script>
The onclick button calls a function found in ajax.js. ajax.js is essentially all very similiar looking functions that typically have one off things that make it hard to re-use the same function. So sadly, a lot of copy, pasting, tweaking happens in that file.
ajax.js
function pullDataDump() { $(function () { var option = $('#option').val() var sdate = $('#sdate').val() var edate = $('#edate').val() $('#container').html('<img src="inc/img/busy.gif" alt="Currently Loading" id="loading" />'); $.ajax({ url: 'inc/ajax.php?p=pullDataDump', type: 'POST', data: 'sdate=' + sdate + '&edate=' + edate + '&option=' + option, success: function (html) { $('#container').html(html); dataTable(); // found in functions.js } }); return false; }); }
Which then calls a php file with the arguments in a POST request where the server side scripting retrieves the data. ajax.php is essentially a massive case/switch that I have been building upon for a long time.
ajax.php
case 'pullDataDump': { $sdate = $_POST['sdate']; $edate = $_POST['edate']; $option = $_POST['option']; ?> <table id="report" class="data"> <thead> <th class="center">DateTime</th> <th class="center">Calls Offered</th> <th class="center">Calls Handled</th> <th class="center">Calls Abandoned</th> <th class="center">Handle Time</th> <th class="center">Overflow Out</th> <th class="center">SL Calls Offered</th> <th class="center">SL Calls Abandoned</th> <th class="center">SL Calls Handled</th> </thead> <?php $sql = "SELECT DateTime, SUM(CallsOfferedHalf - OverflowOutHalf) CallsOffered, SUM(CallsHandledHalf) CallsHandled, SUM(TotalCallsAbandToHalf) CallsAbandonded, SUM(HandleTimeHalf) HandleTime, SUM(OverflowOutHalf) OverFlowOut, SUM(ServiceLevelCallsOfferedHalf) ServiceLevelCallsOffered, SUM(ServiceLevelAbandHalf) ServiceLevelAbandHalf, SUM(ServiceLevelCallsHalf) ServiceLevelCallsHandled FROM test.dbo.Call_Type_Half_Hour hh WHERE CallTypeID IN (SELECT call_type_id FROM ww_sl.dbo.call_type_group_members WHERE call_type_group_id = $option) AND DateTime >= '$sdate 00:00:00' AND DateTime <= '$edate 23:30:00' GROUP BY hh.DateTime ORDER BY hh.DateTime"; $result = sqlsrv_query($msdb, $sql); while ($row = sqlsrv_fetch_array($result)) { ?> <tr> <td class="center"><?php echo $row['DateTime']; ?></td> <td class="center"><?php echo $row['CallsOffered']; ?></td> <td class="center"><?php echo $row['CallsHandled']; ?></td> <td class="center"><?php echo $row['CallsAbandonded']; ?></td> <td class="center"><?php echo $row['HandleTime']; ?></td> <td class="center"><?php echo $row['OverFlowOut']; ?></td> <td class="center"><?php echo $row['ServiceLevelCallsOffered']; ?></td> <td class="center"><?php echo $row['ServiceLevelAbandHalf']; ?></td> <td class="center"><?php echo $row['ServiceLevelCallsHandled']; ?></td> </tr> <?php } echo "</table>"; } break;
The #container div is updated with the results and I have a jquery library that allows manipulation of the displayed results.
My big concern is the increasing growing ajax.js and ajax.php, and I'm not sure where to move from here.