I am refactoring an extensive codebase overtime. In the long run we are going to develop the whole system in classes but in the mean time I am using the opportunity to refine my PHP skills and improve some of the legacy code we use across several hundred websites.
I have read conflicting articles over time about how best to return data from a custom function, generally the debate falls into two categories, those concerned about best technical practice and those concerned about ease of reading and presentation.
I am interesting in opinions (with elaboration) on what you consider best practice when returning from a custom PHP function.
I am undecided as to which of the following as a better standard to follow using this basic theoretical function for example;
Approach a.
Populating a return variable and returning it at the end of the function:
<?php
function theoreticalFunction( $var )
{
$return = '';
if( $something > $somethingelse ){
$return = true;
}else{
$return = false;
}
return $return;
}
?>
Approach b.
Returning at each endpoint:
<?php
function theoreticalFunction( $var )
{
if( $something > $somethingelse ){
return true;
}else{
return false;
}
}
?>
A possible duplicate could have been What is the PHP best practice for using functions that return true or false? however this is not limited to simply true or false despite my basic example above.
I have looked through the PSR guidelines but didn't see anything (but I may have missed it so please feel free to point me to PSR with reference :) ).
Extending the original question:
Is the method used to return different depending on the expected/desired output type?
Does this method change depending on the use of procedural or object oriented programming methods? As this question shows, object orientation brings in its own eccentricities to further extend the possible formatting/presentation options Best practices for returns methods in PHP
Please try to be clear in your explanations, I am interested in WHY you choose your preferred method and what, if anything, made you choose it over another method.
I tend towards early returns - leave the function as soon as you know what is going on. One type of this use if called a 'Guard Clause'
Other things I will often do include dropping final else for a default:
if ($something > $somethingelse) {
return true;
}
return false;
and in fact, conditions of the form if (boolean) return true; else return false, can be shortened even further (if it is clearer to you) to just return ($something > $somethingelse);. Extracting a complex if clause from code like this to a usefully named function can help clear up the meaning of code a lot.
There are people arguing for single exit points in functions (only one return at the end), and others that argue for fail/return early. It's simply a matter of opinion and readability/comprehensibility on a case-by-case basis. There is hardly any objective technical answer.
The reality is that it's simply not something that can be prescribed dogmatically. Some algorithms are better expressed as A and others work better as B.
In your specific case neither is "best"; your code should be written as:
return $something > $somethingelse;
That would hopefully serve as example that there's simply no such thing as a generally applicable rule.
I know this question is old but the it is interesting and according to me
there are many things to say about it.
The first thing to say is that there is no real standard about returning in functions or methods.
It's usually ruled by the rules your team has decided to follow, but if you are the only one on this refactoring you can do what you think better.
In the case of returning a value the important thing I guess is
readability. Sometimes it's better to loose a little bit
of performance for a code that is more readable and maintainable.
I will try to show some examples with pros and cons.
Approach A
<?php
function getTariableType($var = null)
{
if (null === $var) {
return 0;
} elseif (is_string($var)) {
return 1;
} else {
return -1;
}
}
Pros:
Explicitness. Each case explains itself, even without any comments.
Structure. There is a branch for each case, every case is delimited clearly
and it's easy to add a statement for a new case.
Cons:
Readability. All these if..else with brackets make the code hard to read and
we really have to pay attention to every part to understand.
Not required code. The last else statement is not required and the code would be
easier to read if the return -1 was only the last statement of the function,
outside of any else.
Approach B
<?php
function isTheVariableNull($var)
{
return (null === $var);
}
Pros:
Readability. The code is easy to read and understand, at the first look we
know that the function is checking whether the variable is null.
Conciseness. There is only one statement and in this case it's fine and clear.
Cons:
Limit. This notation is limited to really little funtions. Using this notation
or even ternary operator becomes harder to understand in more complicated
functions.
Approach C.1
<?php
function doingSomethingIfNotNullAndPositive($var)
{
if (null !== $var) {
if (0 < $var) {
//Doing something
} else {
return 0;
}
} else {
return -1;
}
}
Pros:
Explicitness. Each case is explicit we can reconstruct the logic of the
function when reading it.
Cons:
Readability. When adding many if..else statements the code is really less
readable. The code is then indented many times looks dirty. Imagine the code
with six nested if.
Difficulty to add code. Because the logic seems complex (even if it is not),
it's difficult to add code or logic into the function.
Plenty of logic. If you have many if..else nested it is perhaps because you
should create a second function. NetBeans IDE for example suggests you to create
an other function that handles the logic of all your nested blocks. A function
should be atomic, it should do only one thing. If it does too much work, has
too much logic, it's hard to maintain and understand. Creating an other function
may be a good option.
Approach C.2
This approch aims to present an alternative to the C.1 notation.
<?php
function doingSomethingIfNotNullAndPositive($var)
{
if (null === $var) {
return -1;
} elseif (0 >= $var) {
return 0;
}
//Doing something
}
Pros:
Readability. This notation is very readable. It's
easy to understand what result we will get according to a given value.
Explicitness. As C.1, this approach is explicit in every branch of the
condition.
Cons:
Difficulty to add logic. If the function becomes a bit more complicated,
adding logic would be difficult because we may need to move all the branches of the
condition.
Approach D
<?php
function kindOfStrlen($var)
{
$return = -1;
if (is_string($var)) {
$return = strlen($var);
}
return $return;
}
Pros:
Default value. In this structure we can see that the default value is handled
from the beginning. We have logic in our function, but if we enter in no
branch we have a value anyway.
Ease to add logic. If we need to add a branch if it's easy and it does not
change the structure of the function.
Const:
Not required variable. In this case the $return variable is not required, we
would write the same function without using it. The solution would be to
return -1 at the end, and return strlen($var) in the if, and it would not
be less readable.
Conclusion
I have not listed all the possible notation here, only some of them. What we can
think about them is there is no perfect one, but in some cases an approach seems
better that an other. For example an is_null function would be fine with the
approach B.
Using an approach or an other is really up to you, the important thing is to
choose a logic and to keep it during all your project.
Using the approach b is more fine with me because in approach a you have written very few lines of code, but if there are many lines of code and many return statements, then are chances that i will somewhere use the wrong return type, where $return was assigned a some other place and i did not notice that.
I prever variant b. Not only is it more readable ( you know exactly that you do not need to consider any of the remaining code after a return statement), but it is also more failsafe.
If you either have a bug in the remaining code, or you encounter a set of conditions you did not take into account when designing the system, it would be possible that your result is changed. This cannot happen when you exit the function with return [$someVariable];
<?php
function theoreticalFunction( $var )
{
if( $something > $somethingelse ){
return true;
}
return false;
}
?>
This approach can also be used as on RETURN Statement, the program cursor is returned back and the next statement will not be executed.
I was refactoring some old code when I stumbled upon a construct similar to this:
// function bar() returns a value
// if the value is an instance of customException class, terminate with error code
// else process the regular data
$foo = bar();
checkForException($foo) && exit($foo->errorCode());
process($foo);
Now strange as it might seem, this is a lot shorter then
$foo=bar();
if(checkForException($foo)) {
exit($foo->errorCode();
}
else {
process($foo);
}
And somewhat more readable (at least after the initial surprise) then
$foo=bar();
(checkForException($foo)) ? exit($foo->errorCode()) : process($foo);
While shorter code doesn't necessarily mean more readable code, I find this to be somewhere in the middle of the two "standard" ways above.
In other words, instead of
if($foo) {
bar();
}
else {
// there is no real reason for this to exist, since
// I have nothing to write here, but I want to conform
// to the general coding practices and my coding OCD
}
One could simply write
$foo && bar();
So what is the reasoning behind this not seeing much use? Can it be as simple as "Don't reinvent the wheel, write the more readable if/else, and if you really want to shorten it, that's what ternary operator is for"?
EDIT: Please keep in mind that the above code was quickly derived from the original code and was mean to be just an example of the use of "short circuit" code. If you can, please restrain from suggesting code improvements, since that was not the desired outcome of the question.
Example No.2
userCheckedTheBox($user) && displayAppropriateInfo();
While $foo && bar(); is fewer lines of code it's much less readable. Making your code easy to understand is usually more important than reducing the total LoC. Even if it's you're not working in an environment with multiple programmers, you will have to come back and read your code at some point in the future, and you probably won't be able to remember what the rationale was behind every line of code (Eagleson's Law).
Generally, you should limit the use of these kinds of statements to only those cases where the programmer's intent is absolutely clear. In my opinion, it's very bad practice to have code which tests a condition and code which actively modifies the current state of the program on the same statement.
Here's one acceptable use for this kind of code:
$isValidUser = $userName && usernameIsValid();
Here, both sides of the && operator are testing a condition, the fact that the right side is calling a function to do that does not harm the readability of the code.
There's an old technique which I believe was popular in hacked-together perl scripts to show errors. pseudo-code:
myFunction( ) || exitWithError( "Uh-oh" )
When coding-to-a-deadline, and when the user interface doesn't need to be stellar, it's a quick way to avoid errors.
The style is also popular in javascript for default parameters:
function myfunction(foo) {
foo = foo || 0;
// note that a non-zero default won't work so well,
// because the user could call the function with 0
}
and for null-checks:
var bar = foo && foo.property;
I find that once you're used to it, it's very readable and often more intuitive than if/else or ?:. But you should only use it when it makes sense. Using it everywhere is going to get very confusing. For example, in your example, you should not use it. Personally I use it for simple error checking and some default values. In big projects, you almost always want to do a lot more when an error occurs, so in those cases you shouldn't use this.
Also you should be careful; this only works in languages which have short-circuit evaluation (http://en.wikipedia.org/wiki/Short-circuit_evaluation). And sometimes and and or are short-circuit, while && and || are not.
myfunction() or die("I'm melting!"); is also quite satisfying to write.
Finally, empty else blocks as a rule is something I've never seen before, or heard anyone recommend. It seems very pointless to me. The most readable option for your example is, quite simply:
if( $foo ) {
bar( );
}
For errors you should use real exceptions:
try {
$foo = bar();
} catch(FooException $e) {
exit($e->errorCode);
}
process($foo);
See the documentation for errorhandling.
What ever that code is doing, returning an instance of CustomException just doesn't add up. Why not change the function definition a little:
function bar()
{
$stuff = true;
if ($stuff === true)
{
return 'Value on success';
}
//something went wrong:
throw new CustomException('You messed up');
}
try
{//here's the outlandish try-catch block
$foo = bar();
}
catch (CustomException $e)
{
exit($e->message());//fugly exit call, work on this, too
}
//carry on here, no exception was thrown
Also, calling that second function (checkForException($foo)) is just absurd. Function calls are cheap, but not free. You want to know if the function returned an instance of CustomException? Don't turn that into a function, but use instanceof. Using short-circuit to keep the number of chars (ad thus parse-time) down, while at the same time wasting resources on on all other levels is about as silly as turning up in a V8 mustang on a hyper-miling course.
Another possible Solution for your problem:
$foo = bar();
!checkForException($foo) or exit($foo->errorCode);
process($foo);
But better change !checkForException for isNoException or something along those lines.
I feel dirty every time I "break" out of a for-each construct (PHP/Javascript)
So something like this:
// Javascript example
for (object in objectList)
{
if (object.test == true)
{
//do some process on object
break;
}
}
For large objectLists I would go through the hassle building a more elegant solution. But for small lists there is no noticeable performance issue and hence "why not?" It's quick and more importantly easy to understand and follow.
But it just "feels wrong". Kind of like a goto statement.
How do you handle this kind of situation?
I use a break. It's a perfectly cromulent solution.
It's quick and more importantly easy to understand and follow.
Don't feel bad about break. Goto is frowned upon because it's quick and more importantly not easy to understand and follow.
See, the break doesn't bug me at all. Programming is built on goto, and for-break - like all control structures - is merely a special-purpose form of goto meant to improve the readability of your code. Don't ever feel bad about writing readable code!
Now, I do feel dirty about direct comparisons to true, especially when using the type-converting equality operator... Oh yeah. What you've written - if (object.test == true) - is equivalent to writing if (object.test), but requires more thought. If you really want that comparison to only succeed if object.test is both a boolean value and true, then you'd use the strict equality operator (===)... Otherwise, skip it.
For small lists, there's no issue with doing this.
As you mention, you may want to think about a more 'elegant' solution for large lists (especially lists with unknown sizes).
Sometimes it feels wrong, but it's all right. You'll learn to love break in time.
Like you said ""why not?" It's quick and more importantly easy to understand and follow."
Why feel dirty, I see nothing wrong with this.
I think is is easier to read and hence easier to maintain.
It is meant to be like it. Break is designed to jump out of a loop. If you have found what you need in a loop why keep the loop going?
Breaks and continues are not gotos. They are there for a reason. As soon as you're done with a loop structure, get out of the loop.
Now, what I would avoid is very, very deep nesting (a.k.a. the arrowhead design anti-pattern).
if (someCondition)
{
for (thing in collection)
{
if (someOtherCondition)
{
break;
}
}
}
If you are going to do a break, then make sure that you've structure your code so that it's only ever one level deep. Use function calls to keep the iteration as shallow as possible.
if (someCondition)
{
loopThroughCollection(collection);
}
function loopThroughCollection(collection)
{
for (thing in collection)
{
if (someOtherCondition)
{
doSomethingToObject(thing);
break;
}
}
}
function doSomethingToObject(thing)
{
// etc.
}
I really don't see anythign wrong with breaking out of a for loop. Unless you have some sort of hash table, dictionary where you have some sort of key to obtain a value there really is no other way.
I'd use a break statement.
In general there is nothing wrong with the break statement. However your code can become a problem if blocks like these appear in different places of your code base. In this case the break statements are code small for duplicated code.
You can easily extract the search into a reusable function:
function findFirst(objectList, test)
{
for (var key in objectList) {
var value = objectList[key];
if (test(value)) return value;
}
return null;
}
var first = findFirst(objectList, function(object) {
return object.test == true;
}
if (first) {
//do some process on object
}
If you always process the found element in some way you can simplify your code further:
function processFirstMatch(objectList, test, processor) {
var first = findFirst(objectList, test);
if (first) processor(first);
}
processFirst(
objectList,
function(object) {
return object.test == true;
},
function(object) {
//do some process on object
}
}
So you can use the power of the functional features in JavaScript to make your original code much more expressive. As a side effect this will push the break statement out of your regular code base into a helper function.
Perhaps I'm misunderstanding your use-case, but why break at all? I'm assuming you're expecting the test to be true for at most one element in the list?
If there's no performance issue and you want to clean up the code you could always skip the test and the break.
for (object in objectList)
{
//do some process on object
}
That way if you do need to do the process on more than one element your code won't break (pun intended).
Use a
Object object;
int index = 0;
do
{
object = objectList[index];
index++;
}
while (object.test == false)
if breaking from a for loop makes you feel uneasy.
My preference is to simply use a break. It's quick and typically doesn't complicate things.
If you use a for, while, or do while loop, you can use a variable to determine whether or not to continue:
for ($i = 0, $c = true; ($i < 10) && $c; $i++) {
// do stuff
if ($condition) {
$c= false;
}
}
The only way to break from a foreach loop is to break or return.
I am using NetBeans for PHP 6.5.
In my code I frequently use the following type of command:
if (($row = $db->get_row($sql))) {
return $row->folder;
} else {
return FALSE;
}
Netbeans tells me that I should not be using assignments in the IF statement.
Why ?
They are not bad, but they can lead to dangerous mistakes.
In c like languages, where an assignment is an expression, (to support for example a=b=c=1;) a common error is:
if (a = 1) { .. }
But you wanted to have
if (a == 1) { .. }
Some developers have learned to type
if (1 == a) { .. }
To create an error if one '=' is forgotten. But I think that it does not improve the readability.
However modern compilers, give a warning if you write
if (a = 1) { .. }
which I think is a better solution. In that case you are forced to check if it was what you really meant.
It's probably trying to help you avoid the dreaded typo:
if(a = b)
//logic error
Although I would expect an enviroment smart enough to warn you about that, to also be smart enough to have "oh, don't worry about that case" conditions.
Conditionals often include short circuit operators. So, given this example:
if ( a=func(x) && b=func(y) )
{
// do this
}
It may not be immediately obvious, but the second assignment would only occur if the first returned >0, and if func(y) had other side effects that you were expecting, they would not happen either.
In short, if you know what you are doing and understand the side effects, then there is nothing wrong with it. However, you must consider the possibility that someone else may be maintaining your code when you're gone and they might not be as experienced as you.
Also, future maintainers may think you intended the following:
if ( a==func(x) && b==func(y) ) ...
If they "fix" your code, they actually break it.
In languages that allways return a value on assignments it's not bad (I think it's quite common in functional languages), but (as others allready have said while I typed this) it should usually be avoided since you or someone else might mistake it for a comparison. The compiler should usually warn about it, but it can be ignored if you're sure what you're doing...
how would a code look like if you do not assign the $row value in the loop condition
this would be much more complicated i think...
although not that good to read for some maintainers, no?
well you can do it like
$next = mysql_fetch_assoc($result)
do{
...
...
...
$next = mysql_fetch_assoc($result) or break;
}while ($next)
I use them all the time, with loops (not sure why that would make a difference), like:
$counter = 0;
while( $getWhateverDataObj = mysql_fetch_object( $sqlResult )) {
$getWhateverObj->firstName[$counter] = $getWhateverDataObj->firstName;
$getWhateverObj->lastName[$counter] = $getWhateverDataObj->lastName;
$counter++;
}
And it works fine.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I know this sounds like a point-whoring question but let me explain where I'm coming from.
Out of college I got a job at a PHP shop. I worked there for a year and a half and thought that I had learned all there was to learn about programming.
Then I got a job as a one-man internal development shop at a sizable corporation where all the work was in C#. In my commitment to the position I started reading a ton of blogs and books and quickly realized how wrong I was to think I knew everything. I learned about unit testing, dependency injection and decorator patterns, the design principle of loose coupling, the composition over inheritance debate, and so on and on and on - I am still very much absorbing it all. Needless to say my programming style has changed entirely in the last year.
Now I find myself picking up a php project doing some coding for a friend's start-up and I feel completely constrained as opposed to programming in C#. It really bothers me that all variables at a class scope have to be referred to by appending '$this->' . It annoys me that none of the IDEs that I've tried have very good intellisense and that my SimpleTest unit tests methods have to start with the word 'test'. It drives me crazy that dynamic typing keeps me from specifying implicitly which parameter type a method expects, and that you have to write a switch statement to do method overloads. I can't stand that you can't have nested namespaces and have to use the :: operator to call the base class's constructor.
Now I have no intention of starting a PHP vs C# debate, rather what I mean to say is that I'm sure there are some PHP features that I either don't know about or know about yet fail to use properly. I am set in my C# universe and having trouble seeing outside the glass bowl.
So I'm asking, what are your favorite features of PHP? What are things you can do in it that you can't or are more difficult in the .Net languages?
Documentation. The documentation gets my vote. I haven't encountered a more thorough online documentation for a programming language - everything else I have to piece together from various websites and man pages.
Arrays. Judging from the answers to this question I don't think people fully appreciate just how easy and useful Arrays in PHP are. PHP Arrays act as lists, maps, stacks and generic data structures all at the same time. Arrays are implemented in the language core and are used all over the place which results in good CPU cache locality. Perl and Python both use separate language constructs for lists and maps resulting in more copying and potentially confusing transformations.
Stream Handlers allow you to extend the "FileSystem" with logic that as far as I know is quite difficult to do in most other languages.
For example with the MS-Excel Stream handler you can create a MS Excel file in the following way:
$fp = fopen("xlsfile://tmp/test.xls", "wb");
if (!is_resource($fp)) {
die("Cannot open excel file");
}
$data= array(
array("Name" => "Bob Loblaw", "Age" => 50),
array("Name" => "Popo Jijo", "Age" => 75),
array("Name" => "Tiny Tim", "Age" => 90)
);
fwrite($fp, serialize($data));
fclose($fp);
Magic Methods are fall-through methods that get called whenever you invoke a method that doesn't exist or assign or read a property that doesn't exist, among other things.
interface AllMagicMethods {
// accessing undefined or invisible (e.g. private) properties
public function __get($fieldName);
public function __set($fieldName, $value);
public function __isset($fieldName);
public function __unset($fieldName);
// calling undefined or invisible (e.g. private) methods
public function __call($funcName, $args);
public static function __callStatic($funcName, $args); // as of PHP 5.3
// on serialize() / unserialize()
public function __sleep();
public function __wakeup();
// conversion to string (e.g. with (string) $obj, echo $obj, strlen($obj), ...)
public function __toString();
// calling the object like a function (e.g. $obj($arg, $arg2))
public function __invoke($arguments, $...);
// called on var_export()
public static function __set_state($array);
}
A C++ developer here might notice, that PHP allows overloading some operators, e.g. () or (string). Actually PHP allows overloading even more, for example the [] operator (ArrayAccess), the foreach language construct (Iterator and IteratorAggregate) and the count function (Countable).
The standard class is a neat container. I only learned about it recently.
Instead of using an array to hold serveral attributes
$person = array();
$person['name'] = 'bob';
$person['age'] = 5;
You can use a standard class
$person = new stdClass();
$person->name = 'bob';
$person->age = 5;
This is particularly helpful when accessing these variables in a string
$string = $person['name'] . ' is ' . $person['age'] . ' years old.';
// vs
$string = "$person->name is $person->age years old.";
Include files can have a return value you can assign to a variable.
// config.php
return array(
'db' => array(
'host' => 'example.org',
'user' => 'usr',
// ...
),
// ...
);
// index.php
$config = include 'config.php';
echo $config['db']['host']; // example.org
You can take advantage of the fact that the or operator has lower precedence than = to do this:
$page = (int) #$_GET['page']
or $page = 1;
If the value of the first assignment evaluates to true, the second assignment is ignored. Another example:
$record = get_record($id)
or throw new Exception("...");
__autoload() (class-) files aided by set_include_path().
In PHP5 it is now unnecessary to specify long lists of "include_once" statements when doing decent OOP.
Just define a small set of directory in which class-library files are sanely structured, and set the auto include path:
set_include_path(get_include_path() . PATH_SEPARATOR . '../libs/');`
Now the __autoload() routine:
function __autoload($classname) {
// every class is stored in a file "libs/classname.class.php"
// note: temporary alter error_reporting to prevent WARNINGS
// Do not suppress errors with a # - syntax errors will fail silently!
include_once($classname . '.class.php');
}
Now PHP will automagically include the needed files on-demand, conserving parsing time and memory.
Easiness. The greatest feature is how easy it is for new developers to sit down and write "working" scripts and understand the code.
The worst feature is how easy it is for new developers to sit down and write "working" scripts and think they understand the code.
The openness of the community surrounding PHP and the massive amounts of PHP projects available as open-source is a lot less intimidating for someone entering the development world and like you, can be a stepping stone into more mature languages.
I won't debate the technical things as many before me have but if you look at PHP as a community rather than a web language, a community that clearly embraced you when you started developing, the benefits really speak for themselves.
Variable variables and functions without a doubt!
$foo = 'bar';
$bar = 'foobar';
echo $$foo; //This outputs foobar
function bar() {
echo 'Hello world!';
}
function foobar() {
echo 'What a wonderful world!';
}
$foo(); //This outputs Hello world!
$$foo(); //This outputs What a wonderful world!
The same concept applies to object parameters ($some_object->$some_variable);
Very, very nice. Make's coding with loops and patterns very easy, and it's faster and more under control than eval (Thanx #Ross & #Joshi Spawnbrood!).t
You can use functions with a undefined number of arguments using the func_get_args().
<?php
function test() {
$args = func_get_args();
echo $args[2]; // will print 'd'
echo $args[1]; // will print 3
}
test(1,3,'d',4);
?>
I love remote files. For web development, this kind of feature is exceptionally useful.
Need to work with the contents of a web page? A simple
$fp = fopen('http://example.com');
and you've got a file handle ready to go, just like any other normal file.
Or how about reading a remote file or web page directly in to a string?
$str = file_get_contents('http://example.com/file');
The usefulness of this particular method is hard to overstate.
Want to analyze a remote image? How about doing it via FTP?
$imageInfo = getimagesize('ftp://user:password#ftp.example.com/image/name.jpg');
Almost any PHP function that works with files can work with a remote file. You can even include() or require() code files remotely this way.
strtr()
It's extremely fast, so much that you would be amazed. Internally it probably uses some crazy b-tree type structure to arrange your matches by their common prefixes. I use it with over 200 find and replace strings and it still goes through 1MB in less than 100ms. For all but trivially small strings strtr() is even significantly faster than strtolower() at doing the exact same thing, even taking character set into account. You could probably write an entire parser using successive strtr calls and it'd be faster than the usual regular expression match, figure out token type, output this or that, next regular expression kind of thing.
I was writing a text normaliser for splitting text into words, lowercasing, removing punctuation etc and strtr was my Swiss army knife, it beat the pants off regular expressions or even str_replace().
One not so well known feature of PHP is extract(), a function that unpacks an associative array into the local namespace. This probably exists for the autoglobal abormination but is very useful for templating:
function render_template($template_name, $context, $as_string=false)
{
extract($context);
if ($as_string)
ob_start();
include TEMPLATE_DIR . '/' . $template_name;
if ($as_string)
return ob_get_clean();
}
Now you can use render_template('index.html', array('foo' => 'bar')) and only $foo with the value "bar" appears in the template.
Range() isn't hidden per se, but I still see a lot of people iterating with:
for ($i=0; $i < $x; $i++) {
// code...
}
when they could be using:
foreach (range(0, 12) as $number) {
// ...
}
And you can do simple things like
foreach (range(date("Y"), date("Y")+20) as $i)
{
print "\t<option value=\"{$i}\">{$i}</option>\n";
}
PHP enabled webspace is usually less expensive than something with (asp).net.
You might call that a feature ;-)
The static keyword is useful outside of a OOP standpoint. You can quickly and easily implement 'memoization' or function caching with something as simple as:
<?php
function foo($arg1)
{
static $cache;
if( !isset($cache[md5($arg1)]) )
{
// Do the work here
$cache[md5($arg1)] = $results;
}
return $cache[md5($arg1)];
}
?>
The static keyword creates a variable that persists only within the scope of that function past the execution. This technique is great for functions that hit the database like get_all_books_by_id(...) or get_all_categories(...) that you would call more than once during a page load.
Caveat: Make sure you find out the best way to make a key for your hash, in just about every circumstance the md5(...) above is NOT a good decision (speed and output length issues), I used it for illustrative purposes. sprintf('%u', crc32(...)) or spl_object_hash(...) may be much better depending on the context.
One nice feature of PHP is the CLI. It's not so "promoted" in the documentation but if you need routine scripts / console apps, using cron + php cli is really fast to develop!
Then "and print" trick
<?php $flag and print "Blah" ?>
Will echo Blah if $flag is true. DOES NOT WORK WITH ECHO.
This is very handy in template and replace the ? : that are not really easy to read.
You can use minus character in variable names like this:
class style
{
....
function set_bg_colour($c)
{
$this->{'background-color'} = $c;
}
}
Why use it? No idea: maybe for a CSS model? Or some weird JSON you need to output. It's an odd feature :)
HEREDOC syntax is my favourite hidden feature. Always difficult to find as you can't Google for <<< but it stops you having to escape large chunks of HTML and still allows you to drop variables into the stream.
echo <<<EOM
<div id="someblock">
<img src="{$file}" />
</div>
EOM;
Probably not many know that it is possible to specify constant "variables" as default values for function parameters:
function myFunc($param1, $param2 = MY_CONST)
{
//code...
}
Strings can be used as if they were arrays:
$str = 'hell o World';
echo $str; //outputs: "hell o World"
$str[0] = 'H';
echo $str; //outputs: "Hell o World"
$str[4] = null;
echo $str; //outputs: "Hello World"
The single most useful thing about PHP code is that if I don't quite understand a function I see I can look it up by using a browser and typing:
http://php.net/function
Last month I saw the "range" function in some code. It's one of the hundreds of functions I'd managed to never use but turn out to be really useful:
http://php.net/range
That url is an alias for http://us2.php.net/manual/en/function.range.php. That simple idea, of mapping functions and keywords to urls, is awesome.
I wish other languages, frameworks, databases, operating systems has as simple a mechanism for looking up documentation.
Fast block comments
/*
die('You shall not pass!');
//*/
//*
die('You shall not pass!');
//*/
These comments allow you to toggle if a code block is commented with one character.
My list.. most of them fall more under the "hidden features" than the "favorite features" (I hope!), and not all are useful, but .. yeah.
// swap values. any number of vars works, obviously
list($a, $b) = array($b, $a);
// nested list() calls "fill" variables from multidim arrays:
$arr = array(
array('aaaa', 'bbb'),
array('cc', 'd')
);
list(list($a, $b), list($c, $d)) = $arr;
echo "$a $b $c $d"; // -> aaaa bbb cc d
// list() values to arrays
while (list($arr1[], $arr2[], $arr3[]) = mysql_fetch_row($res)) { .. }
// or get columns from a matrix
foreach($data as $row) list($col_1[], $col_2[], $col_3[]) = $row;
// abusing the ternary operator to set other variables as a side effect:
$foo = $condition ? 'Yes' . (($bar = 'right') && false) : 'No' . (($bar = 'left') && false);
// boolean False cast to string for concatenation becomes an empty string ''.
// you can also use list() but that's so boring ;-)
list($foo, $bar) = $condition ? array('Yes', 'right') : array('No', 'left');
You can nest ternary operators too, comes in handy sometimes.
// the strings' "Complex syntax" allows for *weird* stuff.
// given $i = 3, if $custom is true, set $foo to $P['size3'], else to $C['size3']:
$foo = ${$custom?'P':'C'}['size'.$i];
$foo = $custom?$P['size'.$i]:$C['size'.$i]; // does the same, but it's too long ;-)
// similarly, splitting an array $all_rows into two arrays $data0 and $data1 based
// on some field 'active' in the sub-arrays:
foreach ($all_rows as $row) ${'data'.($row['active']?1:0)}[] = $row;
// slight adaption from another answer here, I had to try out what else you could
// abuse as variable names.. turns out, way too much...
$string = 'f.> <!-? o+';
${$string} = 'asdfasf';
echo ${$string}; // -> 'asdfasf'
echo $GLOBALS['f.> <!-? o+']; // -> 'asdfasf'
// (don't do this. srsly.)
${''} = 456;
echo ${''}; // -> 456
echo $GLOBALS['']; // -> 456
// I have no idea.
Right, I'll stop for now :-)
Hmm, it's been a while..
// just discovered you can comment the hell out of php:
$q/* snarf */=/* quux */$_GET/* foo */[/* bar */'q'/* bazz */]/* yadda */;
So, just discovered you can pass any string as a method name IF you enclose it with curly brackets. You can't define any string as a method alas, but you can catch them with __call(), and process them further as needed. Hmmm....
class foo {
function __call($func, $args) {
eval ($func);
}
}
$x = new foo;
$x->{'foreach(range(1, 10) as $i) {echo $i."\n";}'}();
Found this little gem in Reddit comments:
$foo = 'abcde';
$strlen = 'strlen';
echo "$foo is {$strlen($foo)} characters long."; // "abcde is 5 characters long."
You can't call functions inside {} directly like this, but you can use variables-holding-the-function-name and call those! (*and* you can use variable variables on it, too)
Array manipulation.
Tons of tools for working with and manipulating arrays. It may not be unique to PHP, but I've never worked with a language that made it so easy.
I'm a bit like you, I've coded PHP for over 8 years. I had to take a .NET/C# course about a year ago and I really enjoyed the C# language (hated ASP.NET) but it made me a better PHP developer.
PHP as a language is pretty poor, but, I'm extremely quick with it and the LAMP stack is awesome. The end product far outweighs the sum of the parts.
That said, in answer to your question:
http://uk.php.net/SPL
I love the SPL, the collection class in C# was something that I liked as soon as I started with it. Now I can have my cake and eat it.
Andrew
I'm a little surprised no-one has mentioned it yet, but one of my favourite tricks with arrays is using the plus operator. It is a little bit like array_merge() but a little simpler. I've found it's usually what I want. In effect, it takes all the entries in the RHS and makes them appear in a copy of the LHS, overwriting as necessary (i.e. it's non-commutative). Very useful for starting with a "default" array and adding some real values all in one hit, whilst leaving default values in place for values not provided.
Code sample requested:
// Set the normal defaults.
$control_defaults = array( 'type' => 'text', 'size' => 30 );
// ... many lines later ...
$control_5 = $control_defaults + array( 'name' => 'surname', 'size' => 40 );
// This is the same as:
// $control_5 = array( 'type' => 'text', 'name' => 'surname', 'size' => 40 );
Here's one, I like how setting default values on function parameters that aren't supplied is much easier:
function MyMethod($VarICareAbout, $VarIDontCareAbout = 'yippie') { }
Quick and dirty is the default.
The language is filled with useful shortcuts, This makes PHP the perfect candidate for (small) projects that have a short time-to-market.
Not that clean PHP code is impossible, it just takes some extra effort and experience.
But I love PHP because it lets me express what I want without typing an essay.
PHP:
if (preg_match("/cat/","one cat")) {
// do something
}
JAVA:
import java.util.regex.*;
Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat")
if (m.find()) {
// do something
}
And yes, that includes not typing Int.