Work in progress!
- 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.
- 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 settings 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.
- Write tests for everything. Also, every endpoint should have a Laravel Dusk E2E test, and every feature should have its own test.
- Keep controllers minimalistic and use actions similar to Laravel Fortify. For example, an interface would be named
UpdatesUserProfileInformation
, and its implementationUpdateUserProfileInformation
. - Keep an activity log of all non-GET requests.
- Implement CSP and other security-related headers from the start. Don't think of it as an after sight.
- 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
orchunkById
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.
- 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.
- 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.
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"
}
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"
],
}
You may use Babel to support code splitting with Inertia.
npm install @babel/plugin-syntax-dynamic-import --dev
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.