PHPackages                             lucinda/abstract\_mvc - 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. [API Development](/categories/api)
4. /
5. lucinda/abstract\_mvc

ActiveLibrary[API Development](/categories/api)

lucinda/abstract\_mvc
=====================

Abstract MVC API to be extended based on STDIN type (url requests, exceptions)

v3.0.13(1mo ago)01.1k↑75%15MITPHPPHP ^8.1

Since Apr 3Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/aherne/mvc)[ Packagist](https://packagist.org/packages/lucinda/abstract_mvc)[ RSS](/packages/lucinda-abstract-mvc/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (2)Versions (39)Used By (5)

Abstract MVC API
================

[](#abstract-mvc-api)

Table of contents:

- [About](#about)
- [Configuration](#configuration)
- [Binding Points](#binding-points)
- [Unit Tests](#unit-tests)
- [Reference Guide](#reference-guide)
- [Specifications](#specifications)
    - [How Is Response Format Detected](#how-is-response-format-detected)
    - [How Are View Resolvers Located](#how-are-view-resolvers-located)
    - [How Is Route Detected](#how-is-route-detected)
    - [How Are Controllers Located](#how-are-controllers-located)
    - [How Are Views Located](#how-are-views-located)

About
-----

[](#about)

This API is a **skeleton** (requires [binding](#binding-points) by developers) created to contain parts of a MVC API that do not relate to STDIN type (console, url request or exception to be handled). It serves as a foundation for:

- [STDOUT MVC API](https://github.com/aherne/php-servlets-api): where STDIN comes from URL requests
- [STDERR MVC API](https://github.com/aherne/errors-api): where STDIN comes from STDERR of url/console requests
- Console MVC API (to be done): where STDIN comes from console requests

API is fully PSR-4 compliant, only requiring PHP8.1+ interpreter and SimpleXML extension. To quickly see how it works, check:

- **[configuration](#configuration)**: setting up an XML file where this API is configured
- **[binding points](#binding-points)**: binding user-defined components defined in XML/code to API prototypes in order to gain necessary abilities
- **[reference guide](#reference-guide)**: describes all API classes, methods and fields relevant to developers
- **[unit tests](#unit-tests)**: API has 100% Unit Test coverage, using [UnitTest API](https://github.com/aherne/unit-testing) instead of PHPUnit for greater flexibility

All classes inside belong to **Lucinda\\MVC** namespace!

Configuration
-------------

[](#configuration)

To configure this API you must have a XML with following tags inside:

- **[application](#application)**: (mandatory) configures your application on a general basis
- **[resolvers](#resolvers)**: (mandatory) configures formats in which your application is able to resolve responses to
- **[routes](#routes)**: (mandatory) configures routes that bind requested resources to controllers and views

### Application

[](#application)

Maximal syntax of this tag is:

```

```

Where:

- **application**: (mandatory) holds settings to configure your application based on attributes and tag:
    - *default\_format*: (mandatory) defines default display format (extension) for your application.
         Must match a *format* attribute in **[resolvers](#resolvers)**!
    - *default\_route*: (mandatory) defines implicit route when your application is invoked with none.
         Must match a *id* attribute in **[routes](#routes)**!
    - *version*: (optional) defines your application version, to be used in versioning static resources.
    - **paths**: (optional) holds where core components used by API are located based on attributes:
        - *views*: (optional) holds folder in which user-defined views will be located (if HTML)

Tag example:

```

```

### Resolvers

[](#resolvers)

Base syntax of this tag is:

```

	...

```

Where:

- **resolvers**: (mandatory) holds settings to resolve views based on response format (extension). Holds a child for each format supported:
    - **resolver**: (mandatory) configures a format-specific view resolver based on attributes:
        - *format*: (mandatory) defines display format (extension) handled by view resolver.
            Example: "html"
        - *content\_type*: (mandatory) defines content type matching display format above.
            Example: "text/html"
        - *class*: (mandatory) name of user-defined PS-4 autoload compliant class (including namespace) that will resolve views.
            Must be a [ViewResolver](#abstract-class-viewresolver) instance!

Tag example:

```

```

### Routes

[](#routes)

Maximal syntax of this tag is:

```

    ...

```

Where:

- **routes**: (mandatory) holds routing rules for handled requests
    - **route**: (optional) holds routing rules specific to a requested URI based on attributes:
        - *id*: (mandatory) unique route identifier (eg: requested requested resource url without trailing slash)
            Example: "users/(name)"
        - *controller*: (optional) name of user-defined PS-4 autoload compliant class (including namespace) that will mitigate requests and responses based on models.
            Must be a [Runnable](#interface-runnable) instance!
        - *view*: (optional) holds user-defined template file that holds the recipe of response for request. Example: "homepage"
        - *format*: (optional) holds response format, if different from *default\_format* @ [application](#application).
            Must match a *format* attribute @ **[resolvers](#resolvers)**!

Tag example:

```

```

Binding Points
--------------

[](#binding-points)

In order to remain flexible and achieve highest performance, API takes no more assumptions than those absolutely required! It offers developers instead an ability to bind to its prototypes via XML:

XML Attribute @ TagClass PrototypeAbility Gained[controller @ route](#routes)[Runnable](#interface-runnable)MVC controller for any STDIN type[class @ resolver](#resolvers)[ViewResolver](#abstract-class-viewResolver)Resolving response in a particular format (eg: html)### Programmatic Binding

[](#programmatic-binding)

It offers developers an ability to **bind programmatically** to its prototypes via [FrontController](#initialization) constructor:

Class PrototypeAbility Gained[ErrorHandler](#interface-errorhandler)(mandatory) Handler to use if a [\\Throwable](https://www.php.net/manual/en/class.throwable.php) while API handles request into responseUnit Tests
----------

[](#unit-tests)

For tests and examples, check following files/folders in API sources:

- [test.php](https://github.com/aherne/mvc/blob/master/test.php): runs unit tests in console
- [unit-tests.xml](https://github.com/aherne/mvc/blob/master/unit-tests.xml): sets up unit tests and mocks "loggers" tag
- [tests](https://github.com/aherne/mvc/blob/master/tests): unit tests for classes from [src](https://github.com/aherne/mvc/blob/master/src) folder

Reference Guide
---------------

[](#reference-guide)

These classes are fully implemented by API:

- [Application](#class-application): reads [configuration](#configuration) XML file and encapsulates information inside
    - [Application\\Route](#class-application-route): encapsulates [route](#routes) XML tag matching *id* of request handled
    - [Application\\Format](#class-application-format): encapsulates [resolver](#resolvers) XML tag matching response *format* for request handled
- [Response](#class-response): encapsulates response to send back to caller
    - [Response\\Status](#class-response-status): encapsulates response HTTP status
    - [Response\\View](#class-response-view): encapsulates view template and data that will be bound into a response body

Following abstract classes require to be extended by developers in order to gain an ability:

- [Runnable](#interface-runnable): defines blueprint for a component whose logic can be *run*
- [ViewResolver](#abstract-class-viewresolver): encapsulates conversion of [Response\\View](#class-response-view) into a [Response](#class-response) body

### Class Application

[](#class-application)

Class [Application](https://github.com/aherne/mvc/blob/master/src/Application.php) encapsulates information detected from XML and defines following public methods relevant to developers:

MethodArgumentsReturnsDescriptiongetVersionvoidstringGets application version based on *version* attribute @ [application](#application) XML taggetTagstring $name[\\SimpleXMLElement](https://www.php.net/manual/en/class.simplexmlelement.php)Gets a pointer to a custom tag in XML rootOther public methods are relevant only to APIs built on top of this.

### Class Application Route

[](#class-application-route)

Class [Application\\Route](https://github.com/aherne/mvc/blob/master/src/Application/Route.php) encapsulates information detected from matching [route](#routes) XML tag and defines following public methods:

MethodArgumentsReturnsDescriptiongetIDvoidstringGets route unique identifier based on value of *id* XML attributegetControllervoidstringGets controller class name/path/namespace based on value of *controller* XML attributegetFormatvoidstringGets custom route-specific display format based on value of *format* XML attribute matching a *format* attribute of [resolver](#resolvers) XML taggetViewvoidstringGets view path based on value of *view* XML attribute### Class Application Format

[](#class-application-format)

Class [Application\\Format](https://github.com/aherne/mvc/blob/master/src/Application/Format.php) encapsulates information detected from matching [resolver](#resolvers) XML tag and defines following public methods:

MethodArgumentsReturnsDescriptiongetNamevoidstringGets reponse format (extension) based on value of *format* XML attributegetCharacterEncodingvoidstringGets response character encoding based on value of *charset* XML attributegetContentTypevoidstringGets response content type based on value of *content\_type* XML attributegetViewResolvervoidstringGets view resolver class based on value of *class* attributeTo better understand how views will be resolved in the end, check [How Are Views Resolved](#how-are-views-resolved) documentation below!

### Class Response

[](#class-response)

Class [Response](https://github.com/aherne/mvc/blob/master/src/Response.php) encapsulates operations to be used in generating response. It defines following public methods relevant to developers:

MethodArgumentsReturnsDescriptiongetBodyvoidstringGets response body saved by method below.setBodystring $bodyvoidSets response body.getStatusvoid[Response\\Status](#class-response-status)Gets response http status saved by method below.setStatus[Response\\HttpStatus](https://github.com/aherne/mvc/blob/master/src/Response/HttpStatus.php)voidSets response http status and splits it into id and descriptionheadersvoidarrayGets all response http headers saved by methods below.headersstring $name?stringGets value of a response http header based on its name. If not found, null is returned!headersstring $name, string $valuevoidSets value of response http header based on its name.viewvoid[Response\\View](#class-response-view)Gets a pointer to view encapsulating data based on which response body will be compiledWhen API completes handling, it will call *commit* method to send headers and response body back to caller!

### Class Response Status

[](#class-response-status)

Class [Response\\Status](https://github.com/aherne/mvc/blob/master/src/Response/Status.php) encapsulates response HTTP status and defines following public methods relevant to developers:

MethodArgumentsReturnsDescriptiongetIdvoidintGets http response status id (eg: "304")getDescriptionvoidstringGets http response status description (eg: "not modified").### Class Response View

[](#class-response-view)

Class [Response\\View](https://github.com/aherne/mvc/blob/master/src/Response/View.php) implements [\\ArrayAccess](https://www.php.net/manual/en/class.arrayaccess.php) and encapsulates template and data that will later be bound to a response body. It defines following public methods relevant to developers:

MethodArgumentsReturnsDescriptiongetFilevoidstringGets location of template file saved by method below.setFilestringintSets location of template file to be used in generating response body.getDatavoidarrayGets all data that will be bound to template when response body will be generated.By virtue of implementing [\\ArrayAccess](https://www.php.net/manual/en/class.arrayaccess.php), developers are able to work with this object as if it were an array:

```
$this->response->view()["hello"] = "world";
```

### Class Response Redirect

[](#class-response-redirect)

Class [Response\\Redirect](https://github.com/aherne/mvc/blob/master/src/Response/Redirect.php) is a [Runnable](#interface-runnable) that encapsulates http status 301/302 redirection with its options. It defines following public methods relevant to developers:

MethodArgumentsReturnsDescription\_\_constructstring $locationvoidSets location to redirect to (by default redirection will be permanent and cacheable).setPermanentbool $flagvoidSets whether redirection is permanent.setPreventCachingbool $flagvoidSets whether browsers should prevent caching redirection.run-voidPerforms redirection and exits code.Example:

```
$redirection = new Lucinda\\MVC\\Redirect("https://www.google.com");
$redirection->setPermanent(false);
$redirection->run();

```

### Interface Runnable

[](#interface-runnable)

Interface [Runnable](https://github.com/aherne/mvc/blob/master/src/Runnable.php) interface it implements, class comes with following public method:

MethodArgumentsReturnsDescriptionrunvoidExecutes component logicUsage example:

### Abstract Class ViewResolver

[](#abstract-class-viewresolver)

Abstract class [ViewResolver](https://github.com/aherne/mvc/blob/master/src/ViewResolver.php) implements [Runnable](https://github.com/aherne/mvc/blob/master/src/Runnable.php) and encapsulates conversion of [Response\\View](#class-response-view) to response body for final response format.

Developers need to implement *run* method for each resolver, where they are able to access following protected fields injected by API via constructor:

FieldTypeDescription$application[Application](#class-application)Gets application information detected from XML.$response[Response](#class-response)Gets access to object based on which response can be manipulated.Usage example:

In order to better understand how view resolvers work, check [How Are View Resolvers Located](#how-are-view-resolvers-found) section below!

Specifications
--------------

[](#specifications)

Since this API is a skeleton to build MVC APIs on top it comes with a series of specifications that may or may not be automatically implemented here:

- [How Is Response Format Detected](#how-is-response-format-detected)
- [How Are View Resolvers Located](#how-are-view-resolvers-located)
- [How Is Route Detected](#how-is-route-detected)
- [How Are Controllers Located](#how-are-controllers-located)

### How Is Response Format Detected

[](#how-is-response-format-detected)

To better understand how *default\_format* and *default\_route* attributes in **[application](#application)** XML tag play together with *format* attribute in **[routes](#routes)** tag and *format* attribute in **[resolvers](#resolvers)** tag, let's take this XML for example:

```

	...

    ...

    ...

```

There will be following situations for above:

If Route DetectedThen Format DetectedDescriptionindexhtmlBecause no specific *format* is set, value of *default\_format* is usedusershtmlBecause no specific *format* is set, value of *default\_format* is usedblogjsonBecause route detected has *format* its value is usedThis logic requires to be implemented by child APIs because the nature of resolvers differs based on STDIN type!

### How Are Views Resolvers Located

[](#how-are-views-resolvers-located)

To better understand how *default\_format* attribute in **[application](#application)** XML tag plays together with *format* and *class* attributes in **[resolvers](#resolvers)** tag, let's take this XML for example:

```

	...

...

```

In that case if "psr-4" attribute in composer.json associates "Lucinda\\Project\\" with "src/" folder then:

- file autoloaded will be src/ViewResolvers/Html.php
- class found there must:
    - be named: "Html"
    - belong to namespace: "Lucinda\\Project\\ViewResolvers"
    - extend [ViewResolver](#abstract-class-viewresolver)

This logic is entirely implemented by this API! Developers only need to plug in suitable [ViewResolver](#abstract-class-viewresolver) classes in XML.

### How Is Route Detected

[](#how-is-route-detected)

To better understand how *default\_route* attribute in **[application](#application)** XML tag plays together with *id* attribute in **[routes](#routes)** tag, let's take this XML for example:

```

	...

    ...

```

Assuming STDIN comes from HTTP requests, there will be following situations for above:

If Request IsThen Route ID DetectedDescription/indexBecause no specific page was requested, that identified by *default\_route* is used/blogblogBecause page is routed, that whose id matches request is usedThis logic requires to be implemented by child APIs since logic of request depends on STDIN type!

### How Are Controllers Located

[](#how-are-controllers-located)

To better understand how *default\_route* attribute in **[application](#application)** XML tag plays together with *id* and *controller* attributes in **[routes](#routes)** tag, let's take this XML for example:

```

	...

...

```

In that case if "psr-4" attribute in composer.json associates "Lucinda\\Project\\" with "src/" folder then:

- file autoloaded will be: "src/Controllers/Homepage.php"
- class found there must:
    - be named: "Homepage"
    - belong to namespace: "Lucinda\\Project\\Controllers"
    - extend Lucinda\*\*???\*\*\\Controller

As you can see above, controller namespace was ommitted because controller itself must be implemented by child APIs (since it depends on STDIN type).

### How Are Views Located

[](#how-are-views-located)

To better understand how *views* attribute in **[application](#application)** XML tag plays together with *id* and *view* attributes in **[routes](#routes)** tag, let's take this XML for example:

```

...

```

In that case if route "user/info" matches STDIN request then:

- file autoloaded will be: "application/views/user-info.**???**"

As you can see above, view extension was ommitted because view itself must be implemented by child APIs (since it depends on STDIN type).

###  Health Score

53

—

FairBetter than 97% of packages

Maintenance90

Actively maintained with recent releases

Popularity19

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity73

Established project with proven stability

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

Recently: every ~1 days

Total

38

Last Release

51d ago

Major Versions

v1.1.2 → v2.0.02021-12-28

v1.1.4 → v2.0.22022-03-19

v1.1.9 → v3.0.02026-03-01

PHP version history (3 changes)v1.0.0PHP ^7.1

v2.0.0PHP ^8.1

v1.1.3PHP ^7.1|^8.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/3382770?v=4)[Lucian Gabriel Popescu](/maintainers/aherne)[@aherne](https://github.com/aherne)

---

Top Contributors

[![aherne](https://avatars.githubusercontent.com/u/3382770?v=4)](https://github.com/aherne "aherne (26 commits)")

---

Tags

apimvcabstract

### Embed Badge

![Health badge](/badges/lucinda-abstract-mvc/health.svg)

```
[![Health](https://phpackages.com/badges/lucinda-abstract-mvc/health.svg)](https://phpackages.com/packages/lucinda-abstract-mvc)
```

###  Alternatives

[m165437/laravel-blueprint-docs

API Blueprint Renderer for Laravel

22779.0k](/packages/m165437-laravel-blueprint-docs)

PHPackages © 2026

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