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(4mo ago)411.7k↓62.9%1[1 PRs](https://github.com/SertyOan/Syra/pulls)MITPHPPHP &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 2d 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 94% of packages

Maintenance82

Actively maintained with recent releases

Popularity30

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity60

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

Recently: every ~28 days

Total

24

Last Release

126d 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

[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k117.2M118](/packages/jdorn-sql-formatter)[propel/propel1

Propel is an open-source Object-Relational Mapping (ORM) for PHP5.

8351.6M87](/packages/propel-propel1)[jfelder/oracledb

Oracle DB driver for Laravel

11518.4k](/packages/jfelder-oracledb)

PHPackages © 2026

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