Code style must follow PSR-1, PSR-2 and PSR-12. Generally speaking, everything string-like that’s not public-facing should use camelCase. Detailed examples on these are spread throughout the guide in their relevant sections.

General PHP Rules

NULLABLE AND UNION TYPES

Whenever possible use the short nullable notation of a type, instead of using a union of the type with null.

// in a class

// good
public ?string $variable;

// bad
public string | null $variable;

VOID RETURN TYPES

If a method returns nothing, it should be indicated with void. This makes it more clear to the users of your code what your intention was when writing it.

// good

// in a Laravel model
public function scopeArchived(Builder $query): void
{
    $query->
        ...
}

Typed properties

You should type a property whenever possible. Don’t use a docblock.

// good
class Foo
{
    public string $bar;
}

// bad
class Foo
{
    /** @var string */
    public $bar;
}

Docblocks

Don’t use docblocks for methods that can be fully type hinted (unless you need a description).

Only add a description when it provides more context than the method signature itself. Use full sentences for descriptions, including a period at the end.

// Good
class Url
{
    public static function fromString(string $url): Url
    {
        // ...
    }
}

// Bad: The description is redundant, and the method is fully type-hinted.
class Url
{
    /**
     * Create a url from a string.
     *
     * @param string $url
     *
     * @return \Spatie\Url\Url
     */
    public static function fromString(string $url): Url
    {
        // ...
    }
}

Traits

Each applied trait should go on its own line, and the use keyword should be used for each of them. This will result in clean diffs when traits are added or removed.

// Good
class MyClass {
    use TraitA;
    use TraitB;
}

// Bad
class MyClass {
    use TraitA, TraitB;
}

Strings

When possible prefer string interpolation above sprintf and the . operator.

// Good
$greeting = "Hi, I am {$name}.";

// Bad
$greeting = 'Hi, I am ' . $name . '.';

Ternary operators

Every portion of a ternary expression should be on its own line unless it’s a really short expression.

// Good
$name = $isFoo ? 'foo' : 'bar';

// Bad
$result = $object instanceof Model ?
    $object->name :
   'A default value';

If statements

BRACKET POSITION

Always use curly brackets.

// Good
if ($condition) {
   ...
}

// Bad
if ($condition) ...

HAPPY PATH

Generally a function should have its unhappy path first and its happy path last. In most cases this will cause the happy path being in an unindented part of the function which makes it more readable.

// Good

if (! $goodCondition) {
  throw new Exception;
}

// do work
// Bad

if ($goodCondition) {
 // do work
}

throw new Exception;

AVOID ELSE

In general, else should be avoided because it makes code less readable. In most cases it can be refactored using early returns. This will also cause the happy path to go last, which is desirable.

// Good

if (! $conditionA) {
   // condition A failed

   return;
}

if (! $conditionB) {
   // condition A passed, B failed

   return;
}

// condition A and B passed
// Bad
if ($conditionA) {
   if ($conditionB) {
      // condition A and B passed
   }
   else {
     // condition A passed, B failed
   }
}
else {
   // condition A failed
}

COMPOUND IFS

In general, separate if statements should be preferred over a compound condition. This makes debugging code easier.

// Good
if (! $conditionA) {
   return;
}

if (! $conditionB) {
   return;
}

if (! $conditionC) {
   return;
}

// do stuff
// bad
if ($conditionA && $conditionB && $conditionC) {
  // do stuff
}

Comments

Comments should be avoided as much as possible by writing expressive code. If you do need to use a comment, format it like this:

// There should be a space before a single line comment.

/*
 * If you need to explain a lot you can use a comment block. Notice the
 * single * on the first line. Comment blocks don't need to be three
 * lines long or three characters shorter than the previous line.
 */

A possible strategy to refactor away a comment is to create a function with name that describes the comment

// Good
$this->calculateLoans();
// Bad

// Start calculating loans

Whitespace

Statements should be allowed to breathe. In general always add blank lines between statements, unless they’re a sequence of single-line equivalent operations. This isn’t something enforceable, it’s a matter of what looks best in its context.

// Good
public function getPage($url)
{
    $page = $this->pages()->where('slug', $url)->first();

    if (! $page) {
        return null;
    }

    if ($page['private'] && ! Auth::check()) {
        return null;
    }

    return $page;
}
// Bad: Everything's cramped together.
public function getPage($url)
{
    $page = $this->pages()->where('slug', $url)->first();
    if (! $page) {
        return null;
    }
    if ($page['private'] && ! Auth::check()) {
        return null;
    }
    return $page;
}
// Good: A sequence of single-line equivalent operations.
public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->string('email')->unique();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}

Don’t add any extra empty lines between {} brackets.

// Good
if ($foo) {
    $this->foo = $foo;
}

// Bad
if ($foo) {

    $this->foo = $foo;

}

Naming Classes

Naming things is often seen as one of the harder things in programming. That’s why we’ve established some high level guidelines for naming classes.

CONTROLLERS

Generally controllers are named by the plural form of their corresponding resource and a Controller suffix. This is to avoid naming collisions with models that are often equally named.

e.g. UsersController or EventDaysController

When writing non-resourceful controllers you might come across invokable controllers that perform a single action. These can be named by the action they perform again suffixed by Controller.

e.g. PerformCleanupController

RESOURCES (AND TRANSFORMERS)

Both Eloquent resources and Fractal transformers are plural resources suffixed with Resource or Transformer accordingly. This is to avoid naming collisions with models.

JOBS

A job’s name should describe its action.

E.g. CreateUser or PerformDatabaseCleanup

EVENTS

Events will often be fired before or after the actual event. This should be very clear by the tense used in their name.

E.g. ApprovingLoan before the action is completed and LoanApproved after the action is completed.

LISTENERS

Listeners will perform an action based on an incoming event. Their name should reflect that action with a Listener suffix. This might seem strange at first but will avoid naming collisions with jobs.

E.g. SendInvitationMailListener

COMMANDS

To avoid naming collisions we’ll suffix commands with Command, so they are easiliy distinguisable from jobs.

e.g. PublishScheduledPostsCommand

MAILABLES

Again to avoid naming collisions we’ll suffix mailables with Mail, as they’re often used to convey an event, action or question.

e.g. AccountActivatedMail or NewEventMail