Laravel Development Setup
#laravel #php #setup #development #environment #docker
Last Updated: May 18, 2025 Related: .NET vs Laravel Complete Developer Guide
Quick Navigation
- [[#Development Environment Setup]]
- [[#Laravel Installation Methods]]
- [[#Database Configuration]]
- [[#Essential Packages]]
- [[#Development Workflow]]
- [[#Testing Setup]]
- [[#Deployment Preparation]]
Development Environment Setup
๐ณ Docker Setup (Recommended)
Laravel Sail (Official Docker Environment)
# Create new Laravel project with Sail
curl -s https://laravel.build/my-app | bash
cd my-app
# Start the application
./vendor/bin/sail up -d
# Access the application
# http://localhost
Custom Docker Setup
# docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "8000:8000"
volumes:
- .:/var/www/html
depends_on:
- database
- redis
environment:
- APP_ENV=local
- APP_DEBUG=true
database:
image: mysql:8.0
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: password
MYSQL_USER: laravel
MYSQL_PASSWORD: password
volumes:
- db_data:/var/lib/mysql
redis:
image: redis:alpine
ports:
- "6379:6379"
mailhog:
image: mailhog/mailhog
ports:
- "1025:1025"
- "8025:8025"
volumes:
db_data:
๐ป Local Development Setup
Requirements
- PHP 8.1+ with extensions:
- BCMath
- Ctype
- Fileinfo
- JSON
- Mbstring
- OpenSSL
- PDO
- Tokenizer
- XML
- Composer
- Node.js & npm/yarn
- Database (MySQL, PostgreSQL, SQLite)
Installation Commands
# Install PHP and dependencies (Ubuntu/Debian)
sudo apt update
sudo apt install php8.2 php8.2-cli php8.2-common php8.2-mysql \
php8.2-xml php8.2-curl php8.2-mbstring php8.2-zip php8.2-gd
# Install Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
# Install Node.js (using NodeSource)
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
Laravel Installation Methods
๐ Laravel Installer
# Install Laravel installer globally
composer global require laravel/installer
# Create new project
laravel new my-app
cd my-app
# Alternative: Create with specific version
laravel new my-app --version=10.*
๐ฆ Composer Create-Project
# Create new Laravel project
composer create-project laravel/laravel my-app
# With specific version
composer create-project laravel/laravel:^10.0 my-app
# For development (includes dev dependencies)
composer create-project laravel/laravel my-app --prefer-source
โ๏ธ Initial Configuration
# Generate application key
php artisan key:generate
# Set up environment file
cp .env.example .env
# Configure database in .env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_app
DB_USERNAME=root
DB_PASSWORD=password
# Run migrations
php artisan migrate
# Link storage directory
php artisan storage:link
Database Configuration
๐๏ธ Multiple Database Connections
// config/database.php
'connections' => [
'primary' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'primary_db'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
'analytics' => [
'driver' => 'mysql',
'host' => env('ANALYTICS_DB_HOST', '127.0.0.1'),
'database' => env('ANALYTICS_DB_DATABASE', 'analytics_db'),
'username' => env('ANALYTICS_DB_USERNAME', 'root'),
'password' => env('ANALYTICS_DB_PASSWORD', ''),
// ... other config
],
'testing' => [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
],
];
// Usage in models
class User extends Model
{
protected $connection = 'primary';
}
class AnalyticsEvent extends Model
{
protected $connection = 'analytics';
}
๐ Database Seeding Setup
// database/seeders/DatabaseSeeder.php
class DatabaseSeeder extends Seeder
{
public function run(): void
{
if environment('local', 'staging') {
$this->call([
UserSeeder::class,
ProductSeeder::class,
CategorySeeder::class,
]);
}
// Production-safe seeders
$this->call([
RoleSeeder::class,
PermissionSeeder::class,
]);
}
}
// Example seeder with factory
class UserSeeder extends Seeder
{
public function run(): void
{
// Create admin user
User::factory()->create([
'name' => 'Admin User',
'email' => 'admin@example.com',
'email_verified_at' => now(),
'role' => 'admin',
]);
// Create test users
User::factory(50)->create();
}
}
// Run seeders
php artisan db:seed
php artisan db:seed --class=UserSeeder
Essential Packages
๐ ๏ธ Development Packages
# Debug and profiling
composer require --dev barryvdh/laravel-debugbar
composer require --dev barryvdh/laravel-ide-helper
# Testing
composer require --dev pestphp/pest
composer require --dev pestphp/pest-plugin-laravel
# Code quality
composer require --dev nunomaduro/larastan
composer require --dev squizlabs/php_codesniffer
# API documentation
composer require --dev darkaonline/l5-swagger
๐ฆ Production Packages
# API resources and validation
composer require spatie/laravel-query-builder
composer require spatie/laravel-permission
# Monitoring and logging
composer require spatie/laravel-activitylog
composer require sentry/sentry-laravel
# Performance
composer require predis/predis # Redis client
composer require pusher/pusher-php-server # WebSocket support
# Image processing
composer require intervention/image
โก Frontend Assets Setup
# Install Node dependencies
npm install
# Development build
npm run dev
# Watch for changes
npm run watch
# Production build
npm run build
# Install additional packages
npm install axios vue@next @vitejs/plugin-vue
npm install --save-dev tailwindcss autoprefixer
Development Workflow
๐ง Artisan Commands Reference
# Application
php artisan serve # Start development server
php artisan down # Put app in maintenance mode
php artisan up # Bring app back online
# Database
php artisan migrate # Run migrations
php artisan migrate:rollback # Rollback migrations
php artisan migrate:refresh --seed # Refresh and seed
php artisan db:wipe # Drop all tables
# Code generation
php artisan make:controller UserController --resource
php artisan make:model User -mfcs # Model with migration, factory, controller, seeder
php artisan make:request StoreUserRequest
php artisan make:middleware CheckAge
# Optimization
php artisan optimize # Optimize for production
php artisan optimize:clear # Clear optimization cache
php artisan config:cache # Cache configuration
php artisan route:cache # Cache routes
php artisan view:cache # Cache views
๐๏ธ Project Structure Conventions
app/
โโโ Console/Commands/ # Custom Artisan commands
โโโ Http/
โ โโโ Controllers/
โ โ โโโ Api/ # API controllers
โ โ โโโ Web/ # Web controllers
โ โโโ Middleware/
โ โโโ Requests/ # Form requests
โ โโโ Resources/ # API resources
โโโ Models/
โโโ Services/ # Business logic
โโโ Repositories/ # Data access layer
โโโ Jobs/ # Queued jobs
resources/
โโโ views/
โ โโโ components/ # Blade components
โ โโโ layouts/ # Page layouts
โ โโโ partials/ # Reusable partials
โโโ js/ # JavaScript files
โโโ css/ # Stylesheets
config/ # Configuration files
database/
โโโ migrations/
โโโ factories/
โโโ seeders/
tests/
โโโ Feature/ # Feature tests
โโโ Unit/ # Unit tests
โโโ Pest.php # Pest configuration
๐ Git Workflow
# .gitignore additions for Laravel
/node_modules
/public/hot
/public/storage
/storage/*.key
/vendor
.env
.env.backup
.phpunit.result.cache
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
# Pre-commit hooks setup
composer require --dev brianium/paratest
composer require --dev phpunit/phpunit
# Add to package.json scripts
"scripts": {
"test": "php artisan test",
"test:parallel": "php artisan test --parallel",
"lint": "phpcs --standard=PSR12 app/",
"lint:fix": "phpcbf --standard=PSR12 app/"
}
Testing Setup
๐งช Pest PHP Configuration
// tests/Pest.php
use Illuminate\Foundation\Testing\RefreshDatabase;
usesclass, RefreshDatabase::class)->in('Feature';
usesclass)->in('Unit';
// Global functions
function actingAsUser($user = null): TestCase
{
$user = $user ?: User::factory()->create();
return test()->actingAs($user);
}
function actingAsAdmin(): TestCase
{
$admin = User::factory()->admin()->create();
return test()->actingAs($admin);
}
โ Example Tests
// tests/Feature/UserRegistrationTest.php
<?php
test('user can register with valid data', function () {
$userData = [
'name' => 'John Doe',
'email' => 'john@example.com',
'password' => 'password123',
'password_confirmation' => 'password123',
];
$response = $this->post('/register', $userData);
$response->assertRedirect('/dashboard');
$this->assertDatabaseHas('users', [
'email' => 'john@example.com',
]);
});
test('user cannot register with invalid email', function () {
$userData = [
'name' => 'John Doe',
'email' => 'invalid-email',
'password' => 'password123',
'password_confirmation' => 'password123',
];
$response = $this->post('/register', $userData);
$response->assertSessionHasErrors('email');
$this->assertDatabaseMissing('users', [
'email' => 'invalid-email',
]);
});
// tests/Unit/UserModelTest.php
test('user can have many posts', function () {
$user = User::factory()->create();
$posts = Post::factory(3)->create(['user_id' => $user->id]);
expect($user->posts)->toHaveCount(3);
expectclass;
});
๐ญ Database Testing
// tests/TestCase.php
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
protected function setUp(): void
{
parent::setUp();
// Run migrations for each test
$this->artisan('migrate:fresh');
// Seed test data
$this->seed();
}
protected function tearDown(): void
{
// Clean up after each test
$this->artisan('migrate:reset');
parent::tearDown();
}
}
// Database assertions
test('product creation updates inventory', function () {
$product = Product::factory()->create(['quantity' => 100]);
$product->decreaseQuantity(20);
expect($product->fresh()->quantity)->toBe(80);
$this->assertDatabaseHas('products', [
'id' => $product->id,
'quantity' => 80,
]);
});
Environment Configuration
๐ง Environment Files
# .env.local (development with Docker)
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:generated-key
APP_DEBUG=true
APP_URL=http://localhost
DB_CONNECTION=mysql
DB_HOST=database
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=password
BROADCAST_DRIVER=redis
CACHE_DRIVER=redis
FILESYSTEM_DISK=local
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
๐ Environment Validation
// config/app.php - Add validation for required env vars
if (app()->environment('production')) {
$required = [
'APP_KEY',
'DB_PASSWORD',
'MAIL_PASSWORD'
];
foreach ($required as $var) {
if (empty(env($var))) {
throw new Exception("Required environment variable {$var} is not set");
}
}
}
// Or use a dedicated package
composer require vlucas/phpdotenv
// In bootstrap/app.php
$dotenv = Dotenv\Dotenv::createUnsafeImmutable(__DIR__.'/../');
$dotenv->load();
$dotenv->required(['APP_KEY', 'DB_CONNECTION']);
Performance Optimization
โก Caching Strategies
// config/cache.php - Multiple cache stores
'stores' => [
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache/data'),
],
'redis' => [
'driver' => 'redis',
'connection' => 'cache',
'lock_connection' => 'default',
],
'tags' => [
'driver' => 'redis',
'connection' => 'cache',
],
],
// Usage
Cache::tags(['users', 'posts'])->put('user.1', $user, 3600);
Cache::tags(['posts'])->flush(); // Clear only post-related cache
// Model caching
class User extends Model
{
public function getCachedPosts()
{
return Cache::remember(
"user.{$this->id}.posts",
3600,
fn() => $this->posts()->get()
);
}
}
๐ Queue Configuration
// config/queue.php
'connections' => [
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
'after_commit' => false,
],
],
// Job example
class SendWelcomeEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(
public User $user
) {}
public function handle(): void
{
Mail::to($this->user->email)->send(new WelcomeMail($this->user));
}
public function failed(Throwable $exception): void
{
// Handle failed job
Log::error('Welcome email failed', [
'user_id' => $this->user->id,
'error' => $exception->getMessage(),
]);
}
}
// Queue workers
php artisan queue:work --sleep=3 --tries=3 --timeout=60
php artisan queue:listen --timeout=60
Development Tools
๐ Debugging Tools
// Install Laravel Debugbar
composer require barryvdh/laravel-debugbar --dev
// config/debugbar.php
'enabled' => env('DEBUGBAR_ENABLED', null),
// Add to .env
DEBUGBAR_ENABLED=true
// IDE Helper
composer require barryvdh/laravel-ide-helper --dev
// Generate helper files
php artisan ide-helper:generate
php artisan ide-helper:models
php artisan ide-helper:meta
// Telescope (for local development)
composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate
๐ Code Quality Tools
// Larastan (PHPStan for Laravel)
composer require --dev nunomaduro/larastan
// phpstan.neon
includes:
- vendor/nunomaduro/larastan/extension.neon
parameters:
paths:
- app/
level: 5
ignoreErrors:
- '#Call to an undefined method [a-zA-Z0-9\\_]+Illuminate\\Database\\Eloquent\\Builder#'
// Run analysis
./vendor/bin/phpstan analyse
// PHP CS Fixer
composer require --dev friendsofphp/php-cs-fixer
// .php-cs-fixer.php
<?php
$finder = PhpCsFixer\Finder::create()
->in(__DIR__)
->exclude(['bootstrap/cache', 'storage', 'vendor'])
->notPath('*.blade.php');
return (new PhpCsFixer\Config())
->setRules([
'@PSR2' => true,
'array_syntax' => ['syntax' => 'short'],
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'no_unused_imports' => true,
])
->setFinder($finder);
Related Notes
Quick Commands Reference
Setup Commands
# New project with Sail
curl -s https://laravel.build/myapp | bash
# Traditional setup
composer create-project laravel/laravel myapp
cd myapp && php artisan key:generate
# Database setup
php artisan migrate:refresh --seed
php artisan db:seed --class=UserSeeder
Development Commands
# Serve application
php artisan serve
./vendor/bin/sail up -d
# Asset compilation
npm run dev
npm run watch
npm run build
# Testing
php artisan test
./vendor/bin/pest
php artisan test --parallel
Maintenance Commands
# Clear caches
php artisan optimize:clear
php artisan config:clear
php artisan cache:clear
# Optimization
php artisan optimize
php artisan config:cache
php artisan route:cache
Tags
#laravel #php #setup #development #docker #testing #environment
This setup guide should be updated as Laravel versions and best practices evolve.