using Programming;

A Blog about some of the intrinsics related to programming and how one can get the best out of various languages.

Getting started with PHP

Getting started with PHP

I started my programming career over 15 years ago...which makes me look really old now that I think about it. When I started my career I started with HTML, then I folded some CSS in, and that's where it sat for a while. Don't get me wrong -- I was a child at the time. Eventually, I started picking up PHP, when I did I think it was version 4.2 or 4.3. That's mostly unimportant, I only learned the basic syntax and programming concepts back then. Eventually I went on to PHP 5, and now even PHP 7.

Through that time I've used a variety of languages and paradigms, but I always return to PHP as a language because it's where I started.

My career started on the web, and it then took a detour into desktop, console, and service-based applications. Now-a-days I do minimal web development, most of my time is spent building large-scale API's and platforms. So I think it's fitting that I write some information on PHP: how to get started, get your environment setup, and build great things.

Setting an Environment Up

Back when I started setting a PHP environment up felt overwhelming. Granted I was brand-new to programming at the time, but it always felt like a daunting task. Over the years it has gotten easier. Partly because I know more now than I did then, partly because of the tooling. We're not going to use any fancy tooling...we're going to do it the old-fashioned way because it's important that you understand what PHP is, and what PHP does.

PHP is just a program

When I started with PHP I thought it was this magical thing, this amazing thing that could never be understood -- and, to be fair, at the time, it was. But as I grew, I realized that PHP is just a program. Yeah, it's a complicated, intelligent, dynamic program, but it's just a program.

Like all other pieces of software on a Windows computer, PHP is just a .exe file that has some .dll files it works with. That's it. Nothing more. That said, when you look at how much is in those files, it starts to become apparent that PHP is not a simple, trivial thing, but a massive, complex system that can do so much.

To get started, we're going to download PHP and play with it before anything else. To do that, go to windows.php.net/download, and select the latest "Thread Safe x64" version. At the time of this writing, it is 7.4.6 VC15 x64 Thread Safe (2020-May-12 15:28:43). You will want the "Zip" package which should be the first option. Once you download it, extract the Zip file somewhere, and open the folder in PowerShell.

PHP REPL / Interactive Shell

Once you have a PowerShell window open, launch the "PHP interactive shell" with the command:

./php -a

It should print "Interactive Shell", then prompt with php >. At this point, we can type some valid PHP in. For example, we could type echo "Hello World"; and then press enter, after which it should print Hello World, then take us back to the php > prompt.

At this point we are in something called a "REPL", or "Read, Evaluate, Print Loop." Different languages call it different things, in PHP it's the "Interactive Shell", in F# we call it "F# Interactive" or fsi, in Python it's the default action of the command python. The overall idea here is that a REPL, or interactive shell, is a common feature of many programming languages.

Anyway, we're going to play with PHP in the REPL briefly. We want to familiarize ourselves with the idea that PHP is nothing special, and go over some very basic PHP syntax. And I mean very basic.

PHP: Statements end with a semi-colon

The first rule of PHP: all "statements" end with a semi-colon (;). What a "statement" is doesn't matter at the moment, but understand that most lines should have a semi-colon at the end. If you get a PHP error about "unexpected , expected ';'", that's what happened.

PHP: echo

To start with, the echo we used above is just a little bit of magic. What echo does is print a string to the "output" tied to the PHP processor. In a web scenario that's the HTTP session, in our REPL it is our console (which is why we just see it as another line after we press enter).

Essentially, echo says "send this to whoever is running our code."

You can give echo any value, but it will try to print the "string" version of the value. For a number, that's the base-10 equivalent (i.e. 15), for a string it would be just the string, for an object you might get some odd results because the object may not have a "string" equivalent defined.

PHP: Variables

Next, let's briefly go over variables.

A "variable" is a name we use that contains a value. In PHP variables are not declared prior to use (that means that we can make a new variable whenever we want), and they can change types throughout usage (which means we can change a variable from a number to some text to a group of other values).

Declaring a variable in PHP is extremely simple: use the dollar-sign ($) and then any name you like so long as it starts with a letter or underscore and does not contain spaces: $some_variable for example. Once you've named it, you use a single equal-sign and then any value to set it: $my_name = "Elliott";. At this point, we can now reference $my_name later in the program and it will be set to "Elliott":

$my_name = "Elliott";
echo "Hello $my_name";

If you run this in the REPL, it should print Hello Elliott.

We didn't talk about this before, but you can embed variables directly in a string: "Hello $my_name" causes PHP to replace $my_name with the value stored in that variable, in this case, "Elliott".

Another way to do this is "string concatenation", which is necessary sometimes.

PHP: String Concatenation

String concatenation is pretty simple. As the name implies, it is taking two things and constructing a string out of them. (Note: the two things don't need to be strings, they will get converted to strings if they are not already.)

String concatenation is achieved simply by putting a "dot" (.) between two values. Typically, when we do this we include a "space" on either side of the dot, such as: echo "Hello " . $my_name;. This will print the exact same thing as our echo "Hello $my_name";, but there are situations where you will need to use string concatenation.

Also, notice how our "Hello " includes the space between the word Hello and $my_name: this is important because the string concatenation / dot operation will directly combine the two strings, there will be no whitespace added.

PHP: Flow Control

Whether you've programmed before or not, you may not immediately understand what 'flow control' means, but it's typically a pretty simple thing.

Flow control is how a program decides between multiple options of what to do next. It's a way of changing the path the program will take. Imagine a train approaching a track-split. Obviously the train has to go left or right, it can't go both, so we use "flow control" to push it one direction or the other: PHP has similar constructs.

The simplest form of flow control in PHP is the if / elseif / else statement, where elseif and else are both optional. An if statement basically says "evaluate the condition in this statement, and execute the code in the body of the statement when the evaluation turns out to be true." The question is: what is true?

PHP: True and False

Most programming languages have the idea of a "boolean". That is, a value which is only allowed to be one of two options: TRUE, or FALSE. There are no other possible options.

PHP has a pretty large set of methods for deciding if something is TRUE or FALSE, but while it's a lot of decisions, it's rather straightforward. I'll be pulling from php.net, but the following values are considered FALSE, all others are TRUE:

  • the literal boolean constant FALSE;
  • the integers 0 and -0;
  • the floating-point / decimal values 0.0 and -0.0;
  • an empty string ("");
  • a string of "0";
  • an array that has zero elements ([] or array());
  • the type NULL;
  • unset variables;
  • a SimpleXML object created from an empty tag;

Every other value is considered TRUE at the time of this writing. The rules may change, so it's recommended to visit the PHP.net documentation on the subject.

Back to Flow Control: Testing Conditions

So now that we understand TRUE and FALSE to a limited degree, we can go back to flow control. In order for an if statement to make a decision, it has to evaluate if the condition is TRUE or FALSE.

To evaluate conditions, we need a way to test things, and PHP supplies that via various operators:

  • ==: test if two items are "mostly the same" (we'll go deeper into this later);
  • ===: test if two items are identical (we'll go deeper into this later);
  • != and <>: test if two items are not "mostly the same" (opposite of ==);
  • !==: test if two items are not identical (opposite of ===);
  • >: test if one item is greater than another item;
  • <: test if one item is less than another item;
  • >=: test if one item is greater than or equal to another item;
  • <=: test if one item is less than or equal to another item;
  • <=>: indicate whether one item is less than, equal to, or greater than another item (we'll go deeper into this later);

For now, we're going to ignore ==, !=, and <=>, then we'll talk about the three of them at a later time.

So, to test a condition we will use === to determine if our name is equal to a comparison: $my_name === "Jon". If $my_name was set to "Jon" before this line, then the result will be TRUE, if it was not, then the result is FALSE.

After we test our condition, we create a new "scope" within the if that has the code we want to run. This is achieved by putting an opening brace ({) after the if, and a closing brace (}) after the code we want to run.

Afterwards, we can use an else in the same way to do something different if our condition was not true.

In PHP, we do this simply by putting it all together with parenthesis around our condition as follows:

if ($my_name === "Jon") {
    echo "You owe me a lot of money, Jon.";
} else {
    echo "Hello $my_name";
}

You'll notice, if you type the first line into the PHP REPL, it gives you php { for the next line instead of php >, this is because the REPL recognizes that you opened a new scope and did not close it yet, so it is going to wait for more code.

Setting up a web environment

Ok, long-winded intro to PHP complete, it's time we setup a web server to process PHP files. This is actually a relatively straightforward process. In many cases you'll find people refer to these as a stack with one of the following names: LAMP, LAPP, LAP, WAMP, WAPP or WAP. What does this all mean?

  • LAMP: Linux, Apache, MySQL, PHP
  • LAPP: Linux, Apache, PostgreSQL, PHP
  • LAP: Linux, Apache, PHP
  • WAMP: Windows, Apache, MySQL, PHP
  • WAPP: Windows, Apache, PostgreSQL, PHP
  • WAP: Windows, Apache, PHP

We're going to setup a WAP server, someday we might make it a WAMP or WAPP server, but for now we don't need any "SQL" component.

If you're running Windows, congratulations! You have the first thing setup. If you're not...I have some bad news: my examples will all be for Windows.

Next, we need to setup Apache and PHP. We'll setup Apache, then we'll tag PHP in.

To setup Apache we need to download a Windows version. The Apache Software Foundation keeps a list of Windows third-parties on their website. We're going to use the Apache Lounge version, which is Apache 2.4 VS16 / VC15 x64 / Win64: https://www.apachelounge.com/download/VS16/binaries/httpd-2.4.43-win64-VS16.zip.

You will also need the Visual C++ Redistributable for Visual Studio 2015-2019 if you do not have it already. Fortunately, Apache Lounge provides a link to a version of it: https://aka.ms/vs/16/release/VC_redist.x64.exe.

Install the redistributable first, then we can setup Apache.

Setting up Apache

Once the redistributables are installed, we can setup Apache. Fortunately, Apache Lounge makes it easy to get things installed. We will install Apache as a service, which means it will start on system boot and logs will be managed by Windows.

We want to put Apache somewhere memorable. For you, I don't care where you put it, but I'm going to put mine under C:\Web\ so that it's somewhere memorable. We want to copy the contents of the Apache24 folder of our download to wherever we decided. With the default setup structure, our web root will be <apache root>\htdocs, so mine will be C:\Web\htdocs.

Once we have Apache copied to our root folder, we need to grab that path (C:\Web in my case) and open the conf\httpd.conf file. Near the top (in my case, line 37) should be a Define SRVROOT ... line, which we will need to modify to the path we are using. Again, we'll use my case:

Define SRVROOT "C:/Web"

Once we've done that, save the file. We're ready to install and run Apache.

To install Apache, open an Admin PowerShell session in the bin folder under your Apache install (C:\Web\bin in my case) and run the following:

.\httpd.exe -k install -n "Apache HTTP Server"

If you get the following error you can ignore it:

AH00558: httpd.exe: Could not reliably determine the server's fully qualified domain name, using <some IPv4 or IPv6 address>. Set the 'ServerName' directive globally to suppress this message

This just means that Apache could not identify a DNS name (such as "www.example.com") to use. We could specify one, but we don't have one.

Once that is complete, run Get-Service ApacheHttpServer in your PowerShell window, and you should see the following:

Status   Name               DisplayName
------   ----               -----------
Stopped  ApacheHttpServer   Apache HTTP Server

This means that the service has been installed successfully.

Next, run Start-Service ApacheHttpServer, then run Get-Service ApacheHttpServer when that completes. You should see:

Status   Name               DisplayName
------   ----               -----------
Running  ApacheHttpServer   Apache HTTP Server

If all went well, Apache is installed and, more importantly, running. To verify, open a web browser and navigate to http://localhost. You should see a very basic page with the text "It works!"

Adding PHP to Apache

Now that Apache is installed, we need to get back into the PHP folder we downloaded and played with earlier.

First, turn Apache off. You can do this with Stop-Service ApacheHttpServer and then running Get-Service ApacheHttpServer to verify.

Create a folder named php inside your Apache root, for me this is C:\Web\php, copy the files from the PHP 7.4.6 x64 Type Safe download into this folder.

Copy the php.ini-development in your new php directory and rename it to php.ini, mine is C:\Web\php\php.ini.

We will need to edit this new php.ini, so go ahead and open it.

Locate the extension_dir settings (on my version, this is line 755) and uncomment the Windows line (757 on my version) by removing the semi-colon (;) from the beginning, then add your PHP root before the ext, mine looks like:

extension_dir = "C:/Web/php/ext"

Next, we need to edit our httpd.conf.

We want to find the DirectoryIndex line (on my version this is line 285). We want to add index.php before index.html, so the line should read:

DirectoryIndex index.php index.html

Next, we need to add the PHP configuration to Apache. To do this, go to the end of the httpd.conf file and add the following, replacing C:/Web with your Apache root directory:

LoadModule php7_module "C:/Web/php/php7apache2_4.dll"
AddType application/x-httpd-php .php
PHPIniDir "C:/Web/php"

Once that is complete, run Start-Service ApacheHttpServer and then Get-Service ApacheHttpServer to verify.

If Apache restarted properly, load http://localhost again to verify that Apache is running. Notice that you still see "It works!" because we haven't added any PHP code yet.

Add an index.php file in your htdocs location (mine is C:\Web\htdocs), and let's add some PHP:

<?php
phpinfo();

All PHP pages must use <?php to indicate the start of PHP code, and ?> to indicate the end of PHP code if the file does not end in PHP code.

Once you do this, load http://localhost, and we should finally see a very nice-looking page that has our PHP version listed at the top ("PHP Version 7.4.6" at the time of this writing) and talks about our PHP installation.

Adding some PHP and Apache features

Once your PHP and Apache install is verified, let's add some more features we may or may not use in future tutorials.

To start with, update httpd.conf and do the following:

  1. Locate rewrite_module in the file (mine is line 162);
  2. Uncomment the pound-sign / number-sign (#) at the beginning;

Next, open the php.ini file and do the following:

  1. Locate extension=curl in the file (mine is line 910) and uncomment the line by removing the semi-colon (;) at the beginning;
  2. Locate extension=gd2 in the file (mine is line 914) and uncomment the line by removing the semi-colon (;) at the beginning;
  3. Locate extension=mbstring in the file (mine is line 920) and uncomment the line by removing the semi-colon (;) at the beginning;
  4. Locate extension=mysqli in the file (mine is line 922) and uncomment the line by removing the semi-colon (;) at the beginning;
  5. Locate extension=pdo_mysql in the file (mine is line 927) and uncomment the line by removing the semi-colon (;) at the beginning;
  6. Locate extension=pdo_pgsql in the file (mine is line 930) and uncomment the line by removing the semi-colon (;) at the beginning;
  7. Locate extension=pgsql in the file (mine is line 932) and uncomment the line by removing the semi-colon (;) at the beginning;

Save both of these files and restart Apache. If you don't want to go through stopping and starting the service, you can edit these files while it is running (though none of your changes will take effect) then use Restart-Service ApacheHttpServer and then Get-Service ApacheHttpServer.

Once you have done this, reload your http://localhost page to verify.

  • Find the apache2handler section, and then the "Loaded Modules" cell, and verify that mod_rewrite is in the list;
  • Find the gd section and verify the "GD Support" cell says enabled;
  • Find the mysqlnd section and verify the "API Extensions" cell says mysqli,pdo_mysql;

You may not find all the extensions we enabled in your index.php, and that is OK: some extensions have prerequisites we did not enable. The pgsql and pdo_pgsql require a PostgreSQL driver that is not provided, for example.


All Set

Now that all this is done, we have completed our WAP installation: Windows + Apache + PHP. The next post will start getting into writing more PHP, specifically getting into more topics like looping, functions, and passing data around. As we get into these topics, I will be describing some of the "good practices" around them. (Note: some folks, including myself and past-me, call these "best practices", but I don't know if they are or not. I call them "good practices" because they're things I like to see when looking at someone else's code.)