Best practices with PSR Standards for PHP

Mubasheer Shaik
The Startup
Published in
6 min readMay 29, 2019

PHP has never truly had a uniform standard for writing code. Everyone follows their own naming conventions and coding style guidelines.

PSR Standards

Coding Standards are an important factor for achieving a high code quality. A common visual style, naming conventions, and other technical settings allow us to produce a homogenous code which is easy to read and maintain.

The coding standards try to cover both the technical standard as well as giving incentives for a common development style. These guidelines must be followed by everyone who creates code. If you’re an avid developer you should come across the PSR which stands for “PHP Standards Recommendation.”.

As for the PSR standards themselves, there are various standard but only 7 have been accepted by all members. In this article, we’ll look at some common but most used standards in some detail.

PSR-0 — A standard recommendation that describes “the mandatory requirements that must be adhered to for autoloader interoperability”.

  • A fully-qualified namespace and class must have the following structure \<VendorName>\(<Namespace>\)*<Class Name>.
  • Each namespace must have a top-level namespace (“Vendor Name”).
  • Each namespace can have as many sub-namespaces as it wishes.
  • Each namespace separator is converted to a DIRECTORY_SEPARATOR when loading from the file system.
  • Each _ character in the CLASS NAME is converted to a DIRECTORY_SEPARATOR. The _ character has no special meaning in the namespace.
  • The fully-qualified namespace and class is suffixed with .php when loading from the file system.
  • Alphabetic characters in vendor names, namespaces, and class names may be of any combination of lower case and upper case.

Examples :

\Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php\Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php\Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php .\Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php .

PSR-1 — Basic Coding Standard: these rules focus on naming conventions and file structure. It ensures a high level of technical interoperability between shared PHP code. Imagine if your application is used some multiple third-party components and all these use different naming conventions and character encoding so that would be a mess.

  • Only use the <?php and <?= tags.
  • Only use UTF-8 without BOM for PHP code.
  • Separate side-effects (generate output, access a database etc.) and declarations.
  • Enforce PSR-0 (A standard recommendation that describes “the mandatory requirements that must be adhered to for autoloader interoperability.”).
  • Class names must be defined in StudlyCaps.
  • Class constants must be defined in upper case with underscore separators.
    Method names must be defined in camelCase.

PSR-2 — Coding Style Guide: It follows all psr-1 rules. Its purpose is to have a single style guide for PHP code that results in uniformly formatted shared code.

  • Basic Coding Standard :

Code MUST follow PSR-1.

  • Files

All PHP files MUST use the Unix LF (linefeed) line ending.
All PHP files MUST end with a single blank line.
The closing ?> tag MUST be omitted from files containing only PHP.

  • Lines

There MUST NOT be a hard limit on line length.
The soft limit MUST be 120 characters; lines SHOULD be 80 characters or less.
There MUST NOT be trailing whitespace at the end of non-blank lines.
Blank lines MAY be added to improve readability and to indicate related blocks of code.
There MUST NOT be more than one statement per line.

  • Indenting

Code MUST use 4 spaces for indenting, and MUST NOT use tabs for indenting.

  • Keywords and True/False/Null

PHP keywords MUST be in lower case.
The PHP constants true, false, and null MUST be in lower case.

  • Namespace and Use Declarations

There MUST be one blank line after the namespace declaration.
All use declarations MUST go after the namespace declaration.
There MUST be one use keyword per declaration.
There MUST be one blank line after the use block.

<?phpnamespace App;use \Vendor\Lib1;
use \Vendor\Lib2;
class Sample
{
}
  • Extends and Implements

The extends and implements keywords MUST be declared on the same line as the class name. e.g.

class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
//constant,property,methods}

Lists of implements MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one interface per line.

class ClassName extends ParentClass implements 
\ArrayAccess,
\Countable
{
//constant,property,methods}

Opening braces for classes MUST go on the next line, and closing braces MUST go on the next line after the body.

  • Properties :

Visibility MUST be declared on all properties.

There MUST NOT be more than one property declared per statement.

The var keyword MUST NOT be used to declare a property.

Property names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility. e.g.

namespace \Vendor\Package;class ClassName 
{
public $foo = null;}
  • Methods

There MUST NOT be a space after the opening parenthesis, and there MUST NOT be a space before the closing parenthesis. e.g.

namespace \Vendor\Package;class ClassName 
{
public function foo($arg1,$arg2,$arg3=[])
{
//method body
}}
  • Method Arguments

There MUST NOT be a space before each comma.

There MUST be one space after each comma.

Method arguments with default values MUST go at the end of the argument list.

Example of Arguments not in the same line, when have a long list of arguments.

namespace \Vendor\Package;class ClassName 
{
public function veryLongMethodNameHere(
int $arg1,
&$arg2,
array $arg3 = [])
{
//method body
}}
  • Qualifiers (abstract, final, and static)

When present, the abstract and final declarations MUST precede the visibility
declaration.

When present, the static declaration MUST come after the visibility declaration.

<?php
namespace Vendor\Package;
abstract class ClassName
{
protected static $foo;
abstract protected function zim(); final public static function bar()
{
// method body
}
}
  • Method and Function Calls

There MUST NOT be a space between the method or function name and the opening parenthesis.

There MUST NOT be a space after the opening parenthesis.

There MUST NOT be a space before the closing parenthesis.

In the argument list, there MUST NOT be a space before each comma, and there MUST be one space after each comma.

<?php
bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);

Example of Arguments not in the same line, when have a long list of arguments.

<?php
$foo->bar(
$longArgument,
$longerArgument,
$muchLongerArgument
);
  • Control Structures

There MUST be one space after the control structure keyword.

There MUST NOT be a space after the opening parenthesis.

There MUST NOT be a space before the closing parenthesis.

There MUST be one space between the closing parenthesis and the opening brace.

The structure body MUST be indented once.

The closing brace MUST be on the next line after the body.

  • if-elseif-else

The keyword elseif SHOULD be used instead of else if.

else and elseif is on the same line as the closing brace from the earlier body.

Note the placement of parentheses, spaces, and braces.

<?php
if ($expr1) {
// if body
} elseif ($expr2) {
// elseif body
} else {
// else body;
}
  • switch and case

The case statement MUST be indented once from the switch.

The break keyword (or other terminating keywords) MUST be indented at the same level as the case body.

There MUST be a comment such as // no break when fall-through is intentional in a non-empty case body.

Note the placement of parentheses, spaces, and braces.

<?php
switch ($expr) {
case 0:
echo 'First case, with a break';
break;
case 1:
echo 'Second case, which falls through';
// no break
case 2:
case 3:
case 4:
echo 'Third case, return instead of break';
return;
default:
echo 'Default case';
break;
}

For all other control statements you can read the PHP-FIG.

  • In-Code Documentation

All PHP files should include a DocBlock header.

All classes should include a DocBlock for the class definition.

All class constants, properties and methods should include a DocBlock to explain their purpose.

All functions should include a DocBlock to explain their purpose.

PSR-3 — Logger Interface

PSR-3 describes a shared logging interface which improves reusability.

PSR-4 — Improved Autoloading

The main goal of PSR-4 is to remove the remnants of PSR-0 and the pre-5.3 days completely and allow for a more concise folder structure.

I have covered only PSR-1 and PSR-2 with some best practices I hope you like it. Thanks for reading the article all feedbacks are welcome.

--

--

Mubasheer Shaik
The Startup

Release Manager, Pole to win. Former Tech lead, GKB LABS.