PHPackages                             ray/media-query - 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. ray/media-query

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

ray/media-query
===============

PHP interface-based SQL framework

1.1.1(1w ago)11254.8k↓26.6%83MITPHPPHP ^8.2CI passing

Since Mar 12Pushed 1w ago3 watchersCompare

[ Source](https://github.com/ray-di/Ray.MediaQuery)[ Packagist](https://packagist.org/packages/ray/media-query)[ RSS](/packages/ray-media-query/feed)WikiDiscussions 1.x Synced 2d ago

READMEChangelog (10)Dependencies (36)Versions (64)Used By (3)

[![Hand-drawn Ray.MediaQuery logo showing sky, sea, and land separated by horizon and shoreline boundaries.](docs/assets/img/ray-media-query.png)](docs/assets/img/ray-media-query.png)

Ray.MediaQuery
==============

[](#raymediaquery)

[![codecov](https://camo.githubusercontent.com/741c2069ee7bdebdf25e50e24a2d798400a62854f463eea26037c9a3254f0c11/68747470733a2f2f636f6465636f762e696f2f67682f7261792d64692f5261792e4d6564696151756572792f6272616e63682f312e782f67726170682f62616467652e7376673f746f6b656e3d51424f504355504a5156)](https://codecov.io/gh/ray-di/Ray.MediaQuery)[![Type Coverage](https://camo.githubusercontent.com/5ccbe4de30e70690c7a9635c85683ddd60b2e9bbf5451547fe35d0c716ecabcf/68747470733a2f2f73686570686572642e6465762f6769746875622f7261792d64692f5261792e4d6564696151756572792f636f7665726167652e737667)](https://shepherd.dev/github/ray-di/Ray.MediaQuery)[![Continuous Integration](https://github.com/ray-di/Ray.MediaQuery/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/ray-di/Ray.MediaQuery/actions/workflows/continuous-integration.yml)

Interface-Driven SQL for PHP
----------------------------

[](#interface-driven-sql-for-php)

**Ray.MediaQuery lets SQL be SQL and objects be objects.**

Define a PHP interface, attach `#[DbQuery]`, write a SQL file, and Ray.MediaQuery provides the implementation through Ray.Di + AOP. Return types and docblocks drive fetching, hydration, pagination, and post-query result objects.

```
use Ray\MediaQuery\Annotation\DbQuery;

interface UserQueryInterface
{
    #[DbQuery('user_item')]
    public function item(string $id): ?User;
}

final class User
{
    public function __construct(
        public readonly string $id,
        public readonly string $name,
    ) {}
}
```

```
-- sql/user_item.sql
SELECT id, name FROM users WHERE id = :id;
```

```
$userQuery = $injector->getInstance(UserQueryInterface::class);
$user = $userQuery->item('user-123');
```

Why Ray.MediaQuery?
-------------------

[](#why-raymediaquery)

- **Zero implementation code** — interfaces become working query objects.
- **SQL-first** — use joins, CTEs, window functions, vendor-specific SQL, and query plans directly.
- **Typed PHP results** — hydrate rows to entities, typed collections, or custom result objects.
- **Rich domain objects** — use `factory:` classes, including DI-aware factories, to create computed or service-backed objects, such as exposing `age` from a stored `birth_date`.
- **Explicit boundaries** — SQL files, PHP interfaces, and domain objects remain visible and testable.
- **AI-friendly** — no hidden query generation; the contract is readable by humans and tools.

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

[](#installation)

```
composer require ray/media-query
```

Quick Start
-----------

[](#quick-start)

```
use Ray\AuraSqlModule\AuraSqlModule;
use Ray\Di\AbstractModule;
use Ray\Di\Injector;
use Ray\MediaQuery\Annotation\DbQuery;
use Ray\MediaQuery\MediaQuerySqlModule;

final class AppModule extends AbstractModule
{
    protected function configure(): void
    {
        $this->install(new MediaQuerySqlModule(
            interfaceDir: __DIR__ . '/Query',
            sqlDir: __DIR__ . '/sql',
        ));
        $this->install(new AuraSqlModule('sqlite::memory:'));
    }
}

interface TodoQueryInterface
{
    #[DbQuery('todo_add')]
    public function add(string $id, string $title): void;

    /** @return array */
    #[DbQuery('todo_list')]
    public function list(): array;
}

$injector = new Injector(new AppModule());
$todoQuery = $injector->getInstance(TodoQueryInterface::class);
$todoQuery->add('todo-1', 'Write SQL');
$todos = $todoQuery->list();
```

Result Types at a Glance
------------------------

[](#result-types-at-a-glance)

DeclarationMeaning`array`List of associative rows`?array` + `type: 'row'`Single associative row or `null``/** @return array */ array`Hydrated entity list`?User` + `type: 'row'`Single hydrated entity or `null``void`Execute DML and ignore the result`AffectedRows`DML row count`InsertedRow`INSERT id and resolved bound values`Pages`Lazy paginated hydrated rows`PostQueryInterface`Custom post-query result objectDocumentation
-------------

[](#documentation)

Start from the [Documentation Home](https://ray-di.github.io/Ray.MediaQuery/). It is the single entry point for the manual, hands-on tutorial, BDR pattern, FAQ, ecosystem links, and AI-oriented reference.

Demo Application
----------------

[](#demo-application)

See [demo/](./demo/) for a minimal runnable smoke test of the module wiring. The hands-on tutorial in the documentation site is the full feature walkthrough.

Philosophy
----------

[](#philosophy)

Ray.MediaQuery does not hide SQL to make objects comfortable, and it does not flatten objects to make SQL convenient. It lets both sides do what they are good at: SQL expresses data access precisely, while PHP expresses types, domain behavior, and dependency-injected object construction.

###  Health Score

65

—

FairBetter than 99% of packages

Maintenance98

Actively maintained with recent releases

Popularity44

Moderate usage in the ecosystem

Community25

Small or concentrated contributor base

Maturity80

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 92.9% 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 ~46 days

Recently: every ~18 days

Total

43

Last Release

8d ago

Major Versions

0.17.1 → v1.0.0-rc12025-08-01

1.1.0 → 100.x-dev2026-06-25

PHP version history (6 changes)0.1.0PHP ^7.4 || ^8.0

0.3.0PHP ^7.3 || ^8.0

0.9.0PHP ^8.0

0.12.1PHP ^8.1

0.14.0PHP &gt;=8.1 &lt;8.4

v1.0.0-rc3PHP ^8.2

### Community

Maintainers

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

---

Top Contributors

[![koriym](https://avatars.githubusercontent.com/u/529021?v=4)](https://github.com/koriym "koriym (559 commits)")[![jingu](https://avatars.githubusercontent.com/u/892913?v=4)](https://github.com/jingu "jingu (19 commits)")[![NaokiTsuchiya](https://avatars.githubusercontent.com/u/17171732?v=4)](https://github.com/NaokiTsuchiya "NaokiTsuchiya (8 commits)")[![apple-x-co](https://avatars.githubusercontent.com/u/8497012?v=4)](https://github.com/apple-x-co "apple-x-co (4 commits)")[![mstysk](https://avatars.githubusercontent.com/u/2937579?v=4)](https://github.com/mstysk "mstysk (4 commits)")[![HajimeMat-AVAP](https://avatars.githubusercontent.com/u/55294484?v=4)](https://github.com/HajimeMat-AVAP "HajimeMat-AVAP (3 commits)")[![claude](https://avatars.githubusercontent.com/u/81847?v=4)](https://github.com/claude "claude (2 commits)")[![Copilot](https://avatars.githubusercontent.com/in/1143301?v=4)](https://github.com/Copilot "Copilot (1 commits)")[![yuki777](https://avatars.githubusercontent.com/u/177159?v=4)](https://github.com/yuki777 "yuki777 (1 commits)")[![shotanue](https://avatars.githubusercontent.com/u/22065594?v=4)](https://github.com/shotanue "shotanue (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/ray-media-query/health.svg)

```
[![Health](https://phpackages.com/badges/ray-media-query/health.svg)](https://phpackages.com/packages/ray-media-query)
```

###  Alternatives

[nelmio/api-doc-bundle

Generates documentation for your REST API from attributes

2.4k67.4M263](/packages/nelmio-api-doc-bundle)[bear/resource

Hypermedia framework for object as a service

48687.7k43](/packages/bear-resource)[typo3/cms

TYPO3 CMS is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.

1.2k1.9M122](/packages/typo3-cms)[craftcms/cms

Craft CMS

3.6k3.6M3.1k](/packages/craftcms-cms)[friendsofsymfony/elastica-bundle

Elasticsearch PHP integration for your Symfony project using Elastica

1.3k17.9M50](/packages/friendsofsymfony-elastica-bundle)[kimai/kimai

Kimai - Time Tracking

4.8k9.0k1](/packages/kimai-kimai)

PHPackages © 2026

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