Programster's Blog

Tutorials focusing on Linux, programming, and open-source

PHP Cheatsheet

PHP

Table of Contents

  1. Related Posts
  2. Get File Handle For Output Stream
  3. Write To Stderr
  4. Regular Expressions
  5. Destructuring Assignment
  6. Output CSV File
  7. Read Password Input From Terminal
  8. HTTP Basic Auth
  9. References

Related Posts

Get File Handle For Output Stream

There are many useful functions in the standard library that expect a file handle to write to, but you want to output the the output stream instead. An easy solution for this is to get a handle on the output stream like so:

$fileHandle = fopen("php://output", 'w');

Then you can do something like:

$fileHandle = fopen("php://output", 'w');
$myArray = ["hello", "world"];
fputcsv($fileHandle, $myArray);

Feel free to read more on streams in case you want to do anything funky with the input stream etc.

Write To Stderr

If you are writing a CLI script and something goes wrong, you may wish to output to stderr rather than normal stdout when something goes wrong, so they will appear in error logs etc.

fwrite(STDERR, "You messed up..." . PHP_EOL);

Byte Order Mark

If you are ever generating CSV files for Excel users, you probably want to insert a byte order mark at the very start in order to tell Excel that the content is in UTF-8 format. I find it easiest to just define the byte order mark and then use it when necessary like below:

define('BYTE_ORDER_MARK', "\xEF\xBB\xBF");

Regular Expressions

This regex tutorial is particularly useful for this section.

The following can be used to mean "any kind of letter" (e.g. languages have funky characters not in a-zA-Z).

\p{L}

The following means any kind of whitespace character

\p{Zs}

The following means any kind of number

Below is a regular expression for a line that must be alphanumeric with spaces, underscores and hyphens with 4 or more characters (4 spaces would pass though):

/^[0-9a-zA-Z-_ ]{4,}$/

If you support foreign languages, then you may wish to use the following to allow any type of letter:

/^[\p{L}\p{N}-_ ]{4,}$/u

The /u tells PHP to enable unicode mode in PHP and this will not work on funky letters if you don't have it.

Destructuring Assignment

As of PHP 7.1, you can do the following to rapidly set variables based on the properties of an object/array.

$testArray = ['dog' => 1, 'cat' => 2];
list('dog' => $a, 'cat' => $b) = $testArray;
print "value of a is: {$a}" . PHP_EOL; // outputs 1 from $testArray['dog']

Be Warned, if a value is not set, you will get PHP notices, rather than an exception. E.g.

$test_arr = ['dog' => 1, 'cat' => 2, '' => 3];
list('chow' => $a) = $test_arr;
print "value of chow is: {$chow}" . PHP_EOL;

For that, you will get the following output:

php > $test_arr = ['dog' => 1, 'cat' => 2, '' => 3];
php > list('chow' => $a) = $test_arr;
PHP Notice:  Undefined index: chow in php shell code on line 1
php > print "value of chow is: {$chow}" . PHP_EOL;
PHP Notice:  Undefined variable: chow in php shell code on line 1
value of chow is:

Whilst this seems neat, I can foresee it leading to a lot of bugs and would probably just take the time to write more verbose/explicit code.

Output CSV File

define('BYTE_ORDER_MARK', "\xEF\xBB\xBF");
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=output-filename.csv");
header("Pragma: no-cache");
header("Expires: 0");

$fileHandle = fopen("php://output", 'w');
$myArray = ["hello", "world"];
fwrite($fileHandle, BYTE_ORDER_MARK); // for Excel users
fputcsv($fileHandle, $myArray);
die();

Read Password Input From Terminal

This is useful if you want to get a password from the user safely (don't show the characters as they type).

function getPassword($prompt = "Enter Password:")
{
    echo $prompt;
    system('stty -echo');
    $password = trim(fgets(STDIN));
    system('stty echo');
    return $password;
}

HTTP Basic Auth

You can implement http basic auth support in PHP, with the same effect as using the htaccess file. This allows you more flexibility, and resolves an issue with htaccess whereby if you were to connect over http and had http to https redirection enabled, it would ask for your username and password before it would redirect you to https, thus causing you to be prompted twice, and the first time being over an insecure connection.

Below is an example PSR-15 middleware that will require the user to enter the basic auth

<?php

use \Psr\Http\Message\ServerRequestInterface;
use \Psr\Http\Server\RequestHandlerInterface;
use \Psr\Http\Message\ResponseInterface;

class MiddlewareHttpBasicAuth implements \Psr\Http\Server\MiddlewareInterface
{
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        if (AuthService::getInstance()->isLoggedIn())
        {
            $response = $handler->handle($request);
        }
        else
        {
            if(!isset($_SERVER['PHP_AUTH_USER']))
            {
                $response = new \Slim\Psr7\Response(401);
                $response = $response->withHeader('WWW-Authenticate', 'Basic realm="My Realm"');

                // the body is shown if the user clicks cancel at the prompt for entering username/password
                $body = $response->getBody();
                $body->write('Goodbye!');
                $response = $response->withBody($body);
            }
            else
            {
                if
                (
                       $_SERVER['PHP_AUTH_USER'] === HTTP_BASIC_AUTH_USER
                    && password_verify($_SERVER['PHP_AUTH_PW'], HTTP_BASIC_AUTH_PASSWORD_HASH)
                )
                {
                    AuthService::getInstance()->setLoggedIn();
                    $response = $handler->handle($request);
                }
                else
                {
                    // login failed, re-prompt for the details. 
                    // Alternatively, you may wish to show a login failed message here.
                    $response = new \Slim\Psr7\Response(401);
                    $response = $response->withHeader('WWW-Authenticate', 'Basic realm="My Realm"');
                    $body = $response->getBody();
                    $body->write('Goodbye!');
                    $response = $response->withBody($body);
                }
            }
        }

        return $response;
    }
}

References

Last updated: 17th May 2023
First published: 16th August 2018

This blog is created by Stuart Page

I'm a freelance web developer and technology consultant based in Surrey, UK, with over 10 years experience in web development, DevOps, Linux Administration, and IT solutions.

Need support with your infrastructure or web services?

Get in touch