Dev Cheat Sheet

Search and browse cheat sheet.
Admin key missing/invalid. Use ?admin=1&key=YOURKEY

Laravel - Core Commands & Workflow

11 items
TopicSnippet
Create Project
If inside Docker/Devilbox, run composer inside the php container to match PHP version.
composer create-project laravel/laravel myapp
cd myapp
Run Dev Server (local)
In Docker/Devilbox you usually browse via vhost instead.
php artisan serve
Environment (.env)
Fixes “No application encryption key has been specified.”
cp .env.example .env
php artisan key:generate
Caches (common fix)
If routes/config/views behaving oddly.
php artisan optimize:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear
Migrations
Use migrate:fresh on dev only (drops tables).
php artisan migrate
php artisan migrate:fresh --seed
Seeder
Run a specific seeder class.
php artisan db:seed
php artisan db:seed --class=UserSeeder
Tinker
Interactive REPL. Great for quick checks.
php artisan tinker
Queue
For async jobs; configure queue driver in .env
php artisan queue:work
php artisan queue:listen
Storage link
Needed when serving user files from storage/app/public.
php artisan storage:link
Logs
In Devilbox run in container or map volume.
tail -f storage/logs/laravel.log
Common permissions fix
Exact user depends on container. In Devilbox often “devilbox” user owns files.
chmod -R ug+rw storage bootstrap/cache
# If needed:
chown -R www-data:www-data storage bootstrap/cache

Laravel - Routing, Controllers, Requests (Quick Patterns)

5 items
TopicSnippet
Routes
Remember api routes are typically stateless + prefixed /api.
// routes/web.php
Route::get('/dashboard', fn() => view('dashboard'));

// routes/api.php
Route::get('/status', fn() => ['ok'=>true]);
Controller
Use resource controllers for CRUD.
php artisan make:controller UserController

// web.php
Route::get('/users', [UserController::class, 'index']);
Form Request Validation
Keeps validation clean.
php artisan make:request StoreUserRequest

public function rules(): array {
  return ['email'=>'required|email'];
}

public function store(StoreUserRequest ){
   = ();
}
Eloquent basics
Use fillable/guarded properly.
User::query()->where('active',1)->latest()->paginate(25);

User::create([...]);
([...]);
();
Relationships
Eager load with with(): User::with('posts')->get().
class User extends Model {
  public function posts(){ return $this->hasMany(Post::class); }
}

$user->posts()->create([...]);

Laravel Mix / Vite - Frontend Build (Fixing “Mix manifest does not exist”)

4 items
TopicSnippet
Laravel Mix (older Laravel 5/6/7)
Creates public/mix-manifest.json. Missing file = you haven’t built assets.
npm install
npm run dev
# or
npm run production
Vite (Laravel 9/10/11)
Vite uses /public/build/manifest.json.
npm install
npm run dev
# build
npm run build
If node deps missing
Useful if weird webpack/mix errors.
rm -rf node_modules package-lock.json
npm cache clean --force
npm install
OpenSSL legacy (older webpack)
Sometimes needed with older build tooling.
export NODE_OPTIONS=--openssl-legacy-provider
npm run dev

Vue - Quick Setup + Patterns

4 items
TopicSnippet
Vue 3 component (SFC)
Script setup is the cleanest modern pattern.
<script setup>
import { ref, computed, onMounted } from 'vue'
const count = ref(0)
const doubled = computed(() => count.value * 2)
onMounted(() => console.log('mounted'))
</script>

<template>
  <button @click="count++">Count: {{ count }} ({{ doubled }})</button>
</template>
Props + Emits
Keeps components predictable.
<script setup>
const props = defineProps({ name: String })
const emit = defineEmits(['save'])
</script>

<template>
  <button @click="emit('save')">Save {{ name }}</button>
</template>
API calls (fetch)
Add error handling + abort controllers for production.
const loading = ref(false)
const data = ref(null)

async function load(){
  loading.value = true
  try {
    const res = await fetch('/api/status')
    data.value = await res.json()
  } finally {
    loading.value = false
  }
}
Vue Router (conceptual)
In SPAs you’ll typically serve the same Laravel view + router handles routes.
const routes = [
  { path: '/', component: Home },
  { path: '/users', component: Users }
]

Laravel Livewire - Quick Patterns (v2/v3 style)

5 items
TopicSnippet
Create component
Creates class + blade view.
php artisan make:livewire UsersTable
Basic component (class)
For large tables use pagination + debounced search.
use Livewire\Component;

class UsersTable extends Component
{
  public string $search = '';

  public function render(){
    $users = User::query()
      ->when($this->search, fn($q)=>$q->where('name','like','%'.$this->search.'%'))
      ->limit(50)->get();

    return view('livewire.users-table', compact('users'));
  }
}
Blade view
wire:model binds state, debounce reduces requests.
<div>
  <input type="text" wire:model.debounce.300ms="search" placeholder="Search..." />

  <ul>
    @foreach($users as $u)
      <li>{{ $u->name }}</li>
    @endforeach
  </ul>
</div>
Actions
Use authorisation + confirm dialogs.
<button wire:click="delete({{ $u->id }})">Delete</button>

public function delete(int $id){
  User::whereKey($id)->delete();
}
Validation
Great for “live” form validation.
protected $rules = ['search' => 'max:50'];

public function updated($field){
  $this->validateOnly($field);
}

Bootstrap - Practical Snippets

4 items
TopicSnippet
Include (CDN)
For production you might bundle instead.
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
Grid
Use g-* for spacing.
<div class="container">
  <div class="row g-3">
    <div class="col-12 col-md-6">Left</div>
    <div class="col-12 col-md-6">Right</div>
  </div>
</div>
Form validation (client-side)
Works nicely with Livewire/Vue too (but avoid double-validation confusion).
<form class="needs-validation" novalidate>
  <input class="form-control" required>
  <div class="invalid-feedback">Required</div>
</form>
<script>
(() => {
  const forms = document.querySelectorAll('.needs-validation')
  Array.from(forms).forEach(form => {
    form.addEventListener('submit', e => {
      if (!form.checkValidity()) { e.preventDefault(); e.stopPropagation(); }
      form.classList.add('was-validated')
    }, false)
  })
})()
</script>
Modal (quick)
For Livewire, sometimes use wire:ignore on complex JS components.
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#m">Open</button>
<div class="modal fade" id="m" tabindex="-1">
 <div class="modal-dialog"><div class="modal-content">
  <div class="modal-header"><h5 class="modal-title">Title</h5></div>
  <div class="modal-body">Body</div>
 </div></div>
</div>

Git - Everyday Workflow

5 items
TopicSnippet
Clone / Fetch / Pull (safe defaults)
Use --ff-only to avoid accidental merge commits when pulling.
git clone <repo>
cd <repo>
git fetch --all --prune
git pull --ff-only
Hard reset to remote (nukes local changes)
Danger: deletes uncommitted changes and untracked files. Great for broken working trees.
git fetch --all --prune
git reset --hard origin/master
git clean -fd
Create branch + push upstream
The -u flag sets upstream so future git push/pull works without specifying branch.
git checkout -b feature/my-change
# edit files
git add -A
git commit -m "Explain change"
git push -u origin feature/my-change
Stash (quick context switch)
If stash pop conflicts, resolve then commit.
git status
git stash push -m "WIP: before switching"
# switch branch
# later...
git stash list
git stash pop
Undo last commit (keep changes)
Soft reset is great if you committed too early or with the wrong message.
git reset --soft HEAD~1
# changes remain staged
# or keep changes unstaged:
git reset HEAD~1

Devilbox - Day-to-day (Laravel projects, htdocs, symlinks)

8 items
TopicSnippet
Project structure
Devilbox expects an htdocs directory per project.
~/projects/MyApp/
  htdocs  -> should point to /public for Laravel
  .devilbox/ (optional configs)
Fix missing htdocs for Laravel
If you get “Missing htdocs directory”, recreate and symlink to public.
cd ~/projects/MyApp
rm -rf htdocs
ln -s public htdocs
If symlink permission denied (WSL/Windows mount)
WSL2 + Windows mounts can block symlinks. Prefer Linux path for dev projects.
rm -rf htdocs
mkdir -p htdocs
# fallback: copy (not ideal)
rsync -a public/ htdocs/

# Better: keep projects inside Linux filesystem (e.g. /home/you/projects)
Exec into PHP container
Run composer/npm/artisan inside container for correct PHP/node libs.
cd ~/code/devilbox
docker compose exec php bash
Run composer install inside Devilbox
Use -lc to ensure shell env loads and commands run with login shell.
docker compose exec php bash -lc 'cd /shared/httpd/MyApp && composer install'
Run npm in Devilbox
Some setups use a separate node container; adjust if your Devilbox has one.
docker compose exec php bash -lc 'cd /shared/httpd/MyApp && npm install && npm run dev'
Common Laravel permissions (Devilbox)
If logs can’t be written, fix ownership/permissions.
docker compose exec php bash -lc '
cd /shared/httpd/MyApp
chmod -R ug+rw storage bootstrap/cache || true
'
Missing htdocs directory in
How to fix: Missing htdocs directory in:XXX
cd ~/projects/XXX <--- XXX is the project folders name
mkdir -p htdocs
rm -rf htdocs/*
ln -s ../public htdocs/public

cd ~/code/devilbox
docker compose restart httpd

MySQL/MariaDB - Practical Ops

5 items
TopicSnippet
Connect (local + docker service)
In Devilbox, DB host often equals the service name (mysql).
mysql -h localhost -u root -p

# in docker networks (service name):
mysql -h mysql -P 3306 -u root -p
Create DB + user (basic)
For local dev you can keep root/no-pass depending on setup, but users are cleaner.
CREATE DATABASE myapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'myapp'@'%' IDENTIFIED BY 'strongpassword';
GRANT ALL PRIVILEGES ON myapp.* TO 'myapp'@'%';
FLUSH PRIVILEGES;
Quick inspect: tables + size
Great for spotting runaway logs/session tables.
SHOW TABLES;

SELECT table_name,
       ROUND((data_length+index_length)/1024/1024,2) AS size_mb
FROM information_schema.TABLES
WHERE table_schema = DATABASE()
ORDER BY size_mb DESC;
Dump / restore (fast dev migrations)
If restore fails on FK order, temporarily disable checks during import.
# dump
mysqldump -h mysql -u root -p myapp > myapp.sql

# restore
mysql -h mysql -u root -p myapp < myapp.sql
FK checks (use carefully)
Use for dev resets/imports. Avoid in production workflows.
SET FOREIGN_KEY_CHECKS=0;
-- import / delete / reseed
SET FOREIGN_KEY_CHECKS=1;

Docker - Essentials (for dev + troubleshooting)

7 items
TopicSnippet
Containers
List running / all containers.
docker ps
docker ps -a
Logs
Follow logs to catch errors.
docker logs -f <container>
Exec shell
Most day-to-day debugging starts here.
docker exec -it <container> bash
# or sh if alpine
Compose up/down
Bring environment up/down.
docker compose up -d
docker compose down
Rebuild after Dockerfile changes
Use when dependencies change.
docker compose build --no-cache
docker compose up -d
Prune (careful)
Frees space; volumes removal can delete DB data.
docker system df
docker system prune -f
# remove volumes too (careful):
docker system prune --volumes -f
Networks
Useful for “can’t connect to mysql/redis” issues.
docker network ls
docker network inspect <name>

Linux/WSL - Permissions & Networking

5 items
TopicSnippet
Find what is using a port
Useful when Vite/Node/NGINX won’t start due to port already in use.
sudo lsof -i :80
sudo lsof -i :5173

# or:
sudo ss -lntp | grep -E ':80|:5173'
Fix Laravel write permissions (generic)
Container user may differ. In Devilbox often files are owned by devilbox user.
chmod -R ug+rw storage bootstrap/cache

# if ownership is wrong:
chown -R www-data:www-data storage bootstrap/cache
Symlink issues on Windows mounts (WSL)
If you see 'Permission denied' on ln -s, move project into WSL filesystem.
# Prefer projects in Linux FS:
# /home/<you>/projects instead of /mnt/c/...

# If you must use /mnt/c, symlinks may fail depending on Windows policy.
Quick disk usage + largest folders
Handy for Docker eating disk space.
df -h

# largest directories:
du -h --max-depth=1 | sort -hr | head -n 20
Edit / open from terminal
If VS Code + WSL has permission issues, ensure you’re using the WSL extension + not mixing elevated Windows VS Code.
code .
code path/to/file.php

# nano fallback:
nano path/to/file.php

Composer / NPM / Git - Quick Hits

4 items
TopicSnippet
Composer install/update
Install uses composer.lock; update changes it.
composer install
composer update
composer dump-autoload
Platform/PHP version mismatch
Better solution: run composer in container with correct PHP.
php -v
composer why-not php 8.2

# If you MUST (not ideal):
composer install --ignore-platform-req=php
NPM basics
Build assets for Mix/Vite.
node -v
npm -v
npm install
npm run dev
npm run build
Git hard reset to remote
Wipes local uncommitted changes.
git fetch --all
git reset --hard origin/master
git clean -fd

Testing - PHPUnit/Pest & Laravel

5 items
TopicSnippet
Run tests (PHPUnit)
artisan test uses Laravel’s runner; both work.
php artisan test

# or:
./vendor/bin/phpunit
Create a test
Feature tests hit HTTP + DB. Unit tests are smaller and faster.
php artisan make:test UserApiTest
# feature test by default

php artisan make:test UserModelTest --unit
Database reset between tests
RefreshDatabase migrates and wraps tests to keep a clean DB state.
use Illuminate\Foundation\Testing\RefreshDatabase;

class UserApiTest extends TestCase
{
  use RefreshDatabase;
}
Example HTTP test (Laravel)
Great sanity test when wiring a SPA to an API.
public function test_status_endpoint_returns_ok(): void
{
  $this->getJson('/api/status')
       ->assertOk()
       ->assertJson(['ok' => true]);
}
Factories + seeding in tests
Factories are the best way to generate realistic data fast.
use App\Models\User;

public function test_user_can_be_created(): void
{
  $user = User::factory()->create();
  $this->assertNotNull($user->id);
}

Handy Extras (often useful in real projects)

5 items
TopicSnippet
.env sanity (DB)
In docker/Devilbox the host is often the service name (e.g. mysql).
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=your_db
DB_USERNAME=root
DB_PASSWORD=
CORS (API)
If SPA can’t call API, check CORS + cookies/sanctum.
# config/cors.php
# or middleware

# Debug quickly:
curl -i https://yourhost/api/status
PHP info quick check
Confirm loaded extensions, INI, upload limits. Remove afterwards.
<?php phpinfo();
Upload limits
Set in php.ini or container config, then restart.
upload_max_filesize=50M
post_max_size=50M
max_execution_time=120
Host File Location
Modify the host file on windows
"C:\Windows\System32\drivers\etc\hosts"

Laravel - Auth & Security

5 items
TopicSnippet
Generate APP_KEY + clear caches
Fixes encryption/session issues and clears stale config/routes/views.
php artisan key:generate
php artisan optimize:clear
CSRF token (Blade) + AJAX header
If you see 419 Page Expired, it’s almost always CSRF/session mismatch.
@csrf

// JS (axios/fetch) include X-CSRF-TOKEN
// meta tag:
<meta name="csrf-token" content="{{ csrf_token() }}">
Rate limiting (routes)
Stops brute force. Tune per route and include username/email key if needed.
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Cache\RateLimiting\Limit;

RateLimiter::for('login', function ($request) {
  return Limit::perMinute(10)->by($request->ip());
});

Route::post('/login', ...)->middleware('throttle:login');
Password hashing (never store plain)
Laravel uses bcrypt/argon depending on config. Always Hash::make().
use Illuminate\Support\Facades\Hash;

$hash = Hash::make($password);

if (Hash::check($password, $hash)) {
  // ok
}
Secure .env + config caching
Caching boosts performance but remember to clear when env/config changes.
# Never expose .env in web root.
# For prod:
php artisan config:cache
php artisan route:cache
php artisan view:cache

Debugging & Performance

5 items
TopicSnippet
Tail Laravel logs
If logs won’t write: fix storage permissions/ownership.
tail -f storage/logs/laravel.log

# if daily logs:
ls -la storage/logs/
Enable query logging (quick dev)
Use in local only; this can be noisy and slow on big traffic.
DB::listen(function ($query) {
  logger()->info('SQL', [
    'sql' => $query->sql,
    'bindings' => $query->bindings,
    'time_ms' => $query->time,
  ]);
});
Common “it’s broken” reset
Clears stale cached bootstrap artifacts and refreshes autoload.
php artisan optimize:clear
rm -rf bootstrap/cache/*.php
composer dump-autoload
Slow page checklist
Most real-world slowness is N+1 queries or missing DB indexes.
- Check N+1: use ->with()
- Add indexes to WHERE/JOIN columns
- Cache expensive results
- Queue slow jobs
- Profile SQL timings
PHP limits and timeouts
If large imports fail: increase memory/time + web server timeouts.
php -i | grep -E "memory_limit|max_execution_time|upload_max_filesize|post_max_size"

# typical:
memory_limit=512M
max_execution_time=120

Deploy / Nginx / SSL

5 items
TopicSnippet
Laravel deploy basics (safe order)
Avoid caching before .env changes are final. Use --force for migrations in prod.
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan optimize
php artisan config:cache
php artisan route:cache
php artisan view:cache
Nginx root for Laravel
Root must point to /public, not project root.
server {
  root /var/www/myapp/public;
  index index.php;

  location / {
    try_files $uri $uri/ /index.php?$query_string;
  }
}
Certbot quick renew check
Dry-run confirms renew works before expiry.
sudo certbot certificates
sudo certbot renew --dry-run
Force HTTPS redirect (Nginx idea)
Best handled at the web server level rather than inside Laravel.
server {
  listen 80;
  server_name example.com;
  return 301 https://$host$request_uri;
}
Reload services
Always run nginx -t before reload to avoid taking the site down.
sudo nginx -t && sudo systemctl reload nginx
sudo systemctl restart php8.3-fpm
sudo systemctl status nginx --no-pager

APIs - Patterns & Tools

5 items
TopicSnippet
cURL basics (GET/POST JSON)
Add -H "Accept: application/json" for Laravel API responses.
curl -i https://example.com/api/status

curl -i -X POST https://example.com/api/login \
  -H "Content-Type: application/json" \
  -d '{"email":"a@b.com","password":"secret"}'
Pagination (Laravel API)
Laravel returns meta/links automatically for paginate().
return User::query()
  ->orderByDesc('id')
  ->paginate(25);
API Resource wrapper
Keeps API responses stable even if DB schema changes.
php artisan make:resource UserResource

return UserResource::collection(
  User::paginate(25)
);
API auth header example
Use Bearer tokens or cookie-based auth (Sanctum) depending on setup.
curl -i https://example.com/api/me \
  -H "Authorization: Bearer <token>" \
  -H "Accept: application/json"
HTTP status codes cheat
In Laravel validation errors commonly return 422 for JSON requests.
200 OK
201 Created
204 No Content
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
422 Validation Error
429 Too Many Requests
500 Server Error