What are some useful PHP Idioms? - php

I'm looking to improve my PHP coding and am wondering what PHP-specific techniques other programmers use to improve productivity or workaround PHP limitations.
Some examples:
Class naming convention to handle namespaces: Part1_Part2_ClassName maps to file Part1/Part2/ClassName.php
if ( count($arrayName) ) // handles $arrayName being unset or empty
Variable function names, e.g. $func = 'foo'; $func($bar); // calls foo($bar);

Ultimately, you'll get the most out of PHP first by learning generally good programming practices, before focusing on anything PHP-specific. Having said that...
Apply liberally for fun and profit:
Iterators in foreach loops. There's almost never a wrong time.
Design around class autoloading. Use spl_autoload_register(), not __autoload(). For bonus points, have it scan a directory tree recursively, then feel free to reorganize your classes into a more logical directory structure.
Typehint everywhere. Use assertions for scalars.
function f(SomeClass $x, array $y, $z) {
assert(is_bool($z))
}
Output something other than HTML.
header('Content-type: text/xml'); // or text/css, application/pdf, or...
Learn to use exceptions. Write an error handler that converts errors into exceptions.
Replace your define() global constants with class constants.
Replace your Unix timestamps with a proper Date class.
In long functions, unset() variables when you're done with them.
Use with guilty pleasure:
Loop over an object's data members like an array. Feel guilty that they aren't declared private. This isn't some heathen language like Python or Lisp.
Use output buffers for assembling long strings.
ob_start();
echo "whatever\n";
debug_print_backtrace();
$s = ob_get_clean();
Avoid unless absolutely necessary, and probably not even then, unless you really hate maintenance programmers, and yourself:
Magic methods (__get, __set, __call)
extract()
Structured arrays -- use an object

My experience with PHP has taught me a few things. To name a few:
Always output errors. These are the first two lines of my typical project (in development mode):
ini_set('display_errors', '1');
error_reporting(E_ALL);
Never use automagic. Stuff like autoLoad may bite you in the future.
Always require dependent classes using require_once. That way you can be sure you'll have your dependencies straight.
Use if(isset($array[$key])) instead of if($array[$key]). The second will raise a warning if the key isn't defined.
When defining variables (even with for cycles) give them verbose names ($listIndex instead of $j)
Comment, comment, comment. If a particular snippet of code doesn't seem obvious, leave a comment. Later on you might need to review it and might not remember what it's purpose is.
Other than that, class, function and variable naming conventions are up to you and your team. Lately I've been using Zend Framework's naming conventions because they feel right to me.
Also, and when in development mode, I set an error handler that will output an error page at the slightest error (even warnings), giving me the full backtrace.

Fortunately, namespaces are in 5.3 and 6. I would highly recommend against using the Path_To_ClassName idiom. It makes messy code, and you can never change your library structure... ever.
The SPL's autoload is great. If you're organized, it can save you the typical 20-line block of includes and requires at the top of every file. You can also change things around in your code library, and as long as PHP can include from those directories, nothing breaks.
Make liberal use of === over ==. For instance:
if (array_search('needle',$array) == false) {
// it's not there, i think...
}
will give a false negative if 'needle' is at key zero. Instead:
if (array_search('needle',$array) === false) {
// it's not there!
}
will always be accurate.

See this question: Hidden Features of PHP. It has a lot of really useful PHP tips, the best of which have bubbled up to the top of the list.

There are a few things I do in PHP that tend to be PHP-specific.
Assemble strings with an array.
A lot of string manipulation is expensive in PHP, so I tend to write algorithms that reduce the discrete number of string manipulations I do. The classic example is building a string with a loop. Start with an array(), instead, and do array concatenation in the loop. Then implode() it at the end. (This also neatly solves the trailing-comma problem.)
Array constants are nifty for implementing named parameters to functions.

Enable NOTICE, and if you realy want to STRICT error reporting. It prevents a lot of errors and code smell: ini_set('display_errors', 1); error_reporting(E_ALL && $_STRICT);
Stay away from global variables
Keep as many functions as possible short. It reads easier, and is easy to maintain. Some people say that you should be able to see the whole function on your screen, or, at least, that the beginning and end curly brackets of loops and structures in the function should both be on your screen
Don't trust user input!

I've been developing with PHP (and MySQL) for the last 5 years. Most recently I started using a framework (Zend) with a solid javascript library (Dojo) and it's changed the way I work forever (in a good way, I think).
The thing that made me think of this was your first bullet: Zend framework does exactly this as it's standard way of accessing 'controllers' and 'actions'.
In terms of encapsulating and abstracting issues with different databases, Zend_Db this very well. Dojo does an excellent job of ironing out javascript inconsistencies between different browsers.
Overall, it's worth getting into good OOP techniques and using (and READING ABOUT!) frameworks has been a very hands-on way of getting to understand OOP issues.
For some standalone tools worth using, see also:
Smarty (template engine)
ADODB (database access abstraction)

Declare variables before using them!

Get to know the different types and the === operator, it's essential for some functions like strpos() and you'll start to use return false yourself.

Related

PHP Avoiding globals in procedural programming

I normally use procedural programming with PHP and looking at other questions here asking how to avoid globals the answers were often to use OOP instead. Is it not possible to avoid globals with procedural programming?
For example I can write the following function in two ways. Both have advantages and disadvantages. If I call this function often then it looks bloated with the second method since it has to pass all the variables each time. The alternative is the first method where the function simply passes the value and the variables are all globals in the function.
doWhatIneedtodo(2);
function doWhatIneedtodo($val) {
global $this; global $that; global $theother;
if ($val == 1) {
$this++;
} else
if ($val == 2) {
$that++;
} else
if ($val == 3) {
$theother++;
}
}
doWhatIneedtodo(2,$this,$that,$theother);
function doWhatIneedtodo($val,&$this,&$that,&$theother) {
if ($val == 1) {
$this++;
} else
if ($val == 2) {
$that++;
} else
if ($val == 3) {
$theother++;
}
}
Or perhaps there's a better way to do this that I haven't though of?
It's very much a progression from troublesome code to less troublesome code:
Purely procedural code without using functions: almost impossible to reuse or modularise, quickly leads to name clashes and spaghetti code in any decent-sized program.
Procedural code using functions: some namespacing/scoping for some variables, though eventually still the same issues as above if you use globals.
Procedural code with functions and without globals, veering towards functional programming: no name clashes, great reusability, but a lot of passing around of individual values.
In other languages this is where structs would come in to define structured "bundles" of values to pass around between functions, but since PHP is lacking structs you'd be using arrays, which are tedious because they are entirely unstructured and untyped and it becomes difficult to keep their structure straight in the long run.
So then objects enter the picture, which provide data structures.
And while you're using objects anyway, you may as well go for encapsulation and let object methods act on their own data, hiding the internal data structure and instead exposing functionality (methods), so the underlying data structures can be changed and that change is localised to the class itself, instead of all the functions that consume a certain struct/array.
So you see, solving problems with global procedural code one by one eventually leads to OOP anyway, at least in PHP. There's a fork in the road halfway through where you could go to pure functional programming as well, but PHP is ill-equipped for being a purely functional language.
The reason you mostly find answers regarding this question for OOP is twofold I think:
Everybody does PHP OOP these days, it's really worth it.
In OOP globals are bad as you want to avoid global state. Introducing global state results in code that's harder to test and to maintain. In procedural PHP everything is global anyways so there's much less need to avoid globals.
Apart from that, my preference goes to your second implementation because it would be far more easy to transition this into proper OOP code. If you use the first implementation and you'd want to change the names of the variables, you'd have to adjust the calling code and the function itself.

Functional Programming - Return Transformed array and the count of the array without calculating twice

I'm trying to write more functional code in PHP without any helper libraries.
I need to return some JSON that includes the results of a transformed array AND the count of that array (for convenience on the data consumer end). Since you're not supposed to use variables in FP, I'm stumped on how to get the count of the array without recalculating/remapping the array.
Here's an example of what my code currently looks like:
$duplicates = array_filter( get_results(), 'find_duplicates' );
send_json( array(
"duplicates" => $duplicates,
"numDuplicates" => count( $duplicates )
) );
How can I do the same without storing the results of the filter in a temporary variable to avoid running array_filter() twice?
But first, acknowledge the following...
"Since you're not supposed to use variables in FP..." – that's a ludicrous understanding of functional programming. Variables are used constantly in functional programs. I'm guessing you saw point-free functional programs and then imagined that every program can be expressed in such a way...
the receiver of the JSON could easily get the number of duplicates using JSON.parse(json).duplicates.length because every Array in JavaScript has a length property – it's arguably silly to attach a numDuplicates in the first place. Anyway, let's assume your consumer has a specific API that requires the numDuplicates field...
functional programming is concerned with things like function purity – maybe you've simplified your code in your post (which is bad; don't do that) or that is in fact your actual code. In such a case, get_results() and send_json functions are impure; send_json has an obvious (but unknown) side effect (the return value is not used) — You ask for a functional solution but you have other outstanding non-functional code... so...
There's nothing wrong with the code you have. Sometimes removing a point (variable, or argument), it hurts the readability of the code. In your case, this code is perfectly legible. It is at this point that I feel you're only trying to shorten the code or make it more clever. Your intention is to improve it, but I think you'd actually harm it in this case.
What if I told you...
a variable assignment can be replaced with a lambda? 0_0
(function ($duplicates) {
send_json([
'duplicates' => $duplicates,
'numDuplicates' => count($duplicates)
});
}) (array_filter(get_results(), 'find_duplicates'));
But that made the code longer.. and there's added abstraction which hurts readability T_T In this case, using a normal variable assignment (as in your original code) would've been much better
Combinators
OK, so what if you had some combinators at your disposal to massage the data into the desired shape?
function apply (...$xs) {
return function ($f) use ($xs) {
return call_user_func($f, ...$xs);
};
}
function identity ($x) { return $x; }
// hey look, mom! no points!
send_json(
array_combine(
['duplicates', 'numDuplicates'],
array_map(
apply(
array_filter(get_results(), 'find_duplicates')),
['identity', 'count'])));
Did we achieve anything other than writing the weirdest PHP you or anyone else has probably seen? Not to mention, the input is strangely nested in the middle of the expression...
remarks
I'm nearly certain that you'll be disappointed with this answer (or disagree with me), but I'm also pretty confident that you're not sure what you're looking for. A guess: you saw functional programming that "doesn't use variables" and assumed that's how all programs can and should be written; but that's just not the case. Sometimes using a variable or two can dramatically improve the readability of a given expression.
Anyway, all of this is truly beside the point because attaching numDuplicates is arguably an anti-pattern in JSON anyway (point #2 above).

PHP 101: variable vs function

I'm creating a global file to hold items that will be re-used throughout my website. What are the differences between these two lines of code? Is one "better" than the other?
This:
$logo = "img/mainlogo.jpg";
vs this:
function logo() {
echo "img/mainlogo.jpg";
}
You should code clear and readable and split in the html and php. The performance profit is not significant...
<?php
...
$logo = "img/mainlogo.jpg";
...
?>
...
<img src="<?= $logo ?>" alt="logo">
...
Of the two options you posted, the function is the better choice. But, to be brutally honest, this sort of thing is exactly what constants are for:
defined('MAIN_LOGO') || define('MAIN_LOGO','img/mainlogo.jpg');
suppose you're working on a site that has to support multiple languages, then you can simply use the same trick:
defined('CLIENT_LOCALE') || define('CLIENT_LOCATE',$whereverYouGetThisFrom);
defined('MAIN_LOGO') || define('MAIN_LOGO','img/mainlogo_'.CLIENT_LOCALE.'.jpg');
//if language is EN, mainlogo_EN.jpg will be used, if lang is ES, mainlogo_ES.jpg, etc...
Besides, a constant, once defined cannot be redefined (clue is in the name, of course). Also: since PHP still has a lot of C-stuff going under the bonnet, and you've tagged this question performance, it might interest you that constants are much like C's macro's, which are a lot faster than regular function calls, or even C++ inline functions (even if they were indeed compiled as inline functions).
Anyway, if you have a ton of these things you want to centralize, either think of creating a couple of ini files for your project, and parse them into some sort of global object
Functions are good.
I see that function logo() is better than $logo. echo doesn't take much memory, but $logo does. Even though, function logo() takes something, it will be handled by PHP's very own garbage collector. You can also use these functions to ensure that you are not misusing the memory allocated.
memory_get_peak_usage();
memory_get_usage();
Explanation:
Upon the ending of an in use function PHP clears the memory it was using, at least more efficiently than if not using a function. If you are using recursive code or something similar that is memory intensive try putting the code into a function or method, upon closing of the function/method the memory used for the function will be garbaged much more efficiently than that of unsetting variables within the loop itself.
Source: 7 tips to prevent PHP running out of memory
The main purpose of a function is to avoid code repetition and perform a specific task. Based on that definition, using a function to only return a value is a bad design.
In that context I think is better a good readability in the code than to save several bytes of memory. We are in 2012, optimization is good but this type of micro-optimization is simply ridiculous. I prefer assigning a variable, it's clear and do what you expect.
$logo = "img/mainlogo.jpg"; can be redefined naturally later without changing code by doing this $logo="img/newmainlogo.jpg"; whereas the function would have to be modified itself, in its first definition.

E_NOTICE: How useful is it REALLY to fix every one?

First off I know this question has gone around more than once here:
Why should I fix E_NOTICE errors?
Why should I fix E_NOTICE errors? Pros and cons
But the more that I fix all E_NOTICEs (as people say you should) the more I notice that:
I am micro-optimising
I am actually making more code and making my code harder to mantain and slower
Take an example:
Say your using the MongoDB PHP driver and you have a MongoDate object in a class var named ts within a class that represents a single row in a collection in your database. Now you acces this var like: $obj->ts->sec but PHP throws a fit (E_NOTICE) because ts in this case is not defined as an object in itself because this particular row does not have a ts field. So you think this is OK, this is desired behaviour, if it's not set return null and I will take care of it myself outside of the interpreters own robotic workings (since you wrap this in a date() function that just returns 1970 if the var is null or a none-object).
But now to fix that E_NOTICE as another developer really wants me to since having ANY E_NOTICEs is terribad and it makes the code slower to not do it according to the errors. So I make a new function in the $obj class called getTs and I give it 3 lines, literally to do nothing but check if the ts var is a MongoDate object and return it if it is...
WHY? Can't PHP do this perfectly fine for me within its much faster interpreter than having to do it within the runtime of the app itself? I mean every where I am having to add useless bumpth to my code, pretty much empty functions to detect variables that I actually just handle with PHPs own ability to return null or checking their instanceof when I really need to (when it is vital to the operation and behaviour of the said function) and don't get me started on the isset()s I have added about 300 lines of isset()s, it's getting out of hand. I have of course got to make this getTs functions because you can't do:
class obj{
public $ts = new MongoDate();
}
I would either have to store the ts within the __constructor (which I am not too happy about either, I am using a lot of magics as it is) or use a function to detect if it's set (which I do now).
I mean I understand why I should fix:
Undefined vars
Assigning properties of unset vars (null vars)
constant errors etc
But if you have tested your code and you know it is safe and will only work the way you desire what is the point in fixing all of the undefined index or none-object errors? Isn't adding a bunch of isset()s and 2 lines functions to your code actually micro-optimisation?
I have noticed after making half my site E_NOTICE compliant that actually it uses more CPU, memory and time now...so really what's the point of dealing with every E_NOTICE error and not just the ones that ARE errors?
Thanks for your thoughts,
You do certainly do get better performance by using isset(). I did some benchmarks, not too long ago, and just hiding errors came out to be about 10x slower.
http://garrettbluma.com/2011/11/14/php-isset-performance/
That said, performance usually isn't a critical factor in PHP. What does, personally drive me crazy is silent errors.
When the interpreter chooses to not flag something as an error (which could lead to instability) is a huge problem. PHP in particular has a tendency to
warn about things that should error (e.g. failure to connect to database) and
issue notices about things that ought to warn (e.g. attempting to access a member of a null object).
Perhaps I'm just overly opinionated about this kind of stuff but I've been bitten before by these silent errors. I recommend always including E_NOTICE in error reporting.
Whether or not you should fix them is certainly debatable, and will just depend on the return in your situation; eg, it's more important if the code will have a longer life-span, more devs, etc.
In general, assuming that your functions will be used (and mis-used) by someone else is the best practice, so you should do isset/!empty/is_object checks to account for this. Often, your code will find it's way into uses and situations you never intended it for.
As far as performance, Every time any kind of error is thrown--E_NOTICE included--the interpreter spins up the error handler, builds a stack trace, and formats the error. The point is that, whether or not you have them reporting, errors always slow execution; therefore, 2-3 function calls to avoid an E_NOTICE will still improve your performance.
Edit:
Alternatives for the above example
I wouldn't necessarily create extra objects to avoid the errors; you can gracefully avoid them without. Here are a couple of options:
1) Function that handles missing ts:
SpecialClass class {
funciton getTs () {
return !empty($this->ts) ? $ts->sec : false;
}
}
2) Deal with missing ts in template/procedure:
if (!empty($obj->ts->sec)) {
//do something
}
I particularly like empty() because you can use it to replace of (isset($var) && ($var or 0 != $var //etc)), saving multiple calls/comparisons and empty never throws notices for the target var or attribute. It will throw an error if you're calling it on a proptery/member of a non-existent variable.

Proper way to declare a function in PHP?

I am not really clear about declaring functions in php, so I will give this a try.
getselection();
function getselection($selection,$price)
{
global $getprice;
switch($selection)
{
case1: case 1:
echo "You chose lemondew <br />";
$price=$getprice['lemondew'].'<br>';
echo "The price:".$price;
break;
Please let me know if I am doing this wrong, I want to do this the correct way; in addition, php.net has examples but they are kind of complex for a newb, I guess when I become proficient I will start using their documentation, thank you for not flaming.
Please provide links that might also help me clear this up?
Your example seems valid enough to me.
foo('bar');
function foo($myVar)
{
echo $myVar
}
// Output: bar
See this link for more info on user-defined functions.
You got off to a reasonable start. Now all you need to do is remove the redundant case 1:, close your switch statement with a } and then close your function with another }. I assume the global array $getprice is defined in your code but not shown in the question.
it's good practice to declare functions before calling them. It'll prevent infrequent misbehavior from your code.
The sample is basically a valid function definition (meaning it runs, except for what Asaph mentions about closing braces), but doesn't follow best practices.
Naming conventions: When a name consists of two or more words, use camelCase or underscores_to_delineate_words. Which one you use isn't important, so long as you're consistent. See also Alex's question about PHP naming conventions.
Picking a good name: a "get" prefix denotes a "getter" or "accessor"; any method or function of the form "getThing" should return a thing and have no affects visible outside the function or object. The sample function might be better called "printSelection" or "printItem", since it prints the name and price of the item that was selected.
Globals: Generally speaking, globals cause problems. One alternative is to use classes or objects: make the variable a static member of a class or an instance member of an object. Another alternative is to pass the data as an additional parameter to the function, though a function with too many parameters isn't very readable.
Switches are very useful, but not always the best choice. In the sample, $selection could easily hold the name of an item rather than a number. This points to one alternative to using switches: use an index into an array (which, incidentally, is how it's done in Python). If the cases have the same code but vary in values used, arrays are the way to go. If you're using objects, then polymorphism is the way to go--but that's a topic unto itself.
The $price parameter appears to serve no purpose. If you want your function to return the price, use a return statement.
When you called the function, you neglected to pass any arguments. This will result in warnings and notices, but will run.

Categories