Table of Contents

  1. Foreword
  2. Introduction
  3. PHP is Like C
  4. PHP is Not Like C

a. Manage Your Echoes
b. Memory Passing By

Foreword

Before we really kick off the article, there are a few things that need to be established.

  1. For the purposes of this article, it is assumed that you have a very basic knowledge of PHP.
  2. This article does not so much go in depth as bring up a few arbitrary concepts, often missed in tutorials and other places of information.
  3. Yog-Sothoth is the gate.
  4. Yog-Sothoth is also the key to the gate.

Now that these points are out of the way, let us move on to the actual article (after a quick stop at the introduction).

Introduction

Despite not being the best, or even a good language to start off your knowledge of programming, many people new to the many languages of computers are pointed in its direction. It is simple to understand why, what with the popularity of the language throughout websites, its ease of use, its similarity to other languages (for those familiar with such) and the many tutorials, forums and other resources there to give quick help with whatever problem one may encounter. Whether you are new to programming or just new to PHP, there are a few things about the language that ought to be mentioned, yet often remain largely ignored, unused or just downright omitted from the many tutorials out there.

PHP is Like C

As many will know, or just have assumed after seeing all the .php extensions in your local browser address bar, PHP was developed as a language optimised for support of the various needs of websites. It does this marvelously and we love it for all the work it has done throughout the years. However, there is more to PHP than just taking care of your dynamic website content needs, and if it could talk, I am certain that it would like for you to get to know it better. But since it can't, it is up to me to get you two a bit more intimate with one another.

Personally, I have always preferred to make something functional that runs as CLI instead of spending time and effort on a fancy GUI. C does that perfectly, and so does PHP, but what with all the focus on websites, it's a lesser known part of it. Firstly, we have the variables argc and argv, familiar to those of us who have meddled with C or any other of the multitude of languages that boast about them to any passerby. They exist within PHP as well, as $argc and $argv; presumably, that slight change in name is not a much too shocking turn of events.

For the uninitiated, the aforementioned variables take care of two necessary things when dealing with command line arguments. $argc holds the number of arguments passed to the script and $argv holds an array with each and every one of the passed arguments, $argv[0] being the name of the script.

But wait, there is more! If you want to wield your scripts through the command line, there has to be more than just a couple of variables to deal with the potentially passed arguments. One has to worry about output and input, for instance. Now, output is nothing new, echo works as well as for any website, nothing strange there. Input, however is an entirely different thing. Those who have already dealt with opening files in PHP will know that you can do it with fopen() and those who haven't, now you know, look it up somewhere, it'll blow your mind. fopen can be utilised for more than just opening your average files, though. There are a few special strings that you can pass instead of a filename to make it work with stdin, and for special situations when a standard echo just isn't good enough for you, stdout and stderr.

The strings are the following:
php://stdin
php://stdout
php://stderr

I'll let you figure out which is for reading and which are for writing. After successfully opening either of these, you can then use any of the standard functions for operating on a file descriptor such as fwrite, fread, fgets, etc.
An example of code that just waits for a user to input a line, then echoes it back:

<?php
/*Note the lack of error checking for the obscenely bold.*/
echo fgets(fopen('php://stdin', 'r'))
?>

The important thing to note about this method is that what fopen will return is a copy of the underlying file descriptors in the running script. What that translates to is that by opening them this way, you cannot close a stream to the script by way of fclose on the returned resource, just the copy. However, the preferred way is to deal with the file descriptors directly, without fopen. The way to do that is to just directly use STDIN, STDOUT or STDERR; closing any of these however, will result in that stream being closed for the script. This means that the first of the below code snippets will output, but the second one won't:

<?php
fclose(fopen('php://stdout', 'w'));
echo 'Output!';
?>
<?php
fclose(STDOUT);
echo 'Unheard...';
?>

There are other php:// wrappers to open out there, such as php://fd for specifying file descriptors, php://input, php://output and a few other, but this article is not meant to go through all of these and how to use them. For more information about these (and most things regarding PHP), look no further than php.net.

Now that you know how to write code for the command line, you will [almost] never again have to install apache just to test a bit of PHP code.

As for those using UNIX-like operating systems, just like with other scripts, you can put the shebang line (#!/usr/bin/php) at the beginning, pointing to where your interpreter is located and you will not even have to manually invoke php each time you run the script.

PHP is Not Like C

>Manage Your Echoes
There are a few different ways to represent strings in PHP and a few different ways of mishandling them when it comes to output, that keep popping up. The glorious first prize for annoying use of strings and echo goes to the style of endlessly repeated rows of echoes, one after another and they look something like this:

echo "I really could have";
echo "made this into";
echo "one single";
echo "echo statement".$screwthiscode;

You already ought to know about the regular single quote and double quote way of making strings and the difference between them, meaning that single quotes do not allow for variable expansion or any escape sequence beside escaping a single quote. What is persistently forgotten is that they can both span multiple lines. The above code could have easily been written as:

echo "I really could have
made this into
one single
echo statement".$screwthiscode;

Now, there are still minor annoyances here such as it being completely unnecessary to use double quotes when nothing is being escaped, but first let us take a look at two other string forms, often forgotten by either tutorials or users: heredoc and nowdoc.
Heredoc is declared with <<< followed by a keyword that may not be a line found within its content because it ends with the same keyword, which has to have a line to itself with only a semicolon being allowed at its end. A heredoc works just like a double quote, except that you will not have to escape double quotes. An example of a heredoc:

$whatever=<<<OMGHEREDOC
This is a heredoc's contents
And I can use " as much as I damn well want to! """""
OMGHEREDOC;

As you see, not only does the keyword at the end need its own line, the initiating one needs to end with a newline to mark where the content starts. Other than that, the keyword follows the rules of variable names and whitespaces may not infringe on its territory. Note, however, that the keyword is not a variable.

The nowdoc is the single quote equivalent of the heredoc, the difference in declaration is that the initial keyword has to be surrounded by single quotes, e.g. <<<'OMGHEREDOC'. This was not implemented until PHP 5.3, however, so if your PHP is out of date, or if you are on windows, have apache installed and are following the adivce on php.net about which installer to use, it will not work.

As you may have noticed in the code above, there was a variable stuck at the end of the string using the concatenation operator, a fine example of another commonly found mistake in PHP code. An important thing to know about the echo construct is that it allows for comma separation. What you are trying to output need not be one big thing, you can just use commas to separate them instead of the concatenation operator, such as this:

/*Wonderful*/
echo 'some string', $somevar, $someothervar, 'even more string', $whatever;
/*Bastardous*/
echo 'some string'.$somevar.$someothervar.'even more string'.$whatever;

What difference does it make? Quite a lot actually; output is a slow process and depending on how much you are going to do of it, changing to a comma separated list can significantly increase the speed of the script. The reason? Coming right up.

>Memory Passing By
PHP deals with memory in a very different way than, say, C/C++ does. It can't really help it, it's a high level interpreted language that doesn't allow you to deal as directly with memory as compiled languages, nor can it optimise during compile time since it has none. This is also the reason why you should not repeatedly call functions for things you know will not change, an example being:

/*Bad code*/
for($i=0;$i<count($someArray);$i++);
/*Good code*/
$arrSize=count($someArray);
for($i=0;$i<$arrSize;$i++);

But we're sidetracking now, let us get back to how PHP deals with memory, and to do that, let's take a look at passing arguments to functions.

PHP being a lot like C/C++ will allow you two forms of passing function arguments: value and reference. When passing by reference, any modification made to that argument will change the original variable as well. When you pass by value, however, a copy will be made of the variable and only the copy will be modified if modification is to occur. Except that with PHP not being a lot like C/C++, this last part about passing by value isn't entirely true.

The way things work in PHP is that it utilises something called copy-on-write. What this means, skipping all the underlying technicality, is that PHP simply keeps track of which part of memory the argument passed as a value is pointing to and only makes a copy when an attempt to modify the memory is made. Plainly speaking: if you do not plan to actually modify a value, passing by value will be faster than passing by reference (despite the instinct of any C++ programmer). This holds true to any part of the program, including simply assigning values to a new variable and it is why an echo statement with commas is quicker than one with concatenation. In the latter, all the values will actually have to be copied and put together into one new massive string, while in the other, they're just echoed in order straight away.

Never forget that PHP is interpreted, how it handles its memory, the fact that you can cast arrays to objects and vice versa (yes, you can, really), that PHP is viable for the command line as well as websites, and that Nyarlathotep is the messenger of the Other Gods.

I'a Nyarlathotep!
I'a Yog-Sothoth!