PHPackages                             osyra/syra - 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. osyra/syra

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

osyra/syra
==========

0.5.4(2mo ago)410.9k↓40.9%1MITPHPPHP &gt;=8.0.0CI failing

Since Oct 15Pushed 2mo ago2 watchersCompare

[ Source](https://github.com/SertyOan/Syra)[ Packagist](https://packagist.org/packages/osyra/syra)[ RSS](/packages/osyra-syra/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (2)Versions (28)Used By (0)

Syra
====

[](#syra)

**Syra** is a PHP Object-Relational Mapping library.

Installation
============

[](#installation)

You can install it via composer: osyra/syra

Defining needed classes
=======================

[](#defining-needed-classes)

You need to create two classes.

```
namespace App;
class CustomDatabase implements \Syra\DatabaseInterface {
    private static
        $writer,
        $reader;

    public static function getWriter() {
        if(is_null(self::$writer)) {
            self::$writer = new \Syra\MySQL\Database('hostname', 'user', 'password');
            self::$writer->connect();
        }

        return self::$writer;
    }

    public static function getReader() {
        if(is_null(self::$reader)) {
            // if you have only one server
            self::$reader = self::getWriter();

            // if you have a slave for read only you could write this :
            //   self::$reader = new \Syra\MySQL\Database('ro-hostname', 'ro-user', 'ro-password');
            //   self::$reader->connect();
        }

        return self::$reader;
    }
}
```

```
namespace App;
class CustomRequest extends \Syra\MySQL\Request {
    const
        DATABASE_CLASS = '\\App\\CustomDatabase';

    protected function buildClassFromTable($table) {
        return '\\App\\Model\\'.$table; // this must return the name of the class matched by the table
    }
}
```

Then for each table of your database you will add a class. The table primary key must be `id`, it can be an integer or a string.

```
namespace App\Model;
class Foobar extends \Syra\MySQL\ModelObject {
    const
        DATABASE_CLASS = '\\App\\CustomDatabase',
        DATABASE_SCHEMA = 'Schema',
        DATABASE_TABLE = 'Foobar';

    protected static
        $properties = [
            'id' => ['class' => 'Integer'],
            'name' => ['class' => 'String'],
            'parent' => ['class' => '\\App\\Model\\Bar']
        ];

    protected
        $id,
        $name,
        $parent;
}

class Bar extends \Syra\MySQL\ModelObject {
    const
        DATABASE_CLASS = '\\App\\CustomDatabase',
        DATABASE_SCHEMA = 'Schema',
        DATABASE_TABLE = 'Bar';

    protected static
        $properties = [
            'id' => ['class' => 'Integer'],
            'name' => ['class' => 'String'],
            'createdAt' => ['class' => 'DateTime']
        ];

    protected
        $id,
        $name,
        $createdAt;
}
```

Requesting data
===============

[](#requesting-data)

Requesting objects
------------------

[](#requesting-objects)

```
$foobars = \App\CustomRequest::get('Foobar')->withFields('id', 'name')
    ->mapAsObjects();

$foobar = \App\CustomRequest::get('Foobar')->withFields('id', 'name')
    ->where('', 'Foobar', 'id', '=', 1)
    ->mapAsObject();
```

Requesting objects with conditions
----------------------------------

[](#requesting-objects-with-conditions)

Condition is the first argument of any where() function. It can start with a closing parenthesis followed by AND or OR and can end with an opening parenthesis.

```
$foobars = \App\CustomRequest::get('Foobar')->withFields('id', 'name')
    ->where('', 'Foobar', 'parent', '=', $parentID)
    ->where('AND (', 'Foobar', 'name', 'LIKE', '%Hello%')
    ->where('OR', 'Foobar', 'name', 'LIKE', '%World')
    ->mapAsObjects();
```

Ordering
--------

[](#ordering)

```
$foobars = \App\CustomRequest::get('Foobar')->withFields('id', 'name')
    ->orderAscBy('Foobar', 'name')
    ->orderDescBy('Foobar', 'id')
    ->mapAsObjects();
```

Limit and offset
----------------

[](#limit-and-offset)

This will get 10 rows from database starting at 10th row.

```
$foobars = \App\CustomRequest::get('Foobar')->withFields('id', 'name')
    ->lines(10)
    ->offset(10)
    ->mapAsObjects();
```

Note: be aware this is a limitation of the number of rows, not the number of objects.

Linking tables to get sub-object
--------------------------------

[](#linking-tables-to-get-sub-object)

```
$foobars = \App\CustomRequest::get('Foobar')->withFields('id', 'name')
    ->leftJoin('Bar')->on('Foobar', 'parent')->withFields('id', 'name', 'createdAt')
    ->mapAsObjects();
```

Linking tables to get a collection
----------------------------------

[](#linking-tables-to-get-a-collection)

```
$bars = \App\CustomRequest::get('Bar')->withFields('id', 'name', 'createdAt')
    ->leftJoin('Foobar', 'Foobars')->on('Bar', 'id', 'parent')->withFields('id', 'name')
    ->mapAsObjects();

foreach($bars as $bar) {
    foreach($bar->myFoobars as $foobar) {
        ...
    }
}
```

Condition on linked table
-------------------------

[](#condition-on-linked-table)

```
$bars = \App\CustomRequest::get('Bar')->withFields('id', 'name', 'createdAt')
    ->leftJoin('Foobar', 'Foobars')->on('Bar', 'id', 'parent')->withFields('id', 'name')->with('', 'name', 'LIKE', '%Hello%')
    ->mapAsObjects();
```

Add additional condition between fields of two tables of same request
---------------------------------------------------------------------

[](#add-additional-condition-between-fields-of-two-tables-of-same-request)

```
$reference = new \stdClass;
$reference->table = 'Bar';
$reference->field = 'language';

$foobars = \App\CustomRequest::get('Foo')->withFields('id', 'language', 'name')
    ->leftJoin('Bar', 'Bars')->on('Foo', 'id', 'foo')->with('', 'language', '=', $reference)->withFields('id', 'foo', 'language')
    ->mapAsObject();
```

Using same table multiple times
-------------------------------

[](#using-same-table-multiple-times)

```
$bars = \App\CustomRequest::get('Bar')->withFields('id', 'name')
    ->leftJoin('Bar')->on('Bar', 'parent')->withFields('id', 'name') # equivalent to ->on('Bar::1', 'parent')
    ->leftJoin('Bar')->on('Bar::2', 'parent')->withFields('id', 'name')
    ->mapAsObjects();
```

Requesting as associative arrays (for latter JSON encoding)
-----------------------------------------------------------

[](#requesting-as-associative-arrays-for-latter-json-encoding)

```
$foobars = \App\CustomRequest::get('Foobar')->withFields('id', 'name')
    ->mapAsArrays();
```

Transforming objects to arrays
------------------------------

[](#transforming-objects-to-arrays)

```
$foobars = \App\CustomRequest::get('Foobar')->withFields('id', 'name')
    ->mapAsObjects();
$arrays = \App\CustomRequest::objectsAsArrays($foobars);

$foobar = \App\CustomRequest::get('Foobar')->withFields('id', 'name')
    ->where('', 'Foobar', 'id', '=', 1)
    ->mapAsObject();
$array = $foobar->asArray();
```

Modifying objects
=================

[](#modifying-objects)

Saving
------

[](#saving)

```
$foobar = \App\CustomRequest::get('Foobar')->withFields('id', 'name')
    ->where('', 'Foobar', 'id', '=', 1)
    ->mapAsObject();
$foobar->name = 'Something';
$foobar->save();
\App\Database::getWriter()->commit();
```

Deleting
--------

[](#deleting)

```
$foobar = \App\CustomRequest::get('Foobar')->withFields('id', 'name')
    ->where('', 'Foobar', 'id', '=', 1)
    ->mapAsObject();
$foobar->delete();
\App\Database::getWriter()->commit();
```

###  Health Score

49

—

FairBetter than 95% of packages

Maintenance84

Actively maintained with recent releases

Popularity29

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity59

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

Recently: every ~28 days

Total

24

Last Release

80d ago

PHP version history (2 changes)0.1.0PHP &gt;=5.4.0

0.1.4PHP &gt;=8.0.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/6a5fe614ce17948bbe85a3e7d70d8f173bfc4408b47dcfbb3707e97a26e25925?d=identicon)[SertyOan](/maintainers/SertyOan)

---

Top Contributors

[![SertyOan](https://avatars.githubusercontent.com/u/17992066?v=4)](https://github.com/SertyOan "SertyOan (111 commits)")

---

Tags

ormphp

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/osyra-syra/health.svg)

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

###  Alternatives

[doctrine/orm

Object-Relational-Mapper for PHP

10.2k285.3M6.2k](/packages/doctrine-orm)[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k115.1M102](/packages/jdorn-sql-formatter)[illuminate/database

The Illuminate Database package.

2.8k52.4M9.4k](/packages/illuminate-database)[ramsey/uuid-doctrine

Use ramsey/uuid as a Doctrine field type.

90440.3M211](/packages/ramsey-uuid-doctrine)[reliese/laravel

Reliese Components for Laravel Framework code generation.

1.7k3.4M16](/packages/reliese-laravel)[wildside/userstamps

Laravel Userstamps provides an Eloquent trait which automatically maintains `created\_by` and `updated\_by` columns on your model, populated by the currently authenticated user in your application.

7511.7M13](/packages/wildside-userstamps)

PHPackages © 2026

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