Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
c19571c
chore: PHP 8.4 autofixes (nullsafe logger, container share API, path …
ksandell Aug 19, 2025
853c5cd
test: skip Redis tests when Redis is not available; stabilize CI acro…
ksandell Aug 19, 2025
51a2fdb
docs: remove duplicate docblocks; standardize @inheritDoc and method …
ksandell Aug 20, 2025
ad9f15f
docblock additions/corrections
ksandell Aug 20, 2025
1fa2530
Merge remote-tracking branch 'origin/develop' into cursor-autofixes
supercid Aug 21, 2025
a1d7201
Revert Container addShared usage and harden cache manager types
supercid Aug 21, 2025
fb5f888
docblock additions/corrections
ksandell Aug 21, 2025
bb41910
Add type declarations to all class properties and improve docblocks
ksandell Aug 22, 2025
d7cf348
Update documentation to reflect actual SPIN Framework usage patterns
ksandell Aug 22, 2025
99ae728
Documentation
ksandell Aug 22, 2025
58ba911
Update README to reflect actual SPIN Framework structure
ksandell Aug 22, 2025
1af8f2c
Fix helper functions and add comprehensive tests
ksandell Aug 22, 2025
a543d68
Fix test configuration and cache loading issues
ksandell Aug 22, 2025
083dfa2
Fix type compatibility issues in redirect() and response() functions
ksandell Aug 23, 2025
5d7f0f4
docblocks in Application and ApplicationInterface synced
ksandell Nov 1, 2025
c7b6c0c
hook related things removed + composer autoload optimization
ksandell Nov 11, 2025
4bcbc7d
support env macro replacement in config values
ksandell Nov 11, 2025
5ec0916
Config to actually use the replace env macro code + changelog
ksandell Nov 11, 2025
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
7 changes: 6 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
# Changelog
SPIN Framework Changelog

## 0.0.35
- Unittests updated to support PHP 8.4 and PHPUnit 12
- Docblocks refactores in many places
- Config

## 0.0.34
- Bugfix on PDO not correctly parsing default options
- Add Redit and cache adapters unit tests with CI sidecar container
Expand All @@ -18,7 +23,7 @@ SPIN Framework Changelog
- Fix MySQL PDO driver compatibility (Removal of overridden connect base method)

## 0.0.30
- Remove deprecated error constant E_STRICT usage
- Remove deprecated error constant E_STRICT usage
- Remove AbstractBaseDaos

## 0.0.29
Expand Down
6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "A super lightweight PHP UI/REST Framework",
"version": "0.0.34",
"keywords": [
"php7",
"php8",
"php-framework",
"framework",
"api",
Expand Down Expand Up @@ -61,5 +61,9 @@
},
"require-dev": {
"phpunit/phpunit": "^10.5 || ^11.0 || ^12.0"
},
"config": {
"optimize-autoloader": true
}
}

349 changes: 349 additions & 0 deletions doc/Configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,349 @@
# Configuration

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

## 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.

### Basic Configuration File Structure

```json
{
"application": {
"global": {
"maintenance": false,
"message": "We are in maintenance mode, back shortly",
"timezone": "Europe/Stockholm"
},
"secret": "${application-secret}"
},
"session": {
"cookie": "SID",
"timeout": 3600,
"refresh": 600,
"driver": "apcu",
"apcu": {
"option": "value"
}
},
"logger": {
"level": "notice",
"driver": "php",
"drivers": {
"php": {
"line_format": "[%channel%] [%level_name%] %message% %context%",
"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_datetime": "Y-m-d H:i:s.v e"
}
}
},
"templates": {
"extension": "html",
"errors": "/Views/Errors",
"pages": "/Views/Pages"
},
"caches": {
"local.apcu": {
"adapter": "APCu",
"class": "\\Spin\\Cache\\Adapters\\Apcu",
"options": {}
},
"remote.redis": {
"adapter": "Redis",
"class": "\\Spin\\Cache\\Adapters\\Redis",
"options": {
"host": "172.20.0.1",
"port": 6379
}
}
},
"factories": {
"http": {
"serverRequest": {
"class": "\\Spin\\Factories\\Http\\ServerRequestFactory",
"options": {}
},
"request": {
"class": "\\Spin\\Factories\\Http\\RequestFactory",
"options": {}
},
"response": {
"class": "\\Spin\\Factories\\Http\\ResponseFactory",
"options": {}
},
"stream": {
"class": "\\Spin\\Factories\\Http\\StreamFactory",
"options": {}
},
"uploadedFile": {
"class": "\\Spin\\Factories\\Http\\UploadedFileFactory",
"options": {}
},
"uri": {
"class": "\\Spin\\Factories\\Http\\UriFactory",
"options": {}
}
},
"container": {
"class": "\\Spin\\Factories\\ContainerFactory",
"options": {
"autowire": true
}
},
"event": {
"class": "\\Spin\\Factories\\EventFactory",
"options": {}
}
},
"hooks": [
{
"OnBeforeRequest": [
"\\App\\Hooks\\OnBeforeRequest"
],
"OnAfterRequest": [
"\\App\\Hooks\\OnAfterRequest"
]
}
],
"connections": {
"example_mysql": {
"type": "Pdo",
"driver": "mysql",
"schema": "<db_schema_name>",
"host": "localhost",
"port": 3306,
"username": "root",
"password": "*****",
"charset": "UTF8",
"options": [
{
"ATTR_PERSISTENT": true
},
{
"ATTR_ERRMODE": "ERRMODE_EXCEPTION"
},
{
"ATTR_AUTOCOMMIT": false
}
]
}
}
}
```

## Accessing Configuration

SPIN provides a `config()` helper function to access configuration values using dot notation:

```php
// Access nested configuration values
$maintenance = config('application.global.maintenance');
$timezone = config('application.global.timezone');
$sessionTimeout = config('session.timeout');

// Access with default values
$logLevel = config('logger.level', 'info');
$dbHost = config('connections.example_mysql.host', 'localhost');
```

## Environment Variables

SPIN supports environment variables in configuration using `${VARIABLE_NAME}` syntax:

```json
{
"application": {
"secret": "${APPLICATION_SECRET}",
"database": {
"password": "${DB_PASSWORD}"
}
}
}
```

## Configuration Sections

### Application Configuration

```json
{
"application": {
"global": {
"maintenance": false,
"message": "We are in maintenance mode, back shortly",
"timezone": "Europe/Stockholm"
},
"secret": "${application-secret}"
}
}
```

### Session Configuration

```json
{
"session": {
"cookie": "SID",
"timeout": 3600,
"refresh": 600,
"driver": "apcu",
"apcu": {
"option": "value"
}
}
}
```

### Logger Configuration

```json
{
"logger": {
"level": "notice",
"driver": "php",
"drivers": {
"php": {
"line_format": "[%channel%] [%level_name%] %message% %context%",
"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_datetime": "Y-m-d H:i:s.v e"
}
}
}
}
```

### Cache Configuration

```json
{
"caches": {
"local.apcu": {
"adapter": "APCu",
"class": "\\Spin\\Cache\\Adapters\\Apcu",
"options": {}
},
"remote.redis": {
"adapter": "Redis",
"class": "\\Spin\\Cache\\Adapters\\Redis",
"options": {
"host": "172.20.0.1",
"port": 6379
}
}
}
}
```

### Database Connections

```json
{
"connections": {
"example_mysql": {
"type": "Pdo",
"driver": "mysql",
"schema": "<db_schema_name>",
"host": "localhost",
"port": 3306,
"username": "root",
"password": "*****",
"charset": "UTF8",
"options": [
{
"ATTR_PERSISTENT": true
},
{
"ATTR_ERRMODE": "ERRMODE_EXCEPTION"
},
{
"ATTR_AUTOCOMMIT": false
}
]
},
"example_sqlite": {
"type": "Pdo",
"driver": "SqlLite",
"filename": "storage\\database\\db.sqlite"
}
}
}
```

### Factory Configuration

```json
{
"factories": {
"http": {
"serverRequest": {
"class": "\\Spin\\Factories\\Http\\ServerRequestFactory",
"options": {}
},
"response": {
"class": "\\Spin\\Factories\\Http\\ResponseFactory",
"options": {}
}
},
"container": {
"class": "\\Spin\\Factories\\ContainerFactory",
"options": {
"autowire": true
}
}
}
}
```

### Hooks Configuration

```json
{
"hooks": [
{
"OnBeforeRequest": [
"\\App\\Hooks\\OnBeforeRequest"
],
"OnAfterRequest": [
"\\App\\Hooks\\OnAfterRequest"
]
}
]
}
```

## Configuration Best Practices

1. **Environment Separation**: Use different configuration files for different environments (dev, staging, prod)
2. **Sensitive Data**: Store sensitive information like passwords and secrets in environment variables
3. **Validation**: Validate configuration values at startup
4. **Defaults**: Provide sensible default values for optional configuration
5. **Documentation**: Document all configuration options and their expected values

## Configuration Validation

SPIN automatically validates configuration when the application starts. Missing required configuration will cause the application to fail to start.

## Dynamic Configuration

While SPIN primarily uses static JSON configuration, you can also set configuration values programmatically:

```php
// Set configuration values at runtime
config('application.global.maintenance', true);
config('session.timeout', 7200);
```

## Configuration Caching

SPIN caches configuration in memory for performance. Changes to configuration files require an application restart to take effect.
Loading