Skip to content

Not necessarily coding standards (naming conventions, avoid else, etc.), but more like 'app'-guidelines - things you don't want to forget.

License

Notifications You must be signed in to change notification settings

protonemedia/laravel-guidelines

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Laravel Guidelines at Protone Media

⚠️ Work in progress! ⚠️

Development Guidelines

Dependencies and styling

  • Use the latest version of the Laravel Framework and additional packages.
  • Use the least amount of additional packages, and avoid solutions that require the installation of additional tools on the server.
  • Stay close to first-party Laravel-style conventions and guidelines. Carefully read the framework documentation and navigate its source code and first-party packages for inspiration.

General

  • Everything should work with Inertia SSR and Laravel Octane.
  • Use translation strings, don't hard-code strings. This also applies to data like the app name, company name, company address, etc. Things may change over time.
  • Prefer storing app-specific settings (like enabling or disabling a feature) in the database rather than configuration files.
  • Avoid events/listeners. As always, it depends on the situation. If we're talking about 5+ actions, this might become cumbersome, and you want to use listeners. But my starting point is to keep it simple within the controller and refactor when it becomes more complex.
  • Use atomic locks for actions like account creation, order confirmation, etc.
  • Actions that involve an unknown amount or database records should always be queued and never performed synchronously. Show a message to the user that the action is queued. Show the user where or how the status can be seen.
  • Present the user clear and informative error messages. Never assume the user knows why something fails.

Testing

  • Write tests for everything. Also, every endpoint should have a Laravel Dusk E2E test, and every feature should have its own test.
  • Ensure that all requests using the HTTP Client have been faked.

Controllers and Actions

  • Keep controllers minimalistic and use actions similar to Laravel Fortify. For example, an interface would be named UpdatesUserProfileInformation, and its implementation UpdateUserProfileInformation.
  • Keep an activity log of all non-GET requests.
  • Don't limit controller methods to CRUD methods. It's perfectly fine to add an approve method, or use an invokable ApproveBlogPost controller.

Security

  • Implement CSP and other security-related headers from the start. Don't think of it as an after sight.
  • Protect your app against Cross-site scripting (XSS). Not only escape user input at the front-end but use the XSS Protection Middleware package to sanitize request input.
  • Prefer uploading files to an external service like S3 instead of allowing file uploads directly to your app server. You may prevent file uploads with the XSS package.

Database and Eloquent

  • Create sensible Model Factories and Seeders. After cloning this repo, there should be a single seeder that you can run to interact with all parts of the app.
  • If you need to display a set of database records, always use pagination.
  • If you need to loop over database records and do some work, always use chunks with the chunk or chunkById method.
  • Never leak Eloquent Models into the front-end. Always use API Resources and don't use toArray() on a Model. Also, never directly use a request to save a model (e.g. Model::create($request->all())). Always validate and manually specify all fields (e.g. Model::create($request->validated())). This way, we can unguard the models.
  • Use the static query() method to begin querying an Eloquent Model.
  • Use Incrementing IDs as the internal primary key. Use UUIDs for consumer-facing endpoints.
  • Prefer timestamps over booleans. For example, published_at instead of is_published.
  • Always prevent the lazy loading of relationships.
  • Keep an eye on the duration of individual database queries. You may add this snippet, which I found in the handleExceedingCumulativeQueryDuration PR.
if (!app()->isProduction()) {
    DB::listen(function (QueryExecuted $event) {
        if ($event->time > 100) {
            throw new QueryException(
                $event->sql,
                $event->bindings,
                new Exception("Individual database query exceeded 100ms.")
            );
        }
    });
}
  • For all data, write a mechanism to delete it as well. Make sure files and database records are deletable without breaking the application.
  • Enforce a morph map to ensure all polymorphs relationships are mapped to an alias: Relation::requireMorphMap().
  • Be careful with chaining orWhere* constraints. When combined with other constraints, you often need to wrap orWhere* method calls.

Mailables and Notifications

  • Prefer attaching a PDF to a Mailable rather than using more text or data in the mail contents.
  • There must be a way for users to resend a Mailable, for example, an order confirmation.
  • When you automate notifications, for example, a cronjob that sends invoice payment reminders, always store a timestamp of the moment you've sent it. You may run the cronjob unlimited times without worrying about sending duplicate notifications.

Misc

ESLint

You may use ESLint to find problems that can be automatically fixed. You'll find a sensible default .eslintrc.js file in this repository.

npm install eslint eslint-plugin-vue --dev

NPM script:

"scripts": {
    "eslint": "./node_modules/.bin/eslint resources/js/ --ext .js,.vue --fix"
}

PHP CS Fixer

You may use PHP CS Fixer to fix your code to follow standards. You'll find a sensible default .php-cs-fixer.php file in this repository.

composer require friendsofphp/php-cs-fixer --dev

Composer script:

"scripts": {
    "php-cs-fixer": [
        "vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --verbose"
    ],
}

Babel

You may use Babel to support code splitting with Inertia.

npm install @babel/plugin-syntax-dynamic-import --dev

Laravel Mix

Deprecated: For new projects, start using Vite.

Install Polyfill extension to include polyfills by using Babel, core-js, and regenerator-runtime.

npm install laravel-mix-polyfill --dev

Checkout the webpack.mix.js example file, which includes fixes for some older browsers.

Sponsorship Support

We proudly support the community by developing Laravel packages and giving them away for free. Keeping track of issues and pull requests takes time, but we're happy to help! If this package saves you time or if you're relying on it professionally, please consider supporting the maintenance and development.

Open-source packages

  • Inertia.js Events for Laravel Dusk: This new package provides helper methods for Laravel Dusk that you can use to wait for specific Inertia.js events to fire.
  • Inertia.js Tables for Laravel Query Builder: This package provides a DataTables-like experience for Inertia.js with support for searching, filtering, sorting, toggling columns, and pagination.
  • Laravel Analytics Event Tracking: Laravel package to easily send events to Google Analytics.
  • Laravel Blade On Demand: Laravel package to compile Blade templates in memory.
  • Laravel Cross Eloquent Search: Laravel package to search through multiple Eloquent models.
  • Laravel Eloquent Scope as Select: Stop duplicating your Eloquent query scopes and constraints in PHP. This package lets you re-use your query scopes and constraints by adding them as a subquery.
  • Laravel Eloquent Where Not: This Laravel package allows you to flip/invert an Eloquent scope, or really any query constraint.
  • Laravel Form Components: Blade components to rapidly build forms with Tailwind CSS Custom Forms and Bootstrap 4. Supports validation, model binding, default values, translations, includes default vendor styling and fully customizable!
  • Laravel MinIO Testing Tools: This package provides a trait to run your tests against a MinIO S3 server.
  • Laravel Mixins: A collection of Laravel goodies.
  • Laravel Paddle: Paddle.com API integration for Laravel with support for webhooks/events.
  • Laravel Verify New Email: This package adds support for verifying new email addresses: when a user updates its email address, it won't replace the old one until the new one is verified.
  • Laravel WebDAV: WebDAV driver for Laravel's Filesystem.
  • Laravel XSS Protection Middleware: Laravel Middleware to protect your app against Cross-site scripting (XSS). It sanitizes request input by utilising the Laravel Security package, and it can sanatize Blade echo statements as well.

Credits

License

The MIT License (MIT). Please see License File for more information.

About

Not necessarily coding standards (naming conventions, avoid else, etc.), but more like 'app'-guidelines - things you don't want to forget.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project