PHPackages                             hashbang/joyst - 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. [Database &amp; ORM](/categories/database)
4. /
5. hashbang/joyst

ActiveLibrary[Database &amp; ORM](/categories/database)

hashbang/joyst
==============

CodeIgniter extension providing automated model functionality based on a DB schema

v0.3.2(11y ago)034GPL-2.0PHPPHP &gt;=5.3.0

Since Apr 10Pushed 11y ago1 watchersCompare

[ Source](https://github.com/hash-bang/Joyst)[ Packagist](https://packagist.org/packages/hashbang/joyst)[ Docs](https://github.com/hash-bang/Joyst)[ RSS](/packages/hashbang-joyst/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (7)DependenciesVersions (8)Used By (0)

Joyst
=====

[](#joyst)

Joyst is a CodeIgniter extension providing automated model functionality based on a DB schema.

Joyst has the following aims:

1. To automate the tedious specification for models in CodeIgniter - its does this by automatically providing common functionality like `get()`, `getAll()`, `getById()` etc.
2. To automate the acccess to the data layer for simple tasks ([CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete)) from the front end to the backend.

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

[](#installation)

Install is via Composer with:

```
composer require hashbang/joyst

```

Common errors:

- `Fatal error: Class 'Joyst_Controller' not found` - Joyst needs to be loaded very early in the CI load order. Add a call to `require('vendor/autoload.php');` in `application/config/config.php` rather than the auto load file.

Use within CodeIgniter
======================

[](#use-within-codeigniter)

Simple example
--------------

[](#simple-example)

Below is an example CodeIgniter model using Joyst which provides user model functionality. The only essencial part of the below is the class extending `Joyst_Model` and having a function called `DefineSchema()` (any caps).

```
class User extends Joyst_Model {

	function DefineSchema() {
		$this->On('getall', function(&$where) {
			if (!isset($where['status'])) // If not specified imply only active users
				$where['status'] = 'active';
		});
		$this->On('create', function(&$row) {
			$row['created'] = time(); // Set the row creation time when creating
			if (isset($row['email']) && empty($row['username'])) // If no username specified make the username the email
				$row['username'] = $row['email'];
			if (isset($row['password'])) { // If setting a password hash it
				$row['passhash'] = $this->HashSet($row['password']);
				unset($row['password']); // Remove it from the output since we are storing it in another field
			}
		});
		$this->On('save', function($id, &$row) {
			$row['edited'] = time(); // Save the time we edited the record
			if (isset($_SESSION['user']) && $_SESSION['user']['userid'] == $userid) // Changing ourself?
				$_SESSION['user'] = array_merge($_SESSION['user'], $this->Get($userid, TRUE)); // Update $_SESSION['user'] to reflect the new data
		});

		return array( // Specify the table schema
			'_model' => 'User',
			'_table' => 'users',
			'_id' => 'userid',
			'userid' => array(
				'type' => 'pk',
				'readonly' => true,
			),
			'username' => array(
				'type' => 'varchar',
				'length' => 50,
			),
			'fname' => array(
				'type' => 'varchar',
				'length' => 50,
			),
			'lname' => array(
				'type' => 'varchar',
				'length' => 50,
			),
			'passhash' => array(
				'type' => 'char',
				'length' => 40,
			),
			'email' => array(
				'type' => 'email',
			),
			'role' => array(
				'type' => 'enum',
				'options' => array(
					'user' => 'Regular user',
					'admin' => 'Administrator',
					'root' => 'Root user'
				),
				'default' => 'user',
			),
			'created' => array(
				'type' => 'epoc',
				'readonly' => true,
			),
			'edited' => array(
				'type' => 'epoc',
				'readonly' => true,
			),
			'lastlogin' => array(
				'type' => 'epoc',
				'readonly' => true,
			),
			'status' => array(
				'type' => 'enum',
				'options' => array('active', 'deleted'),
				'default' => 'active',
			),
		);
	}
}

```

More complex example
--------------------

[](#more-complex-example)

The below example model provides generic device functionality.

```
class Device extends Joyst_Model {

	function DefineSchema() {
		$this->On('getall', function(&$where) {
			if (!isset($where['status'])) // If not specified imply only active items
				$where['status'] = 'active';
		});
		$this->On('create', function(&$row) {
			$row['created'] = time();
			$row['creatorid'] = $_SESSION['user']['userid']; // Set the creator to the current user
		});
		$this->On('save', function($id, &$row) {
			$row['edited'] = time();
			if (isset($row['starred'])) // If we're being passed the meta field 'starred' call our defined function SetStar()
				$this->SetStar($id, $row['starred']);
		});
		$this->on('row', function(&$row) {
			$row['starred'] = $this->IsStarred($row['deviceid']); // Append the meta field 'starred' to the output of each row

			$row['isActive'] = $this->IsActive($row); // Append the meta field 'isActive' to the output of each row
		});
		$this->on('getall', function(&$where) {
			$this->db->select('devices.*');

			// Example of a meta field 'tagid' inserting an automatic join to filter by
			if (isset($where['tagid'])) {
				$this->db->join('tags2devices', 'tags2devices.deviceid = devices.deviceid');
				$this->db->where('tags2devices.tagid', $where['tagid']);
				unset($where['tagid']);
			}

			// Example of another join if the meta field 'starred' is specified in the where condition
			if (isset($where['starred'])) {
				$this->db->join('user2device', 'user2device.deviceid = devices.deviceid');
				$this->db->where('user2device.userid', $this->User->GetActive('userid'));
				unset($where['starred']);
			}

			$this->db->join('dcus', 'dcus.dcuid = devices.dcuid');
			$this->db->where('dcus.locationid', $this->User->GetActive('locationid'));
		});
		$this->on('created', function($deviceid, $row) {
			// Log that we created the item
			$this->Log->Add('device', "Device #$deviceid created", null, array('deviceid' => $deviceid));
		});

		return array(
			'_model' => 'Device',
			'_table' => 'devices',
			'_id' => 'deviceid',
			'deviceid' => array(
				'type' => 'pk',
				'readonly' => true,
			),
			'dcuid' => array(
				'type' => 'fk',
			),
			'ref' => array(
				'type' => 'varchar',
				'length' => 50,
			),
			'name' => array(
				'type' => 'varchar',
				'length' => 100,
			),
			'description' => array(
				'type' => 'varchar',
				'length' => 255,
			),
			'type' => array(
				'type' => 'enum',
				'options' => array(
					'unknown' => 'Unknown',
					'ac' => 'Air Conditioner',
					'light' => 'Light',
					'hotwater' => 'Hot Water',
					'meter' => 'Meter',
				),
				'default' => 'unknown',
			),
			'spec' => array(
				'type' => 'json',
			),
			'created' => array(
				'type' => 'epoc',
				'readonly' => true,
			),
			'creatorid' => array(
				'type' => 'int',
				'readonly' => true,
			),
			'edited' => array(
				'type' => 'int',
				'readonly' => true,
			),
			'status' => array(
				'type' => 'enum',
				'options' => array('active', 'deleted'),
				'default' => 'active',
			),
		);
	}
}

```

Useful snippets
===============

[](#useful-snippets)

Sort the return of a GetAll() call
----------------------------------

[](#sort-the-return-of-a-getall-call)

Sometimes the built-in OrderBy functionality is too limited and you may need to rearrange the return results in the PHP HLL rather than at the database.

The following example hooks itself onto the `GetAll()` return and applies a [Natural Sorting algorithm](http://au2.php.net/manual/en/function.strnatcmp.php) so things get sorted properly when they contain numbers (e.g. '1', '2', '10', '11' gets sorted correctly).

```
$this->on('rows', function(&$rows) {
	return usort($rows, function($a, $b) {
		return strnatcmp($a['name'], $b['name']); // Sort by the name field using a natural string sort
	});
});

```

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity7

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity53

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

Total

7

Last Release

4233d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/8587289?v=4)[hashbang](/maintainers/hashbang)[@hashbang](https://github.com/hashbang)

---

Top Contributors

[![hash-bang](https://avatars.githubusercontent.com/u/624527?v=4)](https://github.com/hash-bang "hash-bang (82 commits)")

---

Tags

schemadatabasecodeignitermodel

### Embed Badge

![Health badge](/badges/hashbang-joyst/health.svg)

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

###  Alternatives

[moloquent/moloquent

A MongoDB based Eloquent model and Query builder for Laravel (Moloquent)

120114.6k7](/packages/moloquent-moloquent)[thedevsaddam/laravel-schema

Display the connected database information in console.

11627.9k1](/packages/thedevsaddam-laravel-schema)

PHPackages © 2026

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