PHPackages                             responsive-sk/slim4-root - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. responsive-sk/slim4-root

ActiveLibrary[Testing &amp; Quality](/categories/testing)

responsive-sk/slim4-root
========================

Root path management with auto-discovery, base path detection and testing utilities for Slim 4 applications

1.4.1(12mo ago)0612MITPHPPHP ^7.4 || ^8.0CI failing

Since Apr 17Pushed 12mo ago1 watchersCompare

[ Source](https://github.com/responsive-sk/slim4-root)[ Packagist](https://packagist.org/packages/responsive-sk/slim4-root)[ RSS](/packages/responsive-sk-slim4-root/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (7)Versions (6)Used By (2)

Slim4 Root
==========

[](#slim4-root)

Root path management with auto-discovery and base path detection for Slim 4 applications. Say goodbye to relative paths like `__DIR__ . '/../../../config'` and hello to clean, consistent path access.

[![Latest Version on Packagist](https://camo.githubusercontent.com/975fb96f9acead70e2a7fca8a80946476fc235bc9c058dfd3bb48ad3b12291e0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f726573706f6e736976652d736b2f736c696d342d726f6f742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/responsive-sk/slim4-root)[![Software License](https://camo.githubusercontent.com/074b89bca64d3edc93a1db6c7e3b1636b874540ba91d66367c0e5e354c56d0ea/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e737667)](LICENSE.md)[![Total Downloads](https://camo.githubusercontent.com/3f57f5da8204ba2a5a44a58a6819f28b99ca9f59d244a2491983c904748a8a19/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f726573706f6e736976652d736b2f736c696d342d726f6f742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/responsive-sk/slim4-root)

New in 1.4
----------

[](#new-in-14)

- **Automatic root path discovery** for common directory structures
- **Built-in path validation** with detailed error messages
- **Cross-platform path normalization** for Windows and Unix
- **Dedicated exception handling** for path-related errors
- **Enhanced developer experience** with more intuitive API
- **No more relative paths** with `../` - everything is relative to the root
- **Base path detection** for applications running in subdirectories
- **Testing utilities** for easier test setup and execution
- **Monolog integration** for easy logging setup

Features
--------

[](#features)

- Centralized path management for Slim 4 applications
- **Auto-discovery** of common directory structures
- Support for custom directory structures
- Path **validation** and **normalization**
- Middleware for accessing paths in route handlers
- **Base path detection** for applications running in subdirectories
- **Testing utilities** for easier test setup and execution
- **Monolog integration** for easy logging setup
- PSR-11 container integration
- No dependencies (except Slim 4 and PSR Container)
- Fully tested
- Ready for PHP 7.4 and 8.0+

Requirements
------------

[](#requirements)

- PHP 7.4+ or 8.0+
- Slim 4

Installation
------------

[](#installation)

```
composer require responsive-sk/slim4-root
```

Usage
-----

[](#usage)

### Basic Usage

[](#basic-usage)

```
use Slim4\Root\Paths;

// Create a new Paths instance with auto-discovery enabled
$paths = new Paths(__DIR__);

// Get paths relative to the root
$configPath = $paths->getConfigPath();
$viewsPath = $paths->getViewsPath();
$logsPath = $paths->getLogsPath();

// Get all paths at once
$allPaths = $paths->getPaths();

// No more ../../../ paths!
// Instead of:
// require_once __DIR__ . '/../../../vendor/autoload.php';
// Use:
// require_once $paths->path('vendor/autoload.php');
```

### With Custom Paths

[](#with-custom-paths)

```
use Slim4\Root\Paths;

// Create a new Paths instance with custom paths
$paths = new Paths(
    __DIR__,
    [
        'config' => __DIR__ . '/app/config',
        'views' => __DIR__ . '/app/views',
        'logs' => __DIR__ . '/app/logs',
    ],
    true, // Enable auto-discovery (default: true)
    false // Disable path validation (default: false)
);

// Get paths
$configPath = $paths->getConfigPath(); // Returns __DIR__ . '/app/config'
$viewsPath = $paths->getViewsPath(); // Returns __DIR__ . '/app/views'
$logsPath = $paths->getLogsPath(); // Returns __DIR__ . '/app/logs'
```

### Path Auto-Discovery

[](#path-auto-discovery)

```
use Slim4\Root\PathsDiscoverer;

// Create a new PathsDiscoverer instance
$discoverer = new PathsDiscoverer();

// Discover paths
$discoveredPaths = $discoverer->discover(__DIR__);

// Use discovered paths
var_dump($discoveredPaths);
```

### Path Validation

[](#path-validation)

```
use Slim4\Root\PathsValidator;
use Slim4\Root\Exception\InvalidPathException;

// Create a new PathsValidator instance
$validator = new PathsValidator();

// Validate paths
try {
    $validator->validate([
        'config' => __DIR__ . '/config',
        'views' => __DIR__ . '/views',
    ], true); // Strict validation (throws exception if path doesn't exist)
} catch (InvalidPathException $e) {
    echo $e->getMessage();
}
```

### Path Normalization

[](#path-normalization)

```
use Slim4\Root\PathsNormalizer;

// Create a new PathsNormalizer instance
$normalizer = new PathsNormalizer();

// Normalize paths
$normalizedPath = $normalizer->normalize('C:\\path\\to\\project\\');
// Returns: 'C:/path/to/project'
```

### With DI Container

[](#with-di-container)

```
use Slim4\Root\PathsProvider;
use DI\ContainerBuilder;

// Create container
$containerBuilder = new ContainerBuilder();

// Register paths services
$rootPath = dirname(__DIR__);
PathsProvider::register(
    $containerBuilder->build(),
    $rootPath,
    [], // Custom paths
    true, // Enable auto-discovery
    false // Disable path validation
);

// Get paths from the container
$paths = $container->get(Slim4\Root\PathsInterface::class);
```

### With Paths Middleware

[](#with-paths-middleware)

```
use Slim4\Root\PathsMiddleware;
use Slim\Factory\AppFactory;

// Create app
$app = AppFactory::createFromContainer($container);

// Add the middleware to the app
$app->add($container->get(PathsMiddleware::class));

// Access paths in a route handler
$app->get('/', function ($request, $response) {
    $paths = $request->getAttribute('paths');
    $configPath = $paths->getConfigPath();

    // ...

    return $response;
});
```

### With Base Path Detection

[](#with-base-path-detection)

```
use Slim4\Root\BasePathMiddleware;
use Slim\Factory\AppFactory;

// Create app
$app = AppFactory::createFromContainer($container);

// Add the middleware to detect and set the base path
$app->add(new BasePathMiddleware($app));

// Now all routes will work correctly even if your app is in a subdirectory
$app->get('/', HomeAction::class);
```

### Integration with Twig

[](#integration-with-twig)

```
use Slim\Views\Twig;
use Slim4\Root\PathsInterface;

// Register Twig with the container
$container->set(Twig::class, function (ContainerInterface $container) {
    $paths = $container->get(PathsInterface::class);

    $twig = Twig::create($paths->getViewsPath(), [
        'cache' => $paths->getCachePath() . '/twig',
        'debug' => true,
        'auto_reload' => true,
    ]);

    return $twig;
});
```

### Integration with Monolog

[](#integration-with-monolog)

```
use Monolog\Level;
use Slim4\Root\Integration\MonologFactory;
use Slim4\Root\PathsInterface;
use Psr\Log\LoggerInterface;

// Register Logger with the container
$container->set(LoggerInterface::class, function (ContainerInterface $container) {
    $paths = $container->get(PathsInterface::class);
    $factory = new MonologFactory($paths);

    return $factory->createLogger([
        'name' => 'app',
        'path' => 'app.log',
        'level' => Level::Debug,
        'rotating' => true,
        'max_files' => 7,
    ]);
});
```

Or use the `MonologProvider` for easier setup:

```
use Monolog\Level;
use Slim4\Root\Integration\MonologProvider;

// Register a single logger
MonologProvider::register($container, [
    'name' => 'app',
    'path' => 'app.log',
    'level' => Level::Debug,
]);

// Register multiple loggers
MonologProvider::registerMultiple($container, [
    'default' => [
        'path' => 'app.log',
        'level' => Level::Debug,
    ],
    'error' => [
        'path' => 'error.log',
        'level' => Level::Error,
    ],
]);

// Use loggers
$logger = $container->get(LoggerInterface::class); // Default logger
$errorLogger = $container->get('logger.error');
```

For more details, see [Monolog Integration](docs/MONOLOG.en.md).

### Testing Utilities

[](#testing-utilities)

The package includes a `Testing` module that provides utilities for easier test setup and execution.

#### TestContainer

[](#testcontainer)

`TestContainer` is a simple static container for sharing objects between tests without using globals.

```
use Slim4\Root\Testing\TestContainer;
use Slim4\Root\Paths;

// In your bootstrap file
$paths = new Paths(__DIR__);
TestContainer::set(Paths::class, $paths);

// In your tests
$paths = TestContainer::get(Paths::class);
```

#### Bootstrap File

[](#bootstrap-file)

The package includes a bootstrap file that you can use in your PHPUnit configuration:

```
// tests/bootstrap.php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/../vendor/responsive-sk/slim4-root/src/Testing/bootstrap.php';
```

Or you can create your own bootstrap file:

```
// tests/bootstrap.php
require_once __DIR__ . '/../vendor/autoload.php';

use Slim4\Root\Paths;
use Slim4\Root\Testing\TestContainer;

// Create Paths object
$rootPath = (string)realpath(__DIR__ . '/..');
$paths = new Paths($rootPath);

// Store in TestContainer
TestContainer::set(Paths::class, $paths);
```

Available Methods
-----------------

[](#available-methods)

### PathsInterface

[](#pathsinterface)

- `getRootPath()` - Get the root path of the project
- `getConfigPath()` - Get the config path
- `getResourcesPath()` - Get the resources path
- `getViewsPath()` - Get the views path
- `getAssetsPath()` - Get the assets path
- `getCachePath()` - Get the cache path
- `getLogsPath()` - Get the logs path
- `getPublicPath()` - Get the public path
- `getDatabasePath()` - Get the database path
- `getMigrationsPath()` - Get the migrations path
- `getStoragePath()` - Get the storage path
- `getTestsPath()` - Get the tests path
- `path(string $path)` - Get a path relative to the root path
- `getPaths()` - Get all paths as an associative array

### BasePathMiddleware

[](#basepathmiddleware)

- `process(ServerRequestInterface $request, RequestHandlerInterface $handler)` - Process the request and set the base path for the Slim application

### PathsDiscoverer

[](#pathsdiscoverer)

- `discover(string $rootPath)` - Discover paths in the given root path

### PathsValidator

[](#pathsvalidator)

- `validate(array $paths, bool $strict)` - Validate paths

### PathsNormalizer

[](#pathsnormalizer)

- `normalize(string $path)` - Normalize path

### TestContainer

[](#testcontainer-1)

- `set(string $key, mixed $value)` - Set an item in the container
- `get(string $key, mixed $default = null)` - Get an item from the container
- `has(string $key)` - Check if an item exists in the container
- `remove(string $key)` - Remove an item from the container
- `clear()` - Clear all items from the container

### MonologFactory

[](#monologfactory)

- `createLogger(array $config = [])` - Create a new Monolog logger instance
- `createConsoleLogger(string $name, Level $level)` - Create a console logger
- `createFileLogger(string $name, string $path, Level $level)` - Create a file logger
- `createRotatingLogger(string $name, string $path, int $maxFiles, Level $level)` - Create a rotating file logger

### MonologProvider

[](#monologprovider)

- `register(ContainerInterface $container, array $config)` - Register a logger in the container
- `registerMultiple(ContainerInterface $container, array $loggers)` - Register multiple loggers
- `registerConsoleLogger(ContainerInterface $container, string $name, Level $level)` - Register a console logger
- `registerFileLogger(ContainerInterface $container, string $name, string $path, Level $level)` - Register a file logger
- `registerRotatingLogger(ContainerInterface $container, string $name, string $path, int $maxFiles, Level $level)` - Register a rotating file logger

Customizing Paths
-----------------

[](#customizing-paths)

You can customize the paths by passing an array of custom paths to the constructor:

```
$paths = new Paths(
    __DIR__,
    [
        'config' => __DIR__ . '/app/config',
        'views' => __DIR__ . '/app/views',
        'logs' => __DIR__ . '/app/logs',
        'cache' => __DIR__ . '/app/cache',
        'public' => __DIR__ . '/public',
        'database' => __DIR__ . '/app/database',
        'migrations' => __DIR__ . '/app/database/migrations',
        'storage' => __DIR__ . '/app/storage',
        'tests' => __DIR__ . '/tests',
    ],
    true, // Enable auto-discovery
    false // Disable path validation
);
```

Feature Comparison
------------------

[](#feature-comparison)

Featurev1.1v1.2v1.3v1.4Auto-discovery❌ No✅ Yes✅ Yes✅ YesPath validation❌ Basic✅ Comprehensive✅ Comprehensive✅ ComprehensivePath normalization❌ No✅ Yes✅ Yes✅ YesError handling❌ Generic exceptions✅ Dedicated exceptions✅ Dedicated exceptions✅ Dedicated exceptionsRelative paths❌ Manual `../`✅ Everything relative to root✅ Everything relative to root✅ Everything relative to rootBase path detection❌ No✅ Yes✅ Yes✅ YesTesting utilities❌ No❌ No✅ Basic✅ EnhancedMonolog integration❌ No❌ No❌ No✅ YesTest coverage✅ Good✅ Excellent✅ Excellent✅ ExcellentFlexibility✅ Good✅ Excellent✅ Excellent✅ ExcellentAuto-Discovery
--------------

[](#auto-discovery)

The `Paths` class can automatically discover common directory structures in your project. This is enabled by default, but you can disable it by passing `false` as the third parameter to the constructor.

```
// With auto-discovery (default)
$paths = new Paths(__DIR__);

// Without auto-discovery
$paths = new Paths(__DIR__, [], false);
```

The auto-discovery process looks for the following directories:

- `config` - Looks for `config`, `app/config`, `etc`
- `resources` - Looks for `resources`, `app/resources`, `res`
- `views` - Looks for `resources/views`, `templates`, `views`, `app/views`
- `assets` - Looks for `resources/assets`, `assets`, `public/assets`
- `cache` - Looks for `var/cache`, `cache`, `tmp/cache`, `storage/cache`
- `logs` - Looks for `var/logs`, `logs`, `log`, `storage/logs`
- `public` - Looks for `public`, `web`, `www`, `htdocs`
- `database` - Looks for `database`, `db`, `storage/database`
- `migrations` - Looks for `database/migrations`, `migrations`, `db/migrations`
- `storage` - Looks for `storage`, `var`, `data`
- `tests` - Looks for `tests`, `test`

Path Validation
---------------

[](#path-validation-1)

The `Paths` class can validate that all paths exist. This is disabled by default, but you can enable it by passing `true` as the fourth parameter to the constructor.

```
// Without validation (default)
$paths = new Paths(__DIR__);

// With validation
$paths = new Paths(__DIR__, [], true, true);
```

If validation is enabled and a path doesn't exist, an `InvalidPathException` will be thrown:

```
try {
    $paths = new Paths(__DIR__, [], true, true);
} catch (\Slim4\Path\Exception\InvalidPathException $e) {
    echo $e->getMessage(); // "Configured path for 'views' is not a valid directory: /path/to/views"
}
```

Testing
-------

[](#testing)

```
composer test
```

Documentation
-------------

[](#documentation)

For detailed documentation, see:

- [Documentation (English)](docs/DOCUMENTATION.en.md)
- [Dokumentácia (Slovenčina)](docs/DOCUMENTATION.md)

### Examples

[](#examples)

- [Simple Example](docs/SIMPLE-EXAMPLE.en.md) - Basic usage in a typical Slim 4 project
- [Template Engines Integration](docs/TEMPLATE-ENGINES.en.md) - Integration with popular PHP template engines
- [Advanced Use Cases](docs/USE-CASES.en.md) - Detailed use cases for various scenarios and architectures
- [Testing](docs/TESTING.en.md) - Testing utilities and integration with PHPUnit
- [Monolog Integration](docs/MONOLOG.en.md) - Integration with Monolog for logging

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

Credits
-------

[](#credits)

- [Responsive.sk Team](https://responsive.sk)
- [All Contributors](../../contributors)

About Responsive.sk
-------------------

[](#about-responsivesk)

Responsive.sk is a web development company specializing in creating modern, responsive web applications using the latest technologies and best practices.

Roadmap
-------

[](#roadmap)

We're planning to expand this package with integrations for other frameworks and libraries. Check out our [TODO list](docs/TODO-COMMUNITY.md) for upcoming features and ways to contribute.

Community
---------

[](#community)

We're looking to collaborate with Laminas and Cycle ORM communities to create integrations for these frameworks. If you're interested in contributing, please check out our [TODO list](docs/TODO-COMMUNITY.md) and get in touch!

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance50

Moderate activity, may be stable

Popularity8

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~7 days

Total

5

Last Release

364d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/a9ca94d5516a8f930325df47de8418a33caf484280105d108a693533c73d4699?d=identicon)[evan70](/maintainers/evan70)

---

Top Contributors

[![evan70](https://avatars.githubusercontent.com/u/67433?v=4)](https://github.com/evan70 "evan70 (5 commits)")

---

Tags

testingphpunitfilesystemslimpathbasepathslim4rootauto-discoverypath-validationpath-normalization

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/responsive-sk-slim4-root/health.svg)

```
[![Health](https://phpackages.com/badges/responsive-sk-slim4-root/health.svg)](https://phpackages.com/packages/responsive-sk-slim4-root)
```

###  Alternatives

[phpunit/phpunit

The PHP Unit Testing framework.

20.0k910.7M134.8k](/packages/phpunit-phpunit)[behat/behat

Scenario-oriented BDD framework for PHP

4.0k96.8M2.0k](/packages/behat-behat)[brianium/paratest

Parallel testing for PHP

2.5k118.8M754](/packages/brianium-paratest)[spatie/phpunit-snapshot-assertions

Snapshot testing with PHPUnit

69417.9M510](/packages/spatie-phpunit-snapshot-assertions)[dg/bypass-finals

Removes final keyword from source code on-the-fly and allows mocking of final methods and classes

56426.3M456](/packages/dg-bypass-finals)[nette/tester

Nette Tester: enjoyable unit testing in PHP with code coverage reporter. 🍏🍏🍎🍏

4917.3M1.5k](/packages/nette-tester)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
