asyassin10 / valhalla-framework
Microservices-only PHP framework for lightweight API services.
Requires
- php: ^8.2
- guzzlehttp/guzzle: ^7.9
- monolog/monolog: ^3.6
Requires (Dev)
- laravel/pint: ^1.29
- phpunit/phpunit: ^11.5
README
Valhalla
Valhalla is a microservices-first PHP framework for building lightweight JSON APIs, internal service endpoints, CLI-driven workflows, local agent-style workers, optional ORM-backed applications, and container-ready services.
It is designed for teams that want a small, focused foundation instead of a full-stack monolith. Valhalla keeps the surface area intentionally compact: routing, middleware, authentication, service-to-service HTTP calls, scaffolding, agents, optional ORM drivers, and one-command container generation.
Why Valhalla
- API-first architecture with JSON responses as the default
- Lightweight core with minimal abstraction overhead
Route::facade with automatic attribute route discovery- Optional ORM support with pluggable Eloquent or Doctrine drivers
- Container scaffolding for Docker and Podman
- CLI scaffolding for projects, controllers, middleware, services, models, and migrations
- JWT and API token authentication support
- Service-to-service HTTP client with retries and circuit-breaker support
- Local TCP-based agent workflow for task-style background services
- Simple structure that is easy to read, extend, and test
Requirements
- PHP 8.2+
- Composer
Install Valhalla Globally
Install the Valhalla CLI globally with Composer:
composer global require asyassin10/valhalla-framework
Make sure Composer's global bin directory is on your PATH.
For zsh on macOS:
echo 'export PATH="$PATH:$HOME/.composer/vendor/bin:$HOME/.config/composer/vendor/bin"' >> ~/.zshrc source ~/.zshrc
Verify the installation:
valhalla
Create a New Project
Create a new service from anywhere:
valhalla new project orders-service
cd orders-service
composer install
cp .env.example .env
php -S 127.0.0.1:8080 -t public
Then open:
http://127.0.0.1:8080/health
You can also scaffold and install dependencies in one step:
valhalla new project orders-service --install
Generated projects now include:
src/Controllers,src/Middleware,src/Servicesdatabase/migrationsconfig/database.php- route, auth, logging, agents, and service config files
ORM-specific directories are created only when you install an ORM driver:
valhalla orm:install eloquentcreatessrc/Modelsvalhalla orm:install doctrinecreatessrc/Entities
Local Development In This Repository
If you are working on the framework itself:
composer install cp .env.example .env php -S 127.0.0.1:8080 -t public
Run the CLI locally from the repository root:
php bin/valhalla
Or:
./bin/valhalla
CLI Commands
Valhalla ships with a project, ORM, container, and operations CLI.
new project Create a new Valhalla API project.
make:controller Generate a controller class.
make:middleware Generate a middleware class.
make:service Generate a service helper class.
install Install Composer dependencies.
auth:generate Generate a JWT for a sample or provided user.
routes:list List registered routes from routes/api.php.
orm:install Install an ORM driver (eloquent or doctrine).
orm:remove Remove ORM configuration from the project.
migrate Run ORM migrations.
migrate:rollback Rollback the last ORM migration.
migrate:diff Generate a Doctrine migration diff.
make:model Generate an ORM model or entity.
make:migration Generate an ORM migration.
install:docker Generate a docker container setup.
install:podman Generate a podman container setup.
up Start the configured container stack.
down Stop the configured container stack.
build Build the configured container stack.
logs Tail logs from the configured container stack.
shell Open a shell in the app container.
queue:work Run the Valhalla queue worker loop.
agent:install Register a new local Valhalla agent.
agent:start Start a registered local agent in the background.
agent:stop Stop a background Valhalla agent.
agent:call Call a running local agent with a task.
agent:list List installed agents.
agent:serve Internal command used to boot an agent server process.
Common Examples
Generate a controller:
valhalla make:controller OrdersController
Generate middleware:
valhalla make:middleware InternalAuth
Generate a service helper:
valhalla make:service BillingService
List registered routes:
valhalla routes:list
Generate a JWT for testing:
valhalla auth:generate 1 "Jane Doe"
Install Eloquent ORM support:
valhalla orm:install eloquent valhalla make:model Order valhalla make:migration create_orders_table valhalla migrate
Install Doctrine ORM support:
valhalla orm:install doctrine valhalla make:model Invoice valhalla migrate:diff valhalla migrate
Generate Docker files:
valhalla install:docker valhalla build valhalla up valhalla logs valhalla shell
Generate Podman files:
valhalla install:podman valhalla build valhalla up
Routing
Valhalla is built around simple, readable route definitions.
use App\Controllers\OrdersController; use Valhalla\Framework\Core\Request; use Valhalla\Framework\Core\Response; use Valhalla\Framework\Facades\Route; Route::get('/health', fn () => Response::json([ 'ok' => true, 'service' => 'orders', ])); Route::get('/users/{id}', fn (Request $request) => Response::json([ 'id' => $request->route('id'), ])); Route::post('/orders', [OrdersController::class, 'store']);
The Route facade is the recommended style because it gives clean editor autocomplete and avoids $router variable warnings in IDEs.
Route Groups
use App\Middleware\AuthMiddleware; use Valhalla\Framework\Facades\Route; Route::group('/internal', [AuthMiddleware::class], function (): void { Route::get('/status', fn () => ['ok' => true]); });
Controller Arrays
use App\Controllers\UsersController; use Valhalla\Framework\Facades\Route; Route::get('/users', [UsersController::class, 'index']); Route::get('/users/{id}', [UsersController::class, 'show']); Route::post('/users', [UsersController::class, 'store']);
Attribute Routes
Controllers in src/Controllers can declare routes with PHP 8 attributes, and Valhalla loads them automatically when the app calls loadRoutes(...).
use Valhalla\Framework\Core\Request; use Valhalla\Framework\Core\Response; use Valhalla\Framework\Routing\Attributes\Get; use Valhalla\Framework\Routing\Attributes\Post; final class UserController { #[Get('/users')] public function index(Request $request): Response { return Response::json(['users' => []]); } #[Post('/users')] public function store(Request $request): Response { return Response::json(['created' => true]); } }
Default bootstrap stays simple:
$app->loadRoutes(dirname(__DIR__).'/routes/api.php');
If you need manual control, the low-level method still exists:
$app->loadAttributeRoutes(UserController::class);
Authentication
Valhalla supports:
- JWT bearer authentication
- Static API tokens for internal service communication
Generate a test token:
valhalla auth:generate 1 "Jane Doe"
Protect a route with middleware:
use Valhalla\Framework\Auth\Auth; use Valhalla\Framework\Core\Response; use Valhalla\Framework\Facades\Route; use Valhalla\Framework\Middleware\AuthMiddleware; Route::get('/secure', fn () => Response::json([ 'authenticated' => true, 'user' => Auth::user(), ]), [AuthMiddleware::class]);
Pluggable ORM System
Valhalla supports one optional ORM driver per project. Install either Eloquent or Doctrine, never both.
ORM Config
config/orm.php is the source of truth:
return [ 'driver' => 'eloquent', ];
or:
return [ 'driver' => 'doctrine', ];
If config/orm.php does not exist, ORM support is skipped silently during application boot.
Eloquent Driver
Install it with:
valhalla orm:install eloquent
This command:
- runs
composer require illuminate/database - creates
src/Models/ - creates
database/migrations/ - writes
config/orm.php - ensures
config/database.phpexists
Generate a model:
valhalla make:model Order
This creates a model under src/Models/ extending Illuminate\Database\Eloquent\Model with protected array $guarded = [];.
Generate a migration:
valhalla make:migration create_orders_table
Run migrations:
valhalla migrate
Rollback the last migration:
valhalla migrate:rollback
Doctrine Driver
Install it with:
valhalla orm:install doctrine
This command:
- runs
composer require doctrine/orm doctrine/migrations - creates
src/Entities/ - creates
database/migrations/ - writes
config/orm.php - ensures
config/database.phpexists
Generate an entity:
valhalla make:model Invoice
Doctrine entities are generated in src/Entities/ with mapping attributes and a getId() getter. After adding fields, generate a diff migration with:
valhalla migrate:diff
Apply migrations:
valhalla migrate
Rollback to the previous Doctrine migration:
valhalla migrate:rollback
Remove ORM config:
valhalla orm:remove
This removes config/orm.php and tells you to remove the Composer package manually.
Database Config
Valhalla reads database credentials from config/database.php and .env values such as:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=valhalla
DB_USERNAME=valhalla
DB_PASSWORD=secret
Docker And Podman Setup
Valhalla can generate a complete container setup with a single command.
Install Docker Files
valhalla install:docker
Install Podman Files
valhalla install:podman
Both commands ask for:
- PHP version:
8.2or8.3 - Database:
mysql,postgres, ornone - Database name, username, and password when a database is enabled
- Cache:
redisornone - Queue worker:
yesorno - HTTP port to expose
Generated files are placed under docker/:
docker/Dockerfiledocker/docker-compose.ymlordocker/podman-compose.ymldocker/nginx/nginx.confdocker/mysql/init.sqlwhen MySQL is selecteddocker/.dockerignore
Valhalla also writes config/container.php:
return [ 'runtime' => 'docker', ];
or:
return [ 'runtime' => 'podman', ];
Container Runtime Commands
Once a runtime is installed, use:
valhalla build valhalla up valhalla logs valhalla shell valhalla down
These commands automatically read config/container.php to choose Docker or Podman.
Queue Worker Container
If you choose a queue worker during container setup, Valhalla creates a worker service that runs:
php bin/valhalla queue:work
Service-to-Service Calls
Valhalla includes a JSON-oriented HTTP client wrapper for internal services.
use Valhalla\Framework\Services\ServiceClient; $client = new ServiceClient($app->config()); $result = $client->json( 'billing', 'POST', 'https://billing.internal/payments', ['invoice_id' => 99] );
The service client supports retry settings and circuit-breaker configuration through config/services.php.
Local Agents
Valhalla includes an MVP local agent system for task-based workers over newline-delimited JSON and TCP.
Install and start an agent:
valhalla agent:install summarizer 9501 valhalla agent:start summarizer valhalla agent:list
Call an agent:
valhalla agent:call summarizer summarize
This is useful for internal automation, background jobs, or local task-oriented services.
Project Structure
bin/ CLI entrypoint
config/ Framework and application configuration
database/ Migration files for ORM-backed apps
docs/ Documentation guides
docker/ Generated Docker or Podman files
examples/basic-service/ Sample Valhalla service
public/ HTTP entrypoint
routes/ Route definitions
src/ Framework source code and app classes
tests/ PHPUnit tests
Documentation
Detailed guides are available in the docs/ directory:
Example Service
A runnable example is included in:
examples/basic-service
This example shows the expected project structure and gives you a starting point for your own services.
Testing
Run the test suite from the repository root:
composer test
Roadmap Direction
Valhalla is a strong fit for:
- internal APIs
- microservice backends
- service orchestration layers
- agent-like local workers
- ORM-backed services with optional Eloquent or Doctrine integration
- containerized API services with Docker or Podman
