Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 71 additions & 18 deletions doc/Getting-Started/Project-Structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ my-app/
├── src/
│ └── app/
│ ├── Config/
│ │ ├── version.json Application identity (code, name, version)
│ │ ├── config.json Environment-independent config
│ │ ├── config-dev.json Development config
│ │ ├── config-prod.json Production config
Expand Down Expand Up @@ -89,18 +90,46 @@ my-app/

Configuration is environment-based and uses JSON:

### `version.json` (required)

Sets your application's identity. The framework loads this automatically at startup before any other config file:

```json
{
"application": {
"code": "my-app",
"name": "My Application",
"version": "1.0.0"
}
}
```

| Field | Purpose |
|-------|---------|
| `code` | Machine identifier — used as Monolog log channel name and shared-storage path suffix |
| `name` | Human-readable application label |
| `version` | Semver version string |

Access at runtime:

```php
app()->getAppCode(); // "my-app"
app()->getAppName(); // "My Application"
app()->getAppVersion(); // "1.0.0"
```

### `config.json` (shared)
Global settings used across all environments:

```json
{
"app": {
"name": "My App",
"timezone": "UTC",
"charset": "UTF-8"
},
"cache": {
"default": "file"
"application": {
"global": {
"maintenance": false,
"message": "We are in maintenance mode, back shortly",
"timezone": "UTC"
},
"secret": "${env:APPLICATION_SECRET}"
}
}
```
Expand All @@ -110,24 +139,48 @@ Development overrides and specific config:

```json
{
"debug": true,
"logging": {
"level": "DEBUG"
"application": {
"global": {
"maintenance": false,
"message": "We are in maintenance mode, back shortly",
"timezone": "UTC"
},
"secret": "${env:APPLICATION_SECRET}"
},
"database": {
"default": "mysql",
"connections": {
"mysql": {
"host": "localhost",
"database": "myapp_dev",
"username": "${env:DB_USER}",
"password": "${env:DB_PASS}"
"logger": {
"level": "debug",
"driver": "file",
"drivers": {
"file": {
"file_path": "storage/log",
"file_format": "Y-m-d",
"line_format": "[%datetime%] [%channel%] [%level_name%] %message% %context%\n",
"line_datetime": "Y-m-d H:i:s.v e"
}
}
},
"connections": {
"mysql": {
"type": "Pdo",
"driver": "mysql",
"schema": "${env:DB_DATABASE}",
"host": "${env:DB_HOST}",
"port": "${env:DB_PORT}",
"username": "${env:DB_USERNAME}",
"password": "${env:DB_PASSWORD}",
"charset": "UTF8",
"options": {
"ATTR_PERSISTENT": false,
"ATTR_ERRMODE": "ERRMODE_EXCEPTION",
"ATTR_AUTOCOMMIT": false
}
}
}
}
```

> **Logger `line_format` and line endings:** On Linux, Docker, and Unix systems the file driver may not append a newline after each entry. Add `\n` at the end of `line_format` to ensure each log entry ends with a newline. On Windows this is not required but harmless.

### `config-prod.json`
Production settings with hardened defaults.

Expand Down
24 changes: 24 additions & 0 deletions doc/Getting-Started/Quick-Start.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,30 @@ mkdir -p src/app/Config
mkdir public
```

## Set Your Application Identity

Create `src/app/Config/version.json`:

```json
{
"application": {
"code": "my-first-app",
"name": "My First App",
"version": "0.1.0"
}
}
```

The framework loads this file automatically at startup. Access the values at runtime:

```php
app()->getAppCode(); // "my-first-app"
app()->getAppName(); // "My First App"
app()->getAppVersion(); // "0.1.0"
```

> `code` is also used as the Monolog log channel name and storage path identifier.

## Create Your First Controller

Create `src/app/Controllers/WelcomeController.php`:
Expand Down
59 changes: 40 additions & 19 deletions doc/Getting-Started/Your-First-App.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,22 @@ mkdir -p public
mkdir -p storage/logs
```

## Step 0: Set Your Application Identity

Create `src/app/Config/version.json`:

```json
{
"application": {
"code": "task-api",
"name": "Task Management API",
"version": "1.0.0"
}
}
```

The framework loads this file automatically at startup. `code` is used as the Monolog log channel name and storage path identifier. Access the values at runtime via `app()->getAppCode()`, `app()->getAppName()`, and `app()->getAppVersion()`.

## Step 1: Create Your First Controller

Create `src/app/Controllers/TaskController.php`:
Expand Down Expand Up @@ -359,33 +375,38 @@ namespace App;

## Step 5: Create Configuration

Create `src/app/Config/config.json`:
Create `src/app/Config/config-dev.json`:

```json
{
"app": {
"name": "Task API",
"version": "1.0.0",
"timezone": "UTC"
"application": {
"global": {
"maintenance": false,
"message": "We are in maintenance mode, back shortly",
"timezone": "UTC"
},
"secret": "${env:APPLICATION_SECRET}"
},
"logging": {
"default": "monolog",
"level": "INFO"
"logger": {
"level": "debug",
"driver": "file",
"drivers": {
"php": {
"line_format": "[%channel%] [%level_name%] %message% %context%\n",
"line_datetime": "Y-m-d H:i:s.v e"
},
"file": {
"file_path": "storage/log",
"file_format": "Y-m-d",
"line_format": "[%datetime%] [%channel%] [%level_name%] %message% %context%\n",
"line_datetime": "Y-m-d H:i:s.v e"
}
}
}
}
```

Create `src/app/Config/config-dev.json`:

```json
{
"debug": true,
"logging": {
"level": "DEBUG",
"path": "storage/logs/app.log"
}
}
```
> **`line_format` and line endings:** Append `\n` to `line_format` in the `file` driver to ensure each log entry ends with a newline on Linux, Docker, and Unix systems. On Windows this is not required but harmless.

## Step 6: Start the Development Server

Expand Down
36 changes: 32 additions & 4 deletions doc/User-Guide/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,32 @@

SPIN Framework uses a JSON-based configuration system that's loaded at runtime and provides easy access through helper functions.

## Application Identity (`version.json`)

Every Spin application must have `src/app/Config/version.json`. The framework loads it automatically at startup — before any `config-{env}.json` — and exposes the values through the `app()` helper:

```json
{
"application": {
"code": "my-app",
"name": "My Application",
"version": "1.0.0"
}
}
```

| Field | Purpose |
|-------|---------|
| `code` | Machine identifier — used as Monolog log channel name and shared-storage path suffix |
| `name` | Human-readable application label |
| `version` | Semver version string |

```php
app()->getAppCode(); // "my-app"
app()->getAppName(); // "My Application"
app()->getAppVersion(); // "1.0.0"
```

## Configuration Structure

SPIN applications use JSON configuration files organized by environment (e.g., `config-dev.json`, `config-prod.json`). The configuration is structured hierarchically and supports environment variables.
Expand Down Expand Up @@ -36,13 +62,13 @@ _Configuration files support `${env:<varName>}` macros for environment variables
"driver": "php",
"drivers": {
"php": {
"line_format": "[%channel%] [%level_name%] %message% %context%",
"line_format": "[%channel%] [%level_name%] %message% %context%\n",
"line_datetime": "Y-m-d H:i:s.v e"
},
"file": {
"file_path": "storage/log",
"file_format": "Y-m-d",
"line_format": "[%datetime%] [%channel%] [%level_name%] %message% %context%",
"line_format": "[%datetime%] [%channel%] [%level_name%] %message% %context%\n",
"line_datetime": "Y-m-d H:i:s.v e"
}
}
Expand Down Expand Up @@ -239,20 +265,22 @@ Missing variables with no inline default resolve to an empty string.
"driver": "php", // Driver name
"drivers": {
"php": {
"line_format": "[%channel%] [%level_name%] %message% %context%",
"line_format": "[%channel%] [%level_name%] %message% %context%\n",
"line_datetime": "Y-m-d H:i:s.v e"
},
"file": {
"file_path": "storage/log",
"file_format": "Y-m-d",
"line_format": "[%datetime%] [%channel%] [%level_name%] %message% %context%",
"line_format": "[%datetime%] [%channel%] [%level_name%] %message% %context%\n",
"line_datetime": "Y-m-d H:i:s.v e"
}
}
}
}
```

> **`line_format` and line endings:** The `\n` at the end of `line_format` ensures each log entry is terminated with a newline. On Linux, Docker, and Unix systems this is required for the file driver to produce readable log files. On Windows the newline is written automatically, but the `\n` is harmless.

### Cache Configuration

```json
Expand Down