Skip to content

Laravel

Laravel is a framework for PHP applications. It MAY be used for websites, APIs, and console applications, and backend processing.

GitHub SHOULD be used for code storage, and GitHub Actions SHOULD be used for CI.

The Laravel framework’s own coding style guide SHOULD be followed.

The first-party tool Laravel Pint will automatically enforce this and can be integrated into IDEs and CI pipelines. Pint MAY be used. It is wrapping PHPCS, which MAY be used instead if additional customization to the style guide is desired.

The Eloquent ORM’s naming conventions SHOULD be followed for tables and columns. In cases where the framework’s pluralization rules for table names result in nonsense, the naming convention SHOULD NOT be followed, and a better name can be used instead.

Pint SHOULD be run on pull requests and the results committed to enforce the coding style guide.

The PHPUnit, Larastan, and Cypress tests SHOULD be automatically run for pull requests. These tests SHOULD be required to pass before merging is allowed.

Controllers SHOULD focus on adapting HTTP request/responses to application logic and SHOULD NOT implement application logic themselves. The controller should delegate application logic to other classes.

This enables application logic to be reused in console commands, queued jobs, API controllers, or other “user interfaces” for the application.

The .env.example file SHOULD be included in the repository, and it SHOULD document what needs to be filled in to get a working environment. It MAY contain 1Password vault reference URLs, enabling the op utility to fill it out for a new team member.

A “demo data” seeder SHOULD be included and documented in the README.md file. This SHOULD provide enough test data to use the application normally.

The following tools SHOULD be used for automated tests. In a web application, all four are applicable.

TypeToolNotes
End-to-EndCypresslaracasts/cypress & DB snapshots are useful for integrating Cypress with Laravel
IntegrationPHPUnit or Pest
UnitPHPUnit or Pest
Static AnalysisLarastanLevel 5+

Pest is a wrapper built on PHPUnit. All PHPUnit tests can be run by Pest, and the Pest runner offers easier-to-set-up parallel test execution & reporting for CI pipelines. A repository SHOULD choose PHPUnit or Pest, and stick to using the chosen tool.

Entra ID OpenID Connect SHOULD be used for SSO/MFA. There is a Northwestern package that configures Laravel Socialite to work with our Entra ID tenant.

The lab404/laravel-impersonate SHOULD be used to enable user switching during local development.

Impersonation MAY be enabled for admin users in deployed environments. If it is enabled, it MUST be restricted to known users, and it MUST log impersonation events. It should not be possible for a student to “find” the development environment and switch to an admin users with broad access to see data they are not entitled to.

Generally, applications SHOULD implement a role-based access control system. The spatie/laravel-permission package MAY be used to construct one.

Cypress tests SHOULD run Axe accessibility checks on all pages. There are two options for this, and a repository SHOULD select one:

  1. Cypress.io subscribers can use the Cypress Dashboard’s accessibility reporting feature.
    • This option will provide the most thorough results, at a higher subscription cost.
  2. The cypress-axe package can be included and run on each page.

Accessibility problems SHOULD prevent the tests from passing, and they SHOULD be fixed before merging or deploying.

Applications SHOULD set and read cookies using the framework’s built-in cooking handling on the Request, via the cookie() helper, or another framework-provided mechanism.

Engaging with cookies in this way means that Laravel can sign & encrypt them, which prevents end-users from viewing or tampering with the values:

All cookies created by the Laravel framework are encrypted and signed with an authentication code, meaning they will be considered invalid if they have been changed by the client.

When accessing cookies set by other applications, special handling is required to avoid the framework’s signature validation and decryption.

When setting cookies, developers SHOULD use the built-in functionality unless there is a documented need to share a particular cookie cross-origin.

Developers SHOULD use the #[SensitiveParameter] attribute to mark sensitive data such as passwords, API keys, and private keys. This will prevent PHP from emitting & logging this data in exceptions & stack traces.

The framework’s built in logging system SHOULD be used for general log messages. Login logging MAY use the general logging facility, provided the log storage backend retains the logs long enough.

Audit logging SHOULD NOT use the framework’s general logging facility, as this may contain sensitive data. Instead, audit logs SHOULD be stored in a separate database table or other secure data enclave.

The Laravel Auditing package MAY be used to implement audit logging to the database for write operations.

Sentry MAY be used for error monitoring. Laravel applications use the Laravel SDK for backend error tracking.

Review the guidance in the General Coding Standards document regarding the use of Sentry.

The framework’s Eloquent ORM or query builder library SHOULD be used for data access. Developers SHOULD make an effort to build queries with the query builder & ORM before resorting to raw SQL. Raw SQL queries & expressions MUST be parameterized to prevent SQL injection vulnerabilities.

Tables SHOULD include the created_at/updated_at timestamps. Soft delete functionality SHOULD be used unless there is a compelling reason — such as data volume — to immediately delete records from the DB.

Composer SHOULD be used for dependency management.

The PEAR package manager MUST NOT be used for userland PHP packages.

Some niche PHP extensions may still be distributed via PEAR. If possible, PIE via Packagist SHOULD be used for extensions over PEAR.

The Javascript coding standards MAY be applicable to a Laravel application, since it’s frontend assets often come from the NPM ecosystem.

The framework’s configuration system SHOULD be used for config values.

When building on top of the config system, developers SHOULD NOT add application-specific custom configs to framework-provided config files (like config/app.php). This makes framework upgrades more difficult by adding a new dimension (app-specific options) to the comparison of old & new config format. Instead, developers SHOULD make their own file(s) in config/ and add options there. These will not be impacted by framework upgrades.

The env() helper MUST NOT be called outside the config/*.php files. Config files MAY be cached when deployed, and in this mode env() will return null for all values.

Encrypted environment files (e.g. .env.production.encrypted) MAY be used. The file encryption key MUST NOT be commited in git.

Developers that are decrypting/encrypting the files MUST NOT pass these as command-line arguments and should instead use the interactive prompt in the php artisan env:decrypt/env:encrypt commands to input them. This will avoid writing them to .bash_history and similar.

Storing these config files in version control makes deployment easier, since the environment configuration is deployed with the app code. It may help with code review: if somebody added a new config option that should be set for dev/qa/prod, the diff will indicate changes to the encrypted files. It won’t be readable, but reviewers can at least see somebody updated something and know that it was not forgotten.

  • Filament is a great option for building CRUD screens. This is typically used for admin backends.