WTF


31
Mar 10

RE: Top 10 PHP Techniques That Will Save You Time and Effort

I realise that I already posted something today, but this seemed like an emergency…

What do you want me to do?  LEAVE?  Then they'll keep being wrong!

I thought maybe this was a serious post when I clicked on it, then when I got to number 2 on the list (I had skipped reading his post about how you should write an index page), I thought maybe he was joking, but at the end of it I realised that he was not.

1. How to Properly Create a Website Index Page
See my post about how to do it right.
[... snip]

$page = isset($_REQUEST['page']) ? $_REQUEST['page'] : 'home';
 
switch($page)
{
    case 'home':           break;
    case 'mail':           break;
    case 'contact':        break;
    default:
        $page = 'home';
}
 
include("$page.php");

[... snip]

Apparently this is the right way. I do like the single point of entry idea, and at least he is filtering the variables so you can’t load other php pages right? It really is too bad my $_COOKIE['page'] = ‘mail’… I wonder what the rest of the site is like. This also makes it a pain to add new pages, and causes a massive switch statement.

2. Use the Request Global Array to Grab Data
There is actually no reason to use $_GET and $_POST arrays to grab values. $_REQUEST, is another global array that fetches you either a get or form request. Therefore, it’s most times more convenient to use something like this to parse data…

No! This is wrong, the $_REQUEST array contains not only the $_POST and $_GET variable contents but it also contains the contents of the $_COOKIE array. The arrays are merged in the order described by your php.ini file, generally $_GET, $_POST, $_COOKIE but not always. So, use the $_POST variable when you mean for it to come from the $_POST variable, use the $_GET for get variables, and the $_COOKIE for things in the cookie. Don’t take the lazy way out.

3. Debugging PHP is About var_dump
If you’re looking for php debugging techniques, i have to say that var_dump is most times the way to go about it…

Wrong again. var_dump simply tells you what is in whatever object/array/whatever you are var_dumping. The xdebug extension is a much better alternative:


The Xdebug extension helps you debugging your script by providing a lot of valuable debug information. The debug information that Xdebug can provide includes the following:

* stack traces and function traces in error messages with:
o full parameter display for user defined functions
o function name, file name and line indications
o support for member functions
* memory allocation
* protection for infinite recursions

Xdebug also provides:

* profiling information for PHP scripts
* code coverage analysis
* capabilities to debug your scripts interactively with a debug client

http://xdebug.org/

4. PHP Handles The Code Logic, Smarty Handles The Presentation
… Learn to use smarty as a template engine for your websites, it will pay off, i promise.

While I am not advocating combining “Code Logic” and “Presentation”, there are much better tools out there than Smarty. Smarty is a horrid piece of archaic spaghetti that had it’s purpose a long time ago, but no longer really does. Or you could learn to separate the presentation from the logic by using one of the myriads of frameworks out there. You could even go one better by separating it out to use the MVC pattern.

5. When You Absolutely Need Global Values, Create a Config File
… Doing it for database tables or database connection information is a good idea, but do not use global variables throughout your PHP code. Moreover, it is always a better idea to keep your global variables at a single config.php file.

Actually… this one isn’t bad, polluting the global namespace is something you should try to avoid, and keeping all of your config values in one place makes them easy to find.

6. If NOT Defined, Access Denied !
If you’re creating your pages the correct way, there will absolutely no reason for anybody to access any other php page other than index.php or home.php.

This goes back to #1, a horrible way to make an index page.

7. Create a Database Class
If you’re doing database programming (pretty common in PHP), it would be a very good idea to create a database class to handle any database management functions.

He then goes on to suggest you make a dbExec($query) function which calls $this->db->exec($query), and a sanitize($var1, $var2…) function which will not actually sanitize the input (it appears to just be making sure the input is numeric?). In his examples he is using the PEAR classes for his database abstraction, which already does this… so I am not sure what the point of putting a database abstraction ontop of a database abstraction is here. Also, use the escape functions that are already given to you by php (or the pear library so that your code is portable across database backends), do not write your own, you will get it wrong.

8. A php File Handles Input, a class.php File Handles Functionality
[...] The php file gets any input that we need and then redirects execution to a function residing to the class file. [...]

It almost seems like he is implementing a poorman’s MVC? I think? Mostly? A much better way would be to actually use an MVC framework (or to look at a tutorial online and see a much better way to do it).

9. Know Your SQL and Always Sanitize
Let me present you an example of a function that uses mySQL and sanitazes using the function seen on point #7

   private function getSentMessages($id)
   {
$this->util->sanitizeInput($id);
 
       $pm_table = $GLOBALS['config']['privateMsg'];
$users = $GLOBALS['config']['users'];
 
       $sql = "SELECT PM.*, USR.username as name_sender FROM $pm_table PM, $users USR
	    WHERE id_sender = '$id' AND sender_purge = FALSE AND USR.id = PM.id_receiver AND is_read = TRUE
	    ORDER BY date_sent DESC";
$result = $this->dbQueryAll($sql);
 
       return $result;
   }

The message is the right one. Sanitize your input. However, it would be awesome if he used some coding standards for naming his variables $user and $pm_table are both tables apparently. The well named function sanitizeInput should probably be renamed to checkInt or something similar since that is what it appears to do. He should also probably not be putting his variables straight in the string, to make it easier to change the query later on when he realises that he missed something. Don’t even get me started on the fact that this function is private and presumably extends his database abstraction class…

10. When You Need Just an Object, Use a Singleton Pattern
It happens pretty often in PHP that we just need a single object created one time and then used globally throughout our whole program. A good example of this is the smarty variable that has to be initialized once and then is used all over the place.
[..snip...]

function smartyObject()
{
    if ($GLOBALS['config']['SmartyObj'] == 0)
    {
        $smarty = new SmartyGame();
        $GLOBALS['config']['SmartyObj'] = $smarty;
    }
    else
        $smarty = $GLOBALS['config']['SmartyObj'];
    return $smarty;
}

[.../snip...]

The singleton pattern: you’re doing it wrong.

This is not actually a singleton pattern, while yes it lets you get the instance that you created earlier, you can still create the object by normal means, so I could have $GLOBALS['config']['SmartyObj'], $GLOBALS['config']['SmartyObj2'], $GLOBALS['config']['SmartyObj3'] which would all be instances of the smarty object, but they can all have different properties and values. If it were a singleton this would not be the case. The proper way of doing this is to use the pattern described in the php.net manual under Patterns Singleton. That way it is always the same object everywhere that you use it, and you do not have to muck around with the $GLOBALS array (which I am pretty sure is a code smell…).

Read his full post here. If you think I may have been too harsh, or not harsh enough, on him, leave a comment.


27
Aug 09

When is 4 – 1 = 4?

When c like languages say so

$a = 5;
$b = 1;
 
$result = $a---$b;
echo $a; #=>4
echo $b; #=>1
echo $result; #=>4
public class FunMaths{
	public static void main(String[] args) {
		int result;
		int a = 5, b = 1;
		result = a---b;
		System.out.println(a);
		System.out.println(b);
		System.out.println(result);
	}
}

13
May 09

On naming functions sanely

When naming your functions, there are certain function prefix/postfixes that should only return specific types. They help the programmers who follow in your footsteps to grasp what it is you were trying to do. It also reduces the number of comments you need because the naming conventions are self explanatory. Here is a short list of some of those function modifiers and the expected return values.

The following should only return boolean values, they should not set anything in the class. They are idempotent. If they are not, you have probably done something wrong or your function is misnamed. Rename it quick before anyone else mistakes it for something that it is not and causes a long bug search.

is_something();
something_exists();

The following should probably not return a value (but if they do it should be true or false based on their success).

set_something();
unset_something();
import_something();
read_something();
calculate_something();
something_calculation();
//this one obviously shouldn't return a value... it could throw an exception though
$something->var = $something_else;

The following should only return values not set them or change anything prior to returning them.

get_something();
retrieve_something();
$something_else = $something->var;
something_value();

The following should only return an integer (long, double…).

count_something();
something_count();

The following are similar, they should also return a number of some sort (could be a float, an int, a double).

total_something();
something_total();
sum_something();

Another thing, don’t use this naming scheme:

get_something();
get_somethings();

There is not enough difference when you are glancing at them quickly or trying to debug something, or you are scrolling through them in an auto-complete pop-up, or documentation. Rather use this one, it is easier to differentiate.

get_something();
get_all_somethings();

Remember:

Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.

- C2.com via Coding Horror


7
May 09

Smarty Best Practices 1

I know I have slagged a lot on smarty in the past, both on my blog and on twitter… It is not because I do not understand it, it is because I see it being misused (at least as far as I am concerned, I may be wrong about it) every day in old projects and all over the internet. So, to make up for the slagging that it has received from me, I will now attempt to show you some best practices (or How to use Smarty the smart way). So, without further ado…

Rule 1: Don’t Manipulate the data

First of all, before you even start using smarty, you have to realise that this is a templating language. You are not supposed to process the data, create new data, delete data, get new data (and so on)… When you are ready to display your template you should already have the data retrieved/created, and ready to go. If you are considering doing this in your smarty template, stop and take a look at your backend code, you probably did something wrong back there. I guess I should do these as some kind of list, so…

Sure it is tempting to do:

{assign var='newVar' value=$oldVar.varThatINeed}

But don’t. It means that people have to go looking for not only $newVar in the php code that displayed the template, they also have to go looking through the smarty code for the assignment. If you need to access that variable, do this instead:

{$oldVar.varThatINeed}

If that variable is supposed to get something from an array, do this:

{$arrayVar[$oldVar.varThatINeed]}

Sure it takes a second more to write it out each time, but it is easier to find in the smarty code.

Breaking Rule 1

There are times when you might need to break rule one. If you find yourself doing anything more complicated than:

{math equation="x + y" x=$height y=$width}

in your template, you should take a step back and look at your code again, why are you doing it this way? Should you be doing it this way? Isn’t there a better way?
I think that even this example provided by the smarty documentation is probably a bit much for the template, especially if the equation is likely to change:

{* Calculate something *}
{math equation="(( x + y ) / z )" x=$vars.var1 y=$vars.var2 z=$vars.var3}

It should probably be something more like:

function calculateSomething($vars){
...
}
//notice I don't rename the function so that you can find it easily later on
//if you didn't want your function named this way, name it something else in your php code...
$smarty->register_modifier('calculateSomething', 'calculateSomething');
$smarty->display('my_template.tpl');
{vars|@caclulateSomething}

Notice the @ symbol, this means pass the whole array as one variable. This is important because smarty apply the modifier to each of the variables in the array if you do not (unless that is what you wanted to happen). While in some cases you may need to break the first rule, if you do it this way, it is managable, reusable. An even better way would be to do this before it gets to the template, but it is understandable to no want to go through the data twice, so this seems like a fair trade off as you are still doing the manipulation in php, and displaying the results of the manipulation in smarty.


9
Apr 09

Smarty… again

Smarty again.To those who think that smarty prevents you in any way from writting your business logic into a template… watch this…

 
{php}
 
if (!$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')) {
    echo 'Could not connect to mysql';
    exit;
}
 
if (!mysql_select_db('mysql_dbname', $link)) {
    echo 'Could not select database';
    exit;
}
 
$sql    = '"INSERT INTO unsafe_tabel (unsafe_var) VALUES('".$_GET['unsafe']."')";
 
$result = mysql_query($sql, $link);
 
if (!$result) {
    echo "DB Error, could not query the database\n";
    echo 'MySQL Error: ' . mysql_error();
    exit;
}
 
{/php}

I think I might have just put stuff that actually belongs in the model into the view… and unescaped too… oh dear… (that would be template for you smarty folks). So, no, smarty does not disuade you from doing it, infact it seems that they encourage it a bit by providing you with the option to do so via the {php} {/php} tags, instead of forcing you to use {rdelim} {ldelim} all throughout your code instead (which would surely discourage most people). If I can do that, the people who’s site’s you’ve written can surely do that too… and mess up the nice templates that you have made for them (and their databases too). So, please think of another reason to use Smarty, and if you cannot, then why are you using it?