PHPackages                             codecat/nin - 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. codecat/nin

ActiveProject[Framework](/categories/framework)

codecat/nin
===========

A minimalistic PHP framework based on some of the ideas of Yii 1 and 2.

2.1.0(3y ago)10331[2 issues](https://github.com/codecat/Nin/issues)[1 PRs](https://github.com/codecat/Nin/pulls)MITPHP

Since Jul 2Pushed 1mo ago4 watchersCompare

[ Source](https://github.com/codecat/Nin)[ Packagist](https://packagist.org/packages/codecat/nin)[ GitHub Sponsors](https://github.com/codecat)[ RSS](/packages/codecat-nin/feed)WikiDiscussions master Synced today

READMEChangelog (4)DependenciesVersions (43)Used By (0)

 [![](https://github.com/codecat/Nin/raw/master/resources/Logo.png)](https://github.com/codecat/Nin/raw/master/resources/Logo.png)

Nin is a minimalistic PHP framework originally based on some of the ideas of Yii. It stands for "No It's Not", a play on Yii's "Yes It Is".

How does it work?
=================

[](#how-does-it-work)

Nin is an MVC system, where `Nin\Model` and `Nin\Controller` are the key classes, and views are included PHP files.

Getting started
===============

[](#getting-started)

Quickly get started with Nin by installing the dependency via Composer. You can find the package [on Packagist](https://packagist.org/packages/codecat/nin). Install it by running:

```
$ composer require codecat/nin

```

Then create `index.php`:

```
include 'vendor/autoload.php';
nf_begin();
```

Detailed installation
---------------------

[](#detailed-installation)

There is also a handy Docker image you can use which has the webserver and PHP preconfigured. Scroll to the bottom of the readme to learn more.

You can also download a release from Github (or the master branch) and include Nin from somewhere else if you prefer. Depending on your webserver, you might also need to configure a rewrite rule so everything points to `index.php`. Example configurations and basic instructions for popular webservers can be found in [`server-configs`](server-configs). I personally recommend [Caddy](https://caddyserver.com/) with php-fpm, since that works very well and already has proper routing to `index.php` by default.

The most minimalistic example
=============================

[](#the-most-minimalistic-example)

After calling `nf_begin`, you automatically have 1 route: `/`. By default, it points to `IndexController.Index`. This means it will look for a class called `IndexController` and a method of that class called `actionIndex`.

To create controller classes, make a folder `controllers` in the same directory as the `index.php` is located. Inside of this folder, we can make a file `IndexController.php`:

```
class IndexController extends \Nin\Controller {
  public function actionIndex() {
    echo 'This is the index page!';
  }
}
```

Routing works as `controller.action`, where `controller` is a class name, and `action` is the action name corresponding to a method in the class prefixed with `action`. For example, `FooController.Bar` will instantiate `FooController` and call `actionBar` on it.

Routes are defined using the `nf_route` function:

```
nf_route('/', 'IndexController.Home');
nf_route('/info', 'IndexController.Info');
nf_route('/user/:username', 'UserController.Profile');
```

The last `nf_route` call in the example above has a special parameter in its path, `:username`. This will become a parameter in your action method. So in the above example, the third route would use this controller class:

```
class UserController extends \Nin\Controller {
  public function actionProfile(string $username) {
    // Do something with $username
  }
}
```

Note that you can specify a type for the method parameter as well, to automatically convert to the correct type. For example, `int $id` will ensure you're definitely getting an integer for a parameter.

Action method parameters can also be set using URL parameters fetched from `$_GET`. For example, if your route was defined as simply `/user`, then you can still set `string $username` by making the URL `?username=foo`. When `username` is not provided in the URL, Nin will throw an error about a missing required parameter. You can make the parameter optional by giving the method parameter a default value, for example: `string $username = 'admin'`.

Parameters will also be passed to the controller constructor, if it accepts parameters. They behave exactly like method parameters. For example, if you have a route `/user/:id/posts` pointing to `UserController.Posts`, you can use the following controller:

```
class UserController extends \Nin\Controller {
  private $user;

  public function __construct(int $id) {
    $this->user = User::findByPk($id);
  }

  public function actionPosts() {
    // Do something with $this->user
  }
}
```

Using views
===========

[](#using-views)

You can also do the following inside of a controller's action method:

```
$this->render('foo');
```

This will render the `foo` view, located at `views/controller/view.php`. So if the above line was in `IndexController`, the view would be located at `views/index/foo.php`.

You can also pass parameters to the `render()` function, like so:

```
$this->render('foo', [
  'bar' => 'hello ',
  'foobar' => 'world'
]);
```

Your view can then use these parameters as if the keys in the array were PHP variables:

```
The controller says:

```

If you create a layout file at `views/layout.php`, you can use that as a wrapper for your views. It will expose the `$content` variable for the rendered view. It could for example look like this:

```

    My website

    My website

```

Using a database
================

[](#using-a-database)

Nin supports PostgreSQL, MySQL, and SQLite. To begin using a database such as PostgreSQL with Nin, specify the database connection information as a parameter to `nf_begin`:

```
nf_begin([
  'postgres' => [
    'hostname' => 'localhost',
    'password' => 'password',
  ],
]);
```

Once this configuration is set, you are ready to create and use models.

Note that the `postgres` key above is a shortcut for the more verbose database configuration:

```
nf_begin([
  'db' => [
    'class' => 'Postgres',
    'options' => [
      'hostname' => 'localhost',
      'password' => 'password',
    ],
  ],
]);
```

The more verbose configuration allows you to implement other third party database contexts and query builders if needed.

Using models
============

[](#using-models)

Models are defined as classes. Static functions are used to configure how the model behaves. For example, a user model looks like this:

```
class User extends \Nin\Model {
  public static function tablename() { return 'users'; }
}
```

By default, the primary key of models is defined as `ID`, but can be changed by defining a static function `primarykey`:

```
public static function primarykey() { return 'id'; }
```

This tells Nin that the database table containing rows of that model is called `users`.

You can now use the new `User` class to do all kinds of operations. To create a new user:

```
$user = new User();
$user->Username = 'admin';
$user->Password = 'hunter2';
$user->Age = 24;
$user->save();

// Nin will automatically set the ID of the model after inserting it
echo 'New user ID: ' . $user->ID;
```

(Sidenote: Make sure you strongly hash passwords in your database, the example above is only for demonstration purposes!)

To find a user by ID:

```
$user = User::findByPk(1);
if (!$user) {
  die('No user found!');
}
echo 'Hello, ' . $user->Username;
```

To find a user by attributes (column values):

```
$user = User::findByAttributes([ 'Username' => 'admin' ]);
if (!$user) {
  die('No user found!');
}
echo 'Hello, ' . $user->Username;
```

You may also use `findAll` and `findAllByAttributes` to get multiple models. They return arrays and work how you would expect:

```
$users = User::findAll();
$users = User::findAllByAttributes([ 'Age' => 24 ]);
```

You can optionally pass options to `findAll` and `findAllByAttributes` as an array in the second parameter. The accepted keys are:

- `group` Perform a group by query with its value
- `order` The order to sort the objects in (`ASC` or `DESC`, by default this is `ASC`)
- `orderby` Which column to sort the object by (by default this is the primary key)
- `limit` Either an integer of how many items you want to get at most, or an array for a range of items

Models can also have **relational** properties. For example, if a user can have multiple posts, you would define the `User` class like this:

```
class User extends \Nin\Model {
  public static function tablename() { return 'users'; }

  public function relations() {
    return [
      'posts' => [ HAS_MANY, 'Post', 'Author' ],
    ];
  }
}
```

You can then simply use `$user->posts` to get an object array of the model `Post`, using the post column `Author`. There are 3 types of relationships you can define:

- `BELONGS_TO` finds one object using **their classname** and **my column**
- `HAS_MANY` finds multiple objects using **their classname** and **their column**
- `HAS_ONE` finds one object using **their classname** and **their column**

Middleware
==========

[](#middleware)

You can set up middleware for specific routes. To do this, use the functions `nf_route_middleware_begin` and `nf_route_middleware_end` to wrap your `nf_route` calls in. For example, to require a user to be logged in for certain routes, you can do this:

```
nf_route_middleware_begin(new Nin\Middleware\AuthSession());
nf_route('/posts', 'PostsController.Index');
nf_route('/users', 'UsersController.Index');
nf_route_middleware_end();
```

When someone navigates to `/posts` or `/users` and they are not logged in (through the user session management provided through `Nin\Nin::setuid()`), the request will stop and never make it to the controller. Additionally, by default `AuthSession` will redirect the user to `/login` as well, so the user can log in.

Middleware can be stacked by doing multiple calls to `nf_route_middleware_begin`. Note that you must also call `nf_route_middleware_end` the same amount of times, or Nin will throw errors.

Docker
======

[](#docker)

Nin is also available as [a docker image](https://hub.docker.com/r/codecatt/nin) based on `caddy:alpine`. Here's a quick example on how to use Nin in your Dockerfile:

```
FROM codecatt/nin:2.0
COPY . /var/www/html

```

And then in your `index.php` you include Nin like this:

```
include('../nin/nf.php');
```

Note that you do not need to do any manual configuration, as this is automatically handled by the Docker image.

There are several tags available:

- `latest`: The latest version.
- `2.0`: The latest 2.0.x version.
- `1.6`: The latest 1.6.x version.
- `1.3`: The latest 1.3.x version.
- `1.2`: The latest 1.2.x version.

###  Health Score

43

↑

FairBetter than 91% of packages

Maintenance55

Moderate activity, may be stable

Popularity15

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity75

Established project with proven stability

 Bus Factor1

Top contributor holds 98.4% 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 ~60 days

Recently: every ~73 days

Total

42

Last Release

1444d ago

Major Versions

1.6.0 → 2.0.02022-02-10

### Community

Maintainers

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

---

Top Contributors

[![codecat](https://avatars.githubusercontent.com/u/136534?v=4)](https://github.com/codecat "codecat (315 commits)")[![sylae](https://avatars.githubusercontent.com/u/2791628?v=4)](https://github.com/sylae "sylae (3 commits)")[![daMichl](https://avatars.githubusercontent.com/u/4919213?v=4)](https://github.com/daMichl "daMichl (2 commits)")

---

Tags

frameworkhacktoberfestmvcninphp

### Embed Badge

![Health badge](/badges/codecat-nin/health.svg)

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

###  Alternatives

[laravel/telescope

An elegant debug assistant for the Laravel framework.

5.2k65.4M157](/packages/laravel-telescope)[spiral/roadrunner

RoadRunner: High-performance PHP application server and process manager written in Go and powered with plugins

8.4k11.6M75](/packages/spiral-roadrunner)[composer/installers

A multi-framework Composer library installer

1.4k133.5M5.5k](/packages/composer-installers)[laravel/dusk

Laravel Dusk provides simple end-to-end testing and browser automation.

1.9k35.9M224](/packages/laravel-dusk)[laravel/fortify

Backend controllers and scaffolding for Laravel authentication.

1.7k38.8M191](/packages/laravel-fortify)[cakephp/chronos

A simple API extension for DateTime.

1.4k47.0M102](/packages/cakephp-chronos)

PHPackages © 2026

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