{"id":23681397,"url":"https://github.com/codecat/nin","last_synced_at":"2026-04-09T14:05:12.109Z","repository":{"id":33089816,"uuid":"36727259","full_name":"codecat/Nin","owner":"codecat","description":"Tiny PHP framework based on some of the core ideas of Yii 1 and 2. (Nin means \"No It's Not\")","archived":false,"fork":false,"pushed_at":"2024-05-10T17:03:11.000Z","size":533,"stargazers_count":10,"open_issues_count":3,"forks_count":1,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-11-17T01:46:27.027Z","etag":null,"topics":["framework","hacktoberfest","mvc","nin","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codecat.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"License","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"patreon":"openplanet"}},"created_at":"2015-06-02T11:01:38.000Z","updated_at":"2024-05-10T17:03:14.000Z","dependencies_parsed_at":"2024-05-10T18:23:57.754Z","dependency_job_id":"01452e4b-ed25-4f9a-8a13-82b1f8999964","html_url":"https://github.com/codecat/Nin","commit_stats":{"total_commits":308,"total_committers":6,"mean_commits":"51.333333333333336","dds":0.0714285714285714,"last_synced_commit":"56166bd1a55f86b5654adb9df1f3e288465f47bb"},"previous_names":[],"tags_count":41,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecat%2FNin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecat%2FNin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecat%2FNin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecat%2FNin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codecat","download_url":"https://codeload.github.com/codecat/Nin/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231774744,"owners_count":18424669,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["framework","hacktoberfest","mvc","nin","php"],"created_at":"2024-12-29T18:37:59.093Z","updated_at":"2025-10-28T01:36:05.002Z","avatar_url":"https://github.com/codecat.png","language":"PHP","funding_links":["https://patreon.com/openplanet"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/codecat/Nin/raw/master/resources/Logo.png\"\u003e\n\u003c/p\u003e\n\nNin 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\".\n\n# How does it work?\nNin is an MVC system, where `Nin\\Model` and `Nin\\Controller` are the key classes, and views are included PHP files.\n\n# Getting started\nQuickly 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:\n\n```\n$ composer require codecat/nin\n```\n\nThen create `index.php`:\n\n```php\ninclude 'vendor/autoload.php';\nnf_begin();\n```\n\n## Detailed installation\nThere 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.\n\nYou 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.\n\n# The most minimalistic example\nAfter 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`.\n\nTo 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`:\n\n```php\nclass IndexController extends \\Nin\\Controller {\n  public function actionIndex() {\n    echo 'This is the index page!';\n  }\n}\n```\n\nRouting 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.\n\nRoutes are defined using the `nf_route` function:\n\n```php\nnf_route('/', 'IndexController.Home');\nnf_route('/info', 'IndexController.Info');\nnf_route('/user/:username', 'UserController.Profile');\n```\n\nThe 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:\n\n```php\nclass UserController extends \\Nin\\Controller {\n  public function actionProfile(string $username) {\n    // Do something with $username\n  }\n}\n```\n\nNote 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.\n\nAction 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'`.\n\nParameters 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:\n\n```php\nclass UserController extends \\Nin\\Controller {\n  private $user;\n\n  public function __construct(int $id) {\n    $this-\u003euser = User::findByPk($id);\n  }\n\n  public function actionPosts() {\n    // Do something with $this-\u003euser\n  }\n}\n```\n\n# Using views\nYou can also do the following inside of a controller's action method:\n\n```php\n$this-\u003erender('foo');\n```\n\nThis 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`.\n\nYou can also pass parameters to the `render()` function, like so:\n\n```php\n$this-\u003erender('foo', [\n  'bar' =\u003e 'hello ',\n  'foobar' =\u003e 'world'\n]);\n```\n\nYour view can then use these parameters as if the keys in the array were PHP variables:\n\n```\n\u003cp\u003eThe controller says: \u003cb\u003e\u003c?= $bar . $foobar ?\u003e\u003c/b\u003e\u003c/p\u003e\n```\n\nIf 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:\n\n```html\n\u003c!doctype html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003ctitle\u003eMy website\u003c/title\u003e\n  \u003c/head\u003e\n\n  \u003cbody\u003e\n    \u003ch1\u003eMy website\u003c/h1\u003e\n    \u003cdiv class=\"content\"\u003e\n      \u003c?= $content ?\u003e\n    \u003c/div\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n# Using a database\nNin 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`:\n\n```php\nnf_begin([\n  'postgres' =\u003e [\n    'hostname' =\u003e 'localhost',\n    'password' =\u003e 'password',\n  ],\n]);\n```\n\nOnce this configuration is set, you are ready to create and use models.\n\nNote that the `postgres` key above is a shortcut for the more verbose database configuration:\n\n```php\nnf_begin([\n  'db' =\u003e [\n    'class' =\u003e 'Postgres',\n    'options' =\u003e [\n      'hostname' =\u003e 'localhost',\n      'password' =\u003e 'password',\n    ],\n  ],\n]);\n```\n\nThe more verbose configuration allows you to implement other third party database contexts and query builders if needed.\n\n# Using models\nModels are defined as classes. Static functions are used to configure how the model behaves. For example, a user model looks like this:\n\n```php\nclass User extends \\Nin\\Model {\n  public static function tablename() { return 'users'; }\n}\n```\n\nBy default, the primary key of models is defined as `ID`, but can be changed by defining a static function `primarykey`:\n\n```php\npublic static function primarykey() { return 'id'; }\n```\n\nThis tells Nin that the database table containing rows of that model is called `users`.\n\nYou can now use the new `User` class to do all kinds of operations. To create a new user:\n\n```php\n$user = new User();\n$user-\u003eUsername = 'admin';\n$user-\u003ePassword = 'hunter2';\n$user-\u003eAge = 24;\n$user-\u003esave();\n\n// Nin will automatically set the ID of the model after inserting it\necho 'New user ID: ' . $user-\u003eID;\n```\n\n(Sidenote: Make sure you strongly hash passwords in your database, the example above is only for demonstration purposes!)\n\nTo find a user by ID:\n\n```php\n$user = User::findByPk(1);\nif (!$user) {\n  die('No user found!');\n}\necho 'Hello, ' . $user-\u003eUsername;\n```\n\nTo find a user by attributes (column values):\n\n```php\n$user = User::findByAttributes([ 'Username' =\u003e 'admin' ]);\nif (!$user) {\n  die('No user found!');\n}\necho 'Hello, ' . $user-\u003eUsername;\n```\n\nYou may also use `findAll` and `findAllByAttributes` to get multiple models. They return arrays and work how you would expect:\n```php\n$users = User::findAll();\n$users = User::findAllByAttributes([ 'Age' =\u003e 24 ]);\n```\n\nYou can optionally pass options to `findAll` and `findAllByAttributes` as an array in the second parameter. The accepted keys are:\n\n* `group` Perform a group by query with its value\n* `order` The order to sort the objects in (`ASC` or `DESC`, by default this is `ASC`)\n* `orderby` Which column to sort the object by (by default this is the primary key)\n* `limit` Either an integer of how many items you want to get at most, or an array for a range of items\n\nModels can also have **relational** properties. For example, if a user can have multiple posts, you would define the `User` class like this:\n\n```php\nclass User extends \\Nin\\Model {\n  public static function tablename() { return 'users'; }\n\n  public function relations() {\n    return [\n      'posts' =\u003e [ HAS_MANY, 'Post', 'Author' ],\n    ];\n  }\n}\n```\n\nYou can then simply use `$user-\u003eposts` to get an object array of the model `Post`, using the post column `Author`. There are 3 types of relationships you can define:\n\n* `BELONGS_TO` finds one object using **their classname** and **my column**\n* `HAS_MANY` finds multiple objects using **their classname** and **their column**\n* `HAS_ONE` finds one object using **their classname** and **their column**\n\n# Middleware\nYou 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:\n\n```php\nnf_route_middleware_begin(new Nin\\Middleware\\AuthSession());\nnf_route('/posts', 'PostsController.Index');\nnf_route('/users', 'UsersController.Index');\nnf_route_middleware_end();\n```\n\nWhen 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.\n\nMiddleware 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.\n\n# Docker\nNin 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:\n\n```\nFROM codecatt/nin:2.0\nCOPY . /var/www/html\n```\n\nAnd then in your `index.php` you include Nin like this:\n\n```php\ninclude('../nin/nf.php');\n```\n\nNote that you do not need to do any manual configuration, as this is automatically handled by the Docker image.\n\nThere are several tags available:\n\n* `latest`: The latest version.\n* `2.0`: The latest 2.0.x version.\n* `1.6`: The latest 1.6.x version.\n* `1.3`: The latest 1.3.x version.\n* `1.2`: The latest 1.2.x version.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodecat%2Fnin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodecat%2Fnin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodecat%2Fnin/lists"}