PHPackages                             bloatless/endocore - 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. [Framework](/categories/framework)
4. /
5. bloatless/endocore

ActiveLibrary[Framework](/categories/framework)

bloatless/endocore
==================

Bloatless Endocore is a framework designed to quickly build web applications following the Action-Domain-Responder pattern.

v0.4.0(6y ago)15752MITPHPPHP ^7.2CI failing

Since Dec 16Pushed 3y ago2 watchersCompare

[ Source](https://github.com/bloatless/endocore)[ Packagist](https://packagist.org/packages/bloatless/endocore)[ Docs](https://bloatless.org)[ RSS](/packages/bloatless-endocore/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (4)Dependencies (4)Versions (8)Used By (2)

 [![](https://camo.githubusercontent.com/c32f73a2d2e53972aa4187a1ffa7e720e107f2a72a7a1f1e4e4a8737eab4338e/68747470733a2f2f626c6f61746c6573732e6f72672f696d672f6c6f676f2e737667)](https://camo.githubusercontent.com/c32f73a2d2e53972aa4187a1ffa7e720e107f2a72a7a1f1e4e4a8737eab4338e/68747470733a2f2f626c6f61746c6573732e6f72672f696d672f6c6f676f2e737667)

Bloatless Endocore
==================

[](#bloatless-endocore)

 Endocore is a framework designed to quickly build web applications following the Action-Domain-Responder pattern.

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

[](#installation)

The easiest and recommended way to start a new Endocore based application is to use the [Endocore Sample App](https://github.com/bloatless/endocore-app). This repository provides you with a boilerplate application including all necessary files and folders to start your project.

You can install the Endocore App using composer:

```
php composer.phar create-project bloatless/endocore-app my_sample_project

```

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

[](#documentation)

Additionally to this documentation you should also have a look into the Endocore App sourcecode. It contains some well documented examples.

- [Directory Structure](#directory-structure)
- [Configuration](#configuration)
- [Routing](#routing)
    - [GET Route](#get-route)
    - [POST Route](#post-route)
    - [Other route types](#other-route-types)
    - [Route parameters](#route-parameters)
- [Actions and Responder](#actions-and-responder)
    - [Actions with JSON response](#actions-with-json-response)
    - [Actions with HTML response](#actions-with-html-response)
- [Domains](#domains)
- [Error Handling and Logging](#error-handling-and-logging)
    - [Using the file logger](#using-the-file-logger)
        - [Logger configuration](#logger-configuration)
        - [Log Levels](#log-levels)
    - [Error responses](#error-responses)
    - [Throwing exceptions](#throwing-exceptions)
        - [Generic Exceptions](#generic-exceptions)
        - [HTTP Exceptions](#http-exceptions)

### Directory Structure

[](#directory-structure)

```
app/            Contains your applications basic files (actions, domains, ...)
bootstrap/      Contains the bootstrap file for your application
config/         Contains the configuration for your application
logs/           Contains log files
public/         Contains the entry script and public files of your application
routes/         Contains the routes file(s) of your application
vendor/         Contains the Endocore framework and other libraries

```

### Configuration

[](#configuration)

After installing the Endocore App you should check and adjust the `config.php` file the `config` folder. Most of the settings should be fine with their default values but if your application needs to use a MySQL database e.g. you need to add or adjust some values.

### Routing

[](#routing)

The routes of your application define which Action will be executed when a specified URL is requested. Each URL supported by your application needs to be routed to an action. You can adjust routes using the `default.php` file in the `routes` folder.

#### GET Route

[](#get-route)

```
return [
    'home' => [
        'method' => 'GET',
        'pattern' => '/about',
        'handler' => 'Bloatless\EndocoreApp\Actions\AboutAction',
    ],
];
```

This example routes the request path `/about` to the AboutAction in your applications Actions folder.

#### POST Route

[](#post-route)

```
return [
    'home' => [
        'method' => 'POST',
        'pattern' => '/customers',
        'handler' => 'Bloatless\EndocoreApp\Actions\AddCustomerAction',
    ],
];
```

This example handles a POST request to `/customers` and calls the `AddCustomerAction` in your application.

#### Other route types

[](#other-route-types)

Of course you can also define `PUT`, `DELETE` or any other valid request types in the same manner.

#### Route parameters

[](#route-parameters)

You can use placeholders within route patterns. These parameters will be passed to your action using the `$arguments`array.

```
return [
    'customer' => [
        'method' => 'GET',
        'pattern' => '/customers/{id}',
        'handler' => 'Bloatless\EndocoreApp\Actions\CustomerAction',
    ],
];
```

This route would match URLs like e.g. `/customers/123`. The CustomerAction would receive an `$arguments` array like this:

```
[
    'id' => 123
]
```

You can additionally use a regular expression pattern to define which values the placeholder accepts.

```
return [
    'customer' => [
        'method' => 'GET',
        'pattern' => '/customers/{id:[0-9]+}',
        'handler' => 'Bloatless\EndocoreApp\Actions\CustomerAction',
    ],
];
```

This route for example would match `/customers/123` but not `customers/abc`.

Segments wrapped in square brackets are considered optional like e.g.:

`pattern' => '/customers[/{id:[0-9]+]'`

### Actions and Responder

[](#actions-and-responder)

Every request the application receives will be dispatched to an action as defined in your routes. The action handles this request. Typically by requesting data from a domain using input data from the request. The data from the domain is than passed to a responder which builds the HTTP response. This response is than returned back into the application by the action.

Endocore provides responders for HTML as well as JSON content. You can use this responders by extending the appropriate actions.

#### Actions with JSON response

[](#actions-with-json-response)

```
class MyJsonAction extends JsonAction
{
    public function __invoke(array $arguments = []): Response
    {
        $data = [
            'foo' => 'Some data...',
        ];
        return $this->responder->found($data);
    }
}
```

This example shows how an Action inherits the JsonResponder from the `JsonAction` and is than able to respond json data using only methods provided by the framework.

#### Actions with HTML response

[](#actions-with-html-response)

If you want to reply with HTML content you can inherit from the `HtmlAction` and make use auf the HtmlResponder.

```
class MyHtmlAction extends HtmlAction
{
    public function __invoke(array $arguments = []): Response
    {
        $data = [
            'body' => 'Hello World!',
        ];
        return $this->responder->found($data);
    }
}
```

This example will output a simple Hello World paragraph.

### Domains

[](#domains)

Domains handle the logic of your application. Domains can be a simple class or any kind of service.

### Error Handling and Logging

[](#error-handling-and-logging)

The Endocore framework provides some basic tools to handle errors and logging.

#### Using the file logger

[](#using-the-file-logger)

From within any `Action` or `Domain` you have access to a PSR-3 compatible file logger.

```
class MyHtmlAction extends HtmlAction
{
    public function __invoke(array $arguments = []): Response
    {
        $this->logger->warning('Some error occurred');
    }
}
```

##### Logger Configuration

[](#logger-configuration)

Using you configuration file `config/config.php` you can define the target folder for your log-files as well as the min. log level:

```
'logger' => [
    'path_logs' => __DIR__ . '/../logs',
    'min_level' => 'warning',
],
```

The log files will be stored per day with a filename like `2018-12-12_endocore.log`.

##### Log levels

[](#log-levels)

A PSR-3 compatible logger can log at different levels. All events with a level lower than the min. level defined in your configuration will be dropped. The available log levels are:

```
$this->logger->debug('Some error occurred');
$this->logger->notice('Some error occurred');
$this->logger->info('Some error occurred');
$this->logger->warning('Some error occurred');
$this->logger->error('Some error occurred');
$this->logger->critial('Some error occurred');
$this->logger->alert('Some error occurred');
$this->logger->emergency('Some error occurred');
```

There is also a generic `log` method available:

```
$this->logger->log('warning', 'Some error occurred');
```

Additionally it is possible to provide some context information:

```
$this->logger->warning('Some error message', [
    'browser' => 'Firefox',
]);
```

#### Error responses

[](#error-responses)

When using a `Responder` (typically from within an `Action`) you can use various methods in case an error occurrs in your application and you need to stop the execution:

```
class MyHtmlAction extends HtmlAction
{
    public function __invoke(array $arguments = []): Response
    {
        // some error occurs...
        return $this->responder->error(['data' => 'some additional data...']);
    }
}
```

This method will automatically respond with an HTTP status code 500 and render a simple error message.

For HTTP errors there are some additional methods which will set there corresponding HTTP status codes automatically:

```
class MyHtmlAction extends HtmlAction
{
    public function __invoke(array $arguments = []): Response
    {
        return $this->responder->badRequest(); // 400
        return $this->responder->notFound(); // 404
        return $this->responder->methodNotAllowed(); // 405
    }
}
```

#### Throwing exceptions

[](#throwing-exceptions)

In case you can not use a responder you are still able to respond with an error message using exceptions. You can throw there exceptions from anywhere in your application.

##### Generic Exceptions

[](#generic-exceptions)

```
class MyDomain
{
    public function myMethod(): string
    {
        throw new EndocoreException('Something went wrong...');
    }
}
```

Throwing a `EndocoreException` will force the application to respond with an error 500 code. Also the error will be logged to your logfile.

##### HTTP Exceptions

[](#http-exceptions)

For each HTTP error supported by a `Responder` there is a corresponding Exception which you can throw anywhere in your application:

```
class MyDomain
{
    public function myMethod(): string
    {
        throw new BadRequestException(); // 400
        throw new NotFoundException(); // 404
        throw new MethodNotAllowedException(); // 405
    }
}
```

License
-------

[](#license)

MIT

###  Health Score

27

—

LowBetter than 49% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity16

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity51

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 ~280 days

Recently: every ~330 days

Total

6

Last Release

1305d ago

PHP version history (2 changes)v0.1.0PHP ^7.2

v0.5.0.x-devPHP ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/1b671374dc6bed0be4c509ea43a89583701957a7f46d7562a8122f66ac372c5b?d=identicon)[nekudo](/maintainers/nekudo)

---

Top Contributors

[![nekudo](https://avatars.githubusercontent.com/u/1132928?v=4)](https://github.com/nekudo "nekudo (132 commits)")

---

Tags

adrframeworkkisslightweightquery-builderframeworkadrbloatlessaction domain responder

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/bloatless-endocore/health.svg)

```
[![Health](https://phpackages.com/badges/bloatless-endocore/health.svg)](https://phpackages.com/packages/bloatless-endocore)
```

###  Alternatives

[hemp/presenter

Easy Model Presenters in Laravel

247592.6k1](/packages/hemp-presenter)[pestphp/pest-plugin-stressless

Stressless plugin for Pest

67792.6k16](/packages/pestphp-pest-plugin-stressless)[arbiter/arbiter

An Action system for Action-Domain-Responder.

3013.2k2](/packages/arbiter-arbiter)[wpstarter/framework

The WpStarter Framework - Laravel Framework for WordPress

1810.1k4](/packages/wpstarter-framework)

PHPackages © 2026

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