Skip to content

Coding Rules

1. Never pass Container into class constructors. Pass all dependencies separately.

Bad:

<?php
namespace Espo\Modules\MyModule;

use Espo\Core\{
    Container,
};

class MyClass
{
    protected $container;

    public function __constructor(Container $container)
    {
        $this->container = $container;
    }
}

Good:

<?php
namespace Espo\Modules\MyModule;

use Espo\Core\{
    ORM\EntityManager
    Utils\Metadata,
};

class MyClass
{
    protected $entityManager;
    protected $metadata;

    public function __constructor(EntityManager $entityManager, Metadata $metadata)
    {
        $this->entityManager = $entityManager;
        $this->metadata = $metadata;
    }
}

Exception: Passing the Container may be acceptable for proxy classes.

2. Never write RAW SQL query. Use ORM instead.

Good:

<?php

$account = $this->entityManager
    ->getRepository('Account')
    ->select(['id', 'name'])
    ->where([
        'type' => 'Customer',
    ])
    ->order('createdAt')
    ->findOne();

3. Specify type hinting for method parameters. Also specify a method return type unless it's supposed to be void.

Parameter types:

<?php
class MyClass
{
    public function myMethod(Request $request, string $text)
    {
    }
}

Return type:

<?php
class MyClass
{
    public function getAsString() : ?string
    {
        // ...
    }
}

4. Never return TRUE or FALSE to indicate a success or failure. Throw an exception if failure, return NULL for empty result.

<?php

use Espo\Core\Exceptions\Error;

class MyClass
{
    public function getAsString() : ?string
    {
        if ($this->isSomethingWrong()) {
            throw new Error("Something is wrong.");
        }

        if ($this->hasNoData()) {
            return null;
        }

        return $this->value;
    }
}

5. Don't write comments, write self explanatory code.

In addition: Do not write phpdoc for non-public methods and properties. It's OK if you don't write phpdoc at all.

Exception: Adding comments may be reasonable in some rare cases.

Bad:

    /**
     * Sanitize input.
     *
     * @param string $input Input string.
     * @return string Sanitized string.
     */
    protected function sanitizeInput(string $input) : string
    {
        // sanitize
        return Util::sanitize($input);
    }

Good:

    protected function sanitizeInput(string $input) : string
    {
        return Util::sanitize($input);
    }

Bad:

// start sanitizing
$string = filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);
// end sanitizing

Good:

$string = $this->sanitizeString($string);

6. Import classes in the beginning of the file.

Bad:

<?php
namespace Espo\Some;

class SomeClass
{
    public function process()
    {
        $object1 = new \Espo\Modules\MyModule\Something();
        $object2 = new \Espo\Modules\MyModule\AnotherThing();
        // ...
        throw new \RuntimeException();
    }
}

Good:

<?php
namespace Espo\Some;

use Espo\Modules\MyModule\{
    Something,
    AnotherThing,
};

use RuntimeException;

class SomeClass
{
    public function process()
    {
        $object1 = new Something();
        $object2 = new AnotherThing();
        // ...
        throw new RuntimeException();
    }
}

7. Not more that 2 levels of indentation per method.

Bad:

<?php
// ...
    public function process()
    {
        if (! $this->isCached()) {
            foreach ($this->itemList as $item) {
                if (! $this->hasItem($item)) {
                    $this->loadItem($item);
                }
            }
        }
    }

Better:

<?php
// ...
    public function process()
    {
        if (! $this->isCached()) {
            foreach ($this->itemList as $item) {
                $this->processLoadItem($item);
            }
        }
    }

Good:

<?php
// ...
    public function process()
    {
        if (! $this->isCached()) {
            $this->processLoadItems();
        }
    }

8. Use early returns.

Bad:

<?php
// ...
    public function getData() : ?Data
    {
        if (! $this->isEmpty()) {
            $this->loadData();

            return $this->data;
        }

        return null;
    }

Good:

<?php
// ...
    public function getData() : ?Data
    {
        if ($this->isEmpty()) {
            return null;
        }

        $this->loadData();

        return $this->data;
    }

8. Avoid too many parameters in functions.

Less is better. Four is too much.

Bad:

<?php
// ...
    public function process(string $city, string $country, string $postalCode)
    {
    }

Good:

<?php
// ...
    public function process(Address $address)
    {
    }

Bad:

<?php
// ...
    public function find(array $where, int $offset = 0, ?int $limit = null, bool $applyAcl = false)
    {
    }

Good:

<?php
// Using builder.
$collection = $finder->getBuilder()
    ->where($where)
    ->offset($offset)
    ->limit($limit)
    ->withAclApplied()
    ->find();