Please look at the code below.
require_once("initvars.inc.php");
require_once("config.inc.php");
?>
<?php
if($latestads_count)
{
?>
<div class="latestposts">
<div class="head"><?php echo $lang['LATEST_ADS']; ?></div>
<table border="0" cellspacing="0" cellpadding="0" class="postlisting" width="100%">
<?php
$sql = "SELECT a.*, ct.cityname, UNIX_TIMESTAMP(a.createdon) AS timestamp, feat.adid AS isfeat,
COUNT(*) AS piccount, p.picfile AS picfile, scat.subcatname, scat.catid, cat.catname
FROM $t_ads a
INNER JOIN $t_cities ct ON a.cityid = ct.cityid
INNER JOIN $t_subcats scat ON a.subcatid = scat.subcatid
INNER JOIN $t_cats cat ON scat.catid = cat.catid
LEFT OUTER JOIN $t_featured feat ON a.adid = feat.adid AND feat.adtype = 'A' AND feat.featuredtill >= NOW()
LEFT OUTER JOIN $t_adpics p ON a.adid = p.adid AND p.isevent = '0'
WHERE $visibility_condn
$loc_condn
GROUP BY a.adid
ORDER BY a.createdon DESC
LIMIT $latestads_count";
$res_latest = mysql_query($sql) or die($sql.mysql_error());
$css_first = "_first";
while($row = mysql_fetch_array($res_latest))
{
$url = buildURL("showad", array($xcityid, $row['catid'], $row['catname'],
$row['subcatid'], $row['subcatname'], $row['adid'], $row['adtitle']));
?>
<?php
if($row['isfeat'])
{
//$feat_class = "class=\"featured\"";
$feat_img = "<img src=\"images/featured.gif\" align=\"absmiddle\">";
}
else
{
//$feat_class = "";
$feat_img = "";
}
if($row['picfile'])
{
$picfile = $row['picfile'];
$imgsize = GetThumbnailSize("{$datadir[adpics]}/{$picfile}", $tinythumb_max_width, $tinythumb_max_height);
}
else
{
$picfile = "";
}
?>
<tr>
<td width="15">
<img src="images/bullet.gif" align="absmiddle">
</td>
<td>
<b><a href="<?php echo $url; ?>" <?php echo $feat_class; ?>><?php echo $row['adtitle']; ?></a></b>
<?php if(0&&$row['picfile']) { ?><img src="images/adwithpic.gif" align="absmiddle"><?php } ?>
<?php echo $feat_img; ?><br>
<span class="adcat">
<?php echo "$row[catname] $path_sep $row[subcatname]"; ?>
<?php
$loc = "";
if($row['area']) $loc = $row['area'];
if($xcityid < 0) $loc .= ($loc ? ", " : "") . $row['cityname'];
if($loc) echo "<br>$loc";
?>
</span>
</td>
<td align="right" width="<?php echo $tinythumb_max_width; ?>">
<?php if($picfile) { ?>
<img src="<?php echo "{$datadir[adpics]}/{$picfile}"; ?>" border="0" width="<?php echo $imgsize[0]; ?>" height="<?php echo $imgsize[1]; ?>" style="border:1px solid black">
<?php } ?>
</td>
</tr>
This is one of the code files from an existing project. As you can see, it has html, sql, php all intermixed together... and obviously difficult to maintain.
There are around 55 files of similar size and type in this application.
I want to refactor this code,and below are my objectives for doing so:
1)Easy to maintain.
2)Be able to extend easily by adding additional features.
3)Be able to reuse this code for different but somewhat similar applications.
I have a number of question based on the above facts:
1) Do you think we can refactor this code into an mvc application?
2)If we can. how much time should it take to refactor the whole project(55 files) say, for an expert programmer?
3)Should i reuse the above code, or should i start from scratch with a existing mvc framework?
4)How much time do we need to complete the whole project, in case we go for an existing mvc framework say symfony, zend etc.?
5)This site as per my knowledge until now would run Mysql only(as the current db is done in mysql). Should we allow for data abstraction/data acces layers in the model(supposing there is something that performs better than Mysql, I'm not sure about this)
7)Can we easily refactor the code to include sub-layers for model(data abstraction/access), view(further templates, view logic etc.), controller etc. in case we want to do that in future or would we need to start from scratch?
8)Is mvc the way to go , or is there a better pattern/way than it(supposing the site is intended for hundred thousands of users)?
Yes.
I would say about an hour per file of that size to make sure everything goes smoothly. So 1-2 weeks of solid work.
If this works well, just re-factor. If you really want something new, grab a framework.
An existing framework will probably take longer to duplicate existing functionality (maybe a month). However, you will have a more stable application in the long run (most likely).
There is nothing wrong with MySQL. Use a data abstraction layer if you feel like you will want to switch in the future for some other reason.
There is no reason why you wouldn't be able to re-factor. I have done this recently and it is not all that difficult.
MVC is pretty much ideal. That said, there are many different ways to do MVC. Some good, some better, some terrible.
I think there is no thing like an "mvc application", but the mvc pattern can certainly be used in this application. You could build some data classes that encapsule the various queries and translate the result to an object or arrays of objects. A controller class can grab those results and process them, then feed the processed data to a specific template. That is an mvc like construct that is quite easy to maintain. I'd build some helper classes as well. You don't want to call mysql_query everywhere, because maybe you'll need to use mysqli next year, or maybe even a completely different database.
So, yes, use the mvc pattern, but not only that. Refactor the entire code. Use ready to use libraries where you can (for instance for database abstraction), and spent a great deal thinking about the right way to go before you start building.
Related
I am learning php. I see that people recommend to separate html and php or logic and markup. But in some specific occasions I am not sure how to do it. For readability and maintainability I try to put all the php in a separate file but now I have to download a title from a database and the only way I see is to put this with the rest of the html and with this html and php mixed. In this specific case, is there a more clean and organized way? is ok to put this peace of php in the "design" file? can or should I put this php code with the rest of the php?
<?php
include("../../externs/includes/connexio.php");
$result = mysqli_query($con, "SELECT * FROM myTable");
while ($row = mysqli_fetch_array($result)) {
$id = $row["id"];
$title = $row["title"];
$subtitle = $row["subtitle"];
?>
<div class="title" id="<?php echo $id; ?>"><?php echo $title; ?> </div>
<div class="subtitle"><?php echo $subtitle;?> </div>
<br>
<?php
}//end while items
?>
First of all I would recommend to read about MVC (Model-View-Controller), you can start at this Wikipedia article:
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
For a simple case as the one fro you question, your solution is, in my opinion, the best. Anything else would be to add unnecessary complexity.
That being said, I will try to use that simple case and offer one possible way to separate logic from presentation with the hope that some basic concepts will become clear from it.
my_controller.php
include("../../externs/includes/connexio.php");
$result = mysqli_query($con, "SELECT * FROM myTable");
$myList = array();
while ($row = mysqli_fetch_array($result))
{
$myList[] = $row;
}
// Now load the view.
include "my_view.php";
my_view.php
<?php foreach ($myList as $row ) : ?>
<div class="title" id="<?php echo $row['id']; ?>"><?php echo $row['title']; ?></div>
<div class="subtitle"><?php echo $row['subtitle'];?></div>
<br>
<?php endforeach; ?>
As you see, I just took your code and separated it in what would be business logic and presentation.
The idea here is that data to be presented should be generated outside the View. The View should know nothing about how the data was "generated".
In this example, the View only knows about the variable $myList containing the fields: id, title and subtitle. If you ever change databases or decide to fetch data from a file or even a Web service; you would not have to touch the View at all.
At the same time, the controller doesn't care about how the View shows the data. Regardless of the source: database, Web service, file, etc; it will always produce an array containing at least the fields expected by the View.
The next step to MVC would be to move data manipulation from controller to a model. I won't go there in detail, but this is how the controller would look like:
include "my_model.php";
$myList = fetchData();
include "my_view.php;
The fetchData() function inside the my_model.php file would basically do the same as my_controller.php above.
A very debatable and indeed debated issue is whether having any PHP code inside the View is a good practice. Some argue that other templating languages such as Smarty should be used. My opinion is that changing the syntax by adding another language doesn't change the inevitable fact that you need some logic in the View, otherwise you would be unable to introduce dynamism to your applications.
As you feel more comfortable reading PHP code, you will be able to look into the several frameworks around and see how they do it. One thing they all have in common is that they all have some logic in the presentation layer, whether it is PHP or something else.
Following are the best practices you can follow while mixing PHP with markup.
(Not a best practice)
1) if for example you have a logic on the top and you wish to generate markup, one not so good way you can do is:
<?php
$query = mysql_query("SELECT id,name FROM table");
while($row = mysql_fetch_assoc($query)){
$id = $row['id'];
$name = $row['name'];
?>
<div>ID:<?php echo $id;?></div>
<div>NAME:<?php echo $name;?></div>
<?php
}
?>
In the above code you have to keep track of the ending curly brace, if your application is complex it can create a problem especially in more then one level of iteration.
2) Good way to do is to make use of PHP tags such as
<?php if(count($array)):?>
<?php foreach($array as $result):?>
<div><?php echo result;?></div>
<?php endforeach;?>
<?php else:?>
<div>NO results found</div>
<?php endif;?>
Your code has no presentation issues but if it is a complex application then you need to follow best practices.
<?php
$array = array();
$query = mysql_query("SELECT id,name FROM table");
while($row = mysql_fetch_assoc($query)):
$array[] = $row;
endwhile;
?>
Outside of PHP tag check the count of $array, if there is count then generate markup.
<?php if(count($array)):?>
<?php foreach($array as $result):?>
<div>ID<?php echo result['id'];?></div>
<div>ID<?php echo result['name'];?></div>
<?php endforeach;?>
<?php else:?>
<div>NO results found</div>
<?php endif;?>
Using this kind of formatting you can achieve pleasing results. Try to separate or avoid mixing too much PHP with markup. If you want your presentation logic to be separated from business logic then I recommend you to use MVC model as it increases readability and maintainability.
I am coming from Asp.net world, where everything is so modular that it creates headaches and nausea sometimes and you forget what you were actually doing.
Here in PHP I was trying to study how to display tabular data, and the solution was very simple but that looked very hasty, because if I write lots of code then it will become haywire.
So my question is what standard should I follow to work with repeating data, if there is any? Please guide me to some quality material to study because I tried but did not find anything. I have studied this link.
[Edit]
The way asp.net render tabular data is by using GridView. here you just create an instance of the GridView class and send it the data retrieved from the database and remain job is done behind the scene without messing the C# or VB code with html or writing the same logic again and again. I mean it is nice example of code resuability and I want to utilize something similar here in php to write the repeating code once and then inherit it if I want it somewhere else.
I myself have migrated from ASP.NET to php and one word of advice is forget what ever you learnt in ASP.net as ASP.net abstracts a lot of thing in web development to a point you forget that you are working with basic html/jscript and http. but again, this is just a personal opinion.
Ragarding your question on how to display a table and populate it with data. Have a look at this example. Here
<?php
$people = array(
array('Tom', '16'),
array('John', '21'),
array('Kate', '19'),
array('Luke', '25')
)
?>
<html>
<head>
<title></title>
</head>
<body>
<table>
<tr>
<td>Name</td><td>Age</td>
</tr>
<?php foreach($people as $person){ ?>
<tr>
<td><?php echo $person[0]; ?></td>
<td><?php echo $person[1]; ?></td>
</tr>
<?php } ?>
</table>
</body>
</html>
I create a 2d array contain data about People and their age. Due to simplicity sake, im using a hard coded array and not retrieving data from a database.
I then use a while loop to loop through the data in the array and for each tuple, I add a <tr> in the table. This is something like a repeater in ASP.NET
DEMO
Just noticed you want a modularized version. Here is an example:
index.php
<?php
include('inc.datasource.php');
$people = DataSource::getUsers();
?>
<html>
<head>
<title></title>
</head>
<body>
<table>
<tr>
<td>Name</td><td>Age</td>
</tr>
<!-- Render rows with data -->
<?php foreach($people as $person){ ?>
<tr>
<td><?php echo $person[0]; ?></td>
<td><?php echo $person[1]; ?></td>
</tr>
<?php } ?>
<!-- End render rows with data -->
</table>
</body>
</html>
inc.database.php
<?php
class DataSource{
public static function getUsers(){
//Connect to database
//Retrieve user data
//Return user data
//Simulating the above steps for simplicity sake
$people = array(
array('Tom', '16'),
array('John', '21'),
array('Kate', '19'),
array('Luke', '25')
);
return $people;
}
}
?>
If you want to completly seperate your php from your html. I suggest you use one of the php mvc frameworks. I personally like using Laravel and CodeIgniter
What could be the most efficient way to make a new Theme and create an article view with multiple objects that link to said article? I am a C# pro but in PHP I am not as well versed as I wish I was.
Suppose you have:
while(have_posts())
<h4><?php the_title(); ?></h4>
<?php the_thumbnail(); ?>
read more
As you can see we have at least 3 calls to the function the_permalink();
Is it faster to call the function three times, or rather call it one time, save it in a variable, and then throw the variable within the loop as much as needed?
While there would be less CPU load to do this, it's a case of premature optimization. The benefit you get isn't that great, particularly because this call doesn't have to touch the database. Once you factor in the fact that what takes the longest with PHP is compiling the code, I'd be surprised if you saw any benefit in a benchmark.
If you dig into the get_permalink() function (in wp-includes/link-template.php) you'll note that the method only consults the options store, which is loaded once on WP initialization.
If you're trying to speed up the site, 99% of the time the way to do it is to cut down on database calls. I'd focus your efforts there :)
I was curious, so I benched with the following code:
ob_start();
$bench = microtime(true);
for ($i = 0; $i < 1000; ++$i) {
the_permalink();
the_permalink();
the_permalink();
}
$bench2 = microtime(true);
ob_end_clean();
echo ($bench2 - $bench) . '<br>';
ob_start();
$bench = microtime(true);
for ($i = 0; $i < 1000; ++$i) {
$permalink = get_permalink();
echo $permalink;
echo $permalink;
echo $permalink;
}
$bench2 = microtime(true);
ob_end_clean();
echo ($bench2 - $bench) . '<br>';
And got the following result:
the_permalink(): 1.891793012619
Storing in a variable and echoing: 0.62593913078308
So storing in a variable and echoing is substantially faster if there are a large number of calls, but for just three calls the performance improvement is only going to be a bit more than one one-thousandth of a second.
Note that some filters are called every time you call the_permalink() too (e.g. the_permalink, post_link, etc.) so the speed gain from storing in a variable may be higher depending on how many hooks there are into those filters and what they do.
It would definitely be much less backend processing to store it in a variable than to call it 3 times in a row per your example. Since the_permalink() echos the permalink, you'll have to use get_permalink() to store it in the variable.
<?php
while(have_posts()) {
$permalink = get_permalink();
?>
<h4><?php the_title(); ?></h4>
<?php the_thumbnail(); ?>
read more
My website consists of many products that are each contained in a div with the id content block. The link, image, background, description and price are all loaded from a mySQL table. My original plan was to save the below html code as a string and loop over the rows in the mySQL table filling the string I created with php/mySQL values.
I was wondering if I am going about this the right way, or is there a better way to create html code from php variables?
<div id="contentblock" style="background-image:url(images/$BACKGROUND.png);">
<div id="picture"><img src="$IMAGELINK"/></div>
<div id="description"><p>$DESCRIPTION</p></div>
<div id="price"><p class=price>$PRICE</p></div>
</div>
Firstly PHP is a template engine - in my experience template engines that layer ontop of PHP are only good for the simplest of cases and are easily outgrown.
Secondly the original code is as good as any method. At risk of stating the obvious to make it better abstract it into a function;
function output_block($BACKGROUND, $LINK, $IMAGELINK, $DESCRIPTION, $PRICE)
{
echo "<div id='contentblock' style='background-image:url(images/$BACKGROUND.png);'>
<div id='picture'><a href='$LINK'><img src='$IMAGELINK'/></a></div>
<div id='description'><p>$DESCRIPTION</p></div>
<div id='price'><p class=price>$PRICE</p></div>
</div>";
}
If you want to make it much better then adopt a framework, an entire admin config page is show below. All of the HTML glue is provided by the framework - the following code is real, but really to illustrate how a framework can provide a lot of the grunge work for you.
In the example below if I want to edit a single entity I'd change the TableViewEdit into a FormView and provide an instance of an entity rather than an iterable list.
$entity = new CbfConfig(); // Database entity
$page = new AdminWebPage("Site Configuration"); // Page for output
/*
* build the view
*/
$vil = new ViewItemList();
$col = &$vil->add(new ViewItem("description","Description"));
$col->get_output_transform()->allow_edit(false); // this field cannot be editted
$col = &$vil->add(new ViewItem("value","Value"));
$v1 = new TableViewEdit($entity, $vil,"admin_values"); // present as standard editable table
/*
* output the page
*/
$page->begin();
$iterable_list = CbfConfig::site_begin();
$page->add_body($v1->get_output($iterable_list,'admin_config'));
$page->end();
Id just have all my html code outside of php tags, then whereever I need a variable from php do as follows
<div id="description"><p><?php echo $DESCRIPTION; ?></p></div>
You can loop around non php code too. For example
<?php
for($i = 0; $i < 10; $i++) {
?>
<div id="description"><p><?php echo $i; ?></p></div>
<?php
} //end for loop
?>
Obviously this is just an example.
well if im without a template engine for somereason i usually do something like:
function partial($file, $args = array()) {
extract($args);
ob_start();
include($file);
return ob_get_clean();
}
Really, there are 3 ways of doing this. Use whichever is easiest for you in the context that you are using it in.
<?php
while(($row=mysql_fetch_assoc($result))!==false)
{
echo "<div>{$row['fieldName']}</div>";
}
?>
<?php
while(($row=mysql_fetch_assoc($result))!==false)
{
echo '<div>'.$row['fieldName'].'</div>';
}
?>
<?php
while(($row=mysql_fetch_assoc($result))!==false)
{
?>
<div><?= $row['fieldName']; ?></div>
<?php
}
?>
I have to modify some parts of a large PHP application. The different parts were written, of course, by different people (mostly interns). After looking through the code, I found that there were 2 styles of coding used by the other developers:
The 'PHP is the glue of the Internet' style, mixing html and php, ex.:
[snip]
<tr class="ds_subsubhead_2">
<td colspan="21" align="left"> A <select name="nb_linge" onChange="MM_jumpMenu('parent',this,0)" style="vertical-align:middle"> <option value="<?=get('index.php',$orgurl,'nb_ligne=','22','23','9999') ?>" <? if($messagesParPage == '9999') { ?>selected="selected"<? } ?>>Tous</option>
<option value="<?=get('index.php',$orgurl,'nb_ligne=','22','23','25') ?>" <? if($messagesParPage =='25') { ?>selected="selected"<? } ?>>25</option>
<option value="<?=get('index.php',$orgurl,'nb_ligne=','22','23','50') ?>" <? if($messagesParPage =='50') { ?>selected="selected"<? } ?>>50</option>
<option value="<?=get('index.php',$orgurl,'nb_ligne=','22','23','75') ?>" <? if($messagesParPage =='75') { ?>selected="selected"<? } ?>>75</option>
[snip] or
<td <? if((isset($_GET['t1']))&&($_GET['t2']!='ALL')) { ?>bgcolor="#0099FF"<? } ?>></td>
<td <? if((isset($_GET['t3']))&&($_GET['t4']!='ALL')) { ?>bgcolor="#0099FF"<? } ?>></td>
<td <? if((isset($_GET['t5']))&&($_GET['t6']!='ALL')) { ?>bgcolor="#0099FF"<? } ?>></td>
[snip] or even
<script type="text/javascript" src="<?=$_SESSION["path"]?>lib/js/ajax.js"></script>
[snip]
... and the more procedural way, ex.:
[snip]
$output .= '<td valign="top"><form name="form5" method="GET" action=""><select name="m" onchange="this.form.submit()">';
if ( empty($_GET['p']) ) $output .= '<option value=" ">All</option>';
else $output .= '<option value='.$_GET['m'].'>'.$_GET['m'].'</option>';
$query = "SELECT DISTINCT maoie FROM ".$BD."site";
$res = mysql_query($query);
while ( $row = mysql_fetch_assoc($res) ) {
if( !empty($row['maoie']) ) $output .= '<option value="'.$row['maoie'].'">'.$row['maoie'].'</option>';
}
$output .= '</select></form></td>';
$output .= add_more_stuff();
echo $output;
Now, I'm not completely sure that this is a more procedural way to do things, but at least it is different from the previous one. Which one, do you think, is generally better?
I, personally, dont't like 'the glue of the Internet' style.
I would ditch both and code the PHP away from any presentation-layer specific HTML. Otherwise things get very nasty, very quickly for anything bigger than 'Hello World' :)
You are shooting yourself in the foot if you want to modify the code later. I would try and kill off this problem by porting to a proper CMS/Abstract presentation.
Neither look good. I wouldn't want to maintain code in either style. save time later by spending time now cleaning it up properly.
Even something as basic as moving your HTML into externally loaded format strings and running them through sprintf() or similar might be better than the current situation. And you say you have a mix of these coding styles !?!
good luck to you sir!
Both styles should be relegated to the tomb of dynamic internet growing pains. Take a peek through some open source PHP projects to see a good, maintainable coding style in action. Things like http://sourceforge.net/projects/wikipedia MediaWiki show a good mix of HTML-In-Source and separation (although it is not perfect IMHO)
There is a third option: templates. Templates are more readable than glue or random emission of ascii vomit. I just tend to use HEREDOCd strings and str_replace, thus:
$template = <<<TEMPLATE
<html>
<head>
<title>{TITLE}</title>
</head>
<body>
<div id='nav'>{NAV}</div>
<div id='content'>{CONTENT}</div>
</body>
TEMPLATE;
$data = array (
"{TITLE}" => "Page title example",
"{NAV}" => buildNav(),
"{CONTENT}" => buildContent());
str_replace(array_keys($data),array_values($data), $template);
I tend to go for something in the middle. If I'm calling fifteen different functions to generate a select <option>, why not just have one function that does everything and creates the complete markup?
Something like this (completely made up example):
<select>
<?php
foreach (database_query() as $row)
echo gen_select($row)
?>
</select>
and somewhere else
function gen_select($row) {
// do something horrifically complicated with the data (creating some variables to make the output easier to follow
return "<option class=\"$class\">$text</option>";
}
I personally work on a CMS that has the latter version, and I am having a very hard time reading it.
2ndly, model/controller code within view's is a great Italian dish.
Both are horrible (that's the real weakness of PHP in my opinion), but at least the first looks readable.
Problems will eventually arise once conditions (is the request POST? is the data valid?) are added, and it will lead invariably to the dreaded second kind of coding. Try to decouple view and logic: str_replacing is way better than building a string by concatenating one gazillion small pieces.
No offence, but both style is from the late '90-s.
You should seriously consider refactor the system and use a template engine to separate at least the PHP and the HTML code.
Even better if you can separate the "business logic" and the "display logic" part.
I think HTML and PHP should be seperated as much as possible. It makes the whole code easier to read and creates a clear structure. That means for me that PHP should not output HTML, since you can use HTML to do that part...
So I'd also prefer the last example, but with one difference: I think using the bracket-style mixed into HTML makes it very hard to read the code. The if...endif style is the better alternative I think. Also printing HTML with PHP seems unlogic.
I'd do it this way:
<td valign="top"><form name="form5" method="GET" action=""><select name="m" onchange="this.form.submit()">;
<? if ( empty($_GET['p']) ): ?>
<option value=" ">All</option>
<? else: ?>
<option value="<?=$_GET['m']?>"><?=$_GET['m']?</option>
<? endif; ?>
<?
$query = "SELECT DISTINCT maoie FROM ".$BD."site";
$res = mysql_query($query);
while ( $row = mysql_fetch_assoc($res) ):
?>
<? if( !empty($row['maoie']) ): ?>
<option value="<?=$row['maoie']?>"><?=$row['maoie']?></option>
<? endif; ?>
<? endwhile; ?>
</select></form></td>
<? echo add_more_stuff(); ?>
At least this is a bit more logic. Nevertheless things like database interaction should be excluded to somewhere else in your web application. If you seperate the data and the design of your page it gets much clearer.
Nevertheless I think using PHP as a template language is totally fine as long as you only use some replacement variables and simple if-statements.