{"id":46371288,"url":"https://github.com/ray-di/ray.aurasqlmodule","last_synced_at":"2026-03-13T02:13:32.231Z","repository":{"id":24846391,"uuid":"28261338","full_name":"ray-di/Ray.AuraSqlModule","owner":"ray-di","description":"Aura.Sql module for Ray.Di","archived":false,"fork":false,"pushed_at":"2026-01-01T11:52:36.000Z","size":669,"stargazers_count":8,"open_issues_count":1,"forks_count":16,"subscribers_count":4,"default_branch":"1.x","last_synced_at":"2026-01-06T10:18:13.292Z","etag":null,"topics":["aura","database","ray-module","sql"],"latest_commit_sha":null,"homepage":"https://packagist.org/packages/ray/aura-sql-module","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/ray-di.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2014-12-20T08:17:52.000Z","updated_at":"2026-01-01T11:52:37.000Z","dependencies_parsed_at":"2025-01-22T08:22:49.311Z","dependency_job_id":"2a7c150a-4723-4ed2-8075-68936e4c26d9","html_url":"https://github.com/ray-di/Ray.AuraSqlModule","commit_stats":{"total_commits":367,"total_committers":13,"mean_commits":28.23076923076923,"dds":0.07084468664850141,"last_synced_commit":"8901e5e21bed545a024245d82e3a00961b391f71"},"previous_names":[],"tags_count":52,"template":false,"template_full_name":null,"purl":"pkg:github/ray-di/Ray.AuraSqlModule","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ray-di%2FRay.AuraSqlModule","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ray-di%2FRay.AuraSqlModule/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ray-di%2FRay.AuraSqlModule/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ray-di%2FRay.AuraSqlModule/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ray-di","download_url":"https://codeload.github.com/ray-di/Ray.AuraSqlModule/tar.gz/refs/heads/1.x","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ray-di%2FRay.AuraSqlModule/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30109076,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T03:40:26.266Z","status":"ssl_error","status_checked_at":"2026-03-05T03:39:15.902Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["aura","database","ray-module","sql"],"created_at":"2026-03-05T04:02:01.427Z","updated_at":"2026-03-05T04:02:06.440Z","avatar_url":"https://github.com/ray-di.png","language":"PHP","readme":"# Ray.AuraSqlModule\n\n[![codecov](https://codecov.io/gh/ray-di/Ray.AuraSqlModule/branch/1.x/graph/badge.svg?token=gcWaftzoXp)](https://codecov.io/gh/ray-di/Ray.AuraSqlModule)\n[![Type Coverage](https://shepherd.dev/github/ray-di/Ray.AuraSqlModule/coverage.svg)](https://shepherd.dev/github/ray-di/Ray.AuraSqlModule)\n[![Continuous Integration](https://github.com/ray-di/Ray.AuraSqlModule/actions/workflows/continuous-integration.yml/badge.svg?branch=2.x)](https://github.com/ray-di/Ray.AuraSqlModule/actions/workflows/continuous-integration.yml)\n\nAn [Aura.Sql](https://github.com/auraphp/Aura.Sql) Module for [Ray.Di](https://github.com/koriym/Ray.Di)\n\n## Installation\n\n```bash\ncomposer require ray/aura-sql-module\n```\n\n## Getting started\n\n### Module install\n\n```php\nuse Ray\\Di\\AbstractModule;\nuse Ray\\AuraSqlModule\\AuraSqlModule;\nuse Ray\\AuraSqlModule\\AuraSqlQueryModule;\n\nclass AppModule extends AbstractModule\n{\n    protected function configure()\n    {\n        $this-\u003einstall(\n            new AuraSqlModule(\n                'mysql:host=localhost;dbname=test',\n                'username',\n                'password',\n                'slave1,slave2,slave3', // optional slave server list\n                $options,               // optional key=\u003evalue array of driver-specific connection options\n                $queries                // Queries to execute after the connection.\n            )\n        );\n    }\n}\n```\n\nUse AuraSqlEnvModule to get the value from the environment variable each time at runtime, instead of specifying the value directly.\n\n```php\n$this-\u003einstall(\n    new AuraSqlEnvModule(\n        'PDO_DSN',             // getenv('PDO_DSN')\n        'PDO_USER',            // getenv('PDO_USER')\n        'PDO_PASSWORD',        // getenv('PDO_PASSWORD')\n        'PDO_SLAVE',           // getenv('PDO_SLAVE')\n        $options,              // optional key=\u003evalue array of driver-specific connection options\n        $queries               // Queries to execute after the connection.\n    )\n);\n```\n\n## Replication\n\nInstalling `AuraSqlReplicationModule` using a `connection locator` for master/slave connections.\n\n```php\nuse Ray\\Di\\AbstractModule;\nuse Ray\\AuraSqlModule\\AuraSqlModule;\nuse Aura\\Sql\\ConnectionLocator;\nuse Aura\\Sql\\Connection;\n\nclass AppModule extends AbstractModule\n{\n    protected function configure()\n    {\n        $locator = new ConnectionLocator;\n        $locator-\u003esetWrite('master', new Connection('mysql:host=localhost;dbname=master', 'id', 'pass'));\n        $locator-\u003esetRead('slave1',  new Connection('mysql:host=localhost;dbname=slave1', 'id', 'pass'));\n        $locator-\u003esetRead('slave2',  new Connection('mysql:host=localhost;dbname=slave2', 'id', 'pass'));\n        $this-\u003einstall(new AuraSqlReplicationModule($locator));\n    }\n}\n```\n\nYou will now have a slave db connection when using HTTP GET, or a master db connection in other HTTP methods.\n\n## Multiple DB\n\nYou may want to inject different connection destinations on the same DB interface with `#[Named($qualifier)]` attribute.\nTwo modules are provided. `NamedPdoModule` is for non replication use. and `AuraSqlReplicationModule` is for replication use.\n\n```php\n#[Inject]\npublic function setLoggerDb(#[Named('log_db')] ExtendedPdoInterface $pdo)\n{\n    // ...\n}\n```\n\n### with no replication\n\nUse `NamedPdoModule ` to inject different named `Pdo` instance for **non** Replication use.\nFor instance, This module install `log_db` named `Pdo` instance.\n\n```php\nclass AppModule extends AbstractModule\n{\n    protected function configure()\n    {\n        $this-\u003einstall(new NamedPdoModule('log_db', 'mysql:host=localhost;dbname=log', 'username', 'password'));\n    }\n}\n```\n\nOr\n\n```php\nclass AppModule extends AbstractModule\n{\n    protected function configure()\n    {\n        $this-\u003einstall(new NamedPdoEnvModule('log_db', 'LOG_DSN', 'LOG_USERNAME', 'LOG_PASSWORD'));\n    }\n}\n```\n\n### with replication\n\nYou can set `$qualifier` in 2nd parameter of AuraSqlReplicationModule.\n\n```php\nclass AppModule extends AbstractModule\n{\n    protected function configure()\n    {\n        $this-\u003einstall(new AuraSqlReplicationModule($locator, 'log_db'));\n    }\n}\n```\n\n## Transaction\n\nAny method marked with `#[Transactional]` will have a transaction started before, and ended after it is called.\n\n```php\nuse Ray\\AuraSqlModule\\Annotation\\WriteConnection; // important\nuse Ray\\AuraSqlModule\\Annotation\\Transactional;   // important\n\nclass User\n{\n    public $pdo;\n\n    #[WriteConnection, Transactional]\n    public function write()\n    {\n         // $this-\u003epdo-\u003erollback(); when exception thrown.\n    }\n}\n```\n\n## Query Builder\n\n[Aura.SqlQuery](https://github.com/auraphp/Aura.SqlQuery) provides query builders for MySQL, Postgres, SQLite, and Microsoft SQL Server. Following four interfaces are bound and can be injected via constructor:\n\n* `Aura\\SqlQuery\\Common\\SelectInterface`\n* `Aura\\SqlQuery\\Common\\InsertInterface`\n* `Aura\\SqlQuery\\Common\\UpdateInterface`\n* `Aura\\SqlQuery\\Common\\DeleteInterface`\n\n```php\nuse Aura\\SqlQuery\\Common\\SelectInterface;\nuse Aura\\Sql\\ExtendedPdoInterface;\n\nclass UserRepository\n{\n    public function __construct(\n        private readonly SelectInterface $select,\n        private readonly ExtendedPdoInterface $pdo\n    ) {}\n\n    public function findById(int $id): array\n    {\n        $statement = $this-\u003eselect\n            -\u003edistinct()                    // SELECT DISTINCT\n            -\u003ecols([                        // select these columns\n                'id',                       // column name\n                'name AS namecol',          // one way of aliasing\n                'col_name' =\u003e 'col_alias',  // another way of aliasing\n                'COUNT(foo) AS foo_count'   // embed calculations directly\n            ])\n            -\u003efrom('users AS u')            // FROM these tables\n            -\u003ewhere('id = :id')\n            -\u003egetStatement();\n\n        return $this-\u003epdo-\u003efetchAssoc($statement, ['id' =\u003e $id]);\n    }\n}\n```\n\n### Multiple Query Builders\n\n```php\nuse Aura\\SqlQuery\\Common\\SelectInterface;\nuse Aura\\SqlQuery\\Common\\InsertInterface;\nuse Aura\\SqlQuery\\Common\\UpdateInterface;\nuse Aura\\Sql\\ExtendedPdoInterface;\n\nclass UserService\n{\n    public function __construct(\n        private readonly SelectInterface $select,\n        private readonly InsertInterface $insert,\n        private readonly UpdateInterface $update,\n        private readonly ExtendedPdoInterface $pdo\n    ) {}\n\n    public function createUser(array $userData): int\n    {\n        $statement = $this-\u003einsert\n            -\u003einto('users')\n            -\u003ecols($userData)\n            -\u003egetStatement();\n\n        $this-\u003epdo-\u003eperform($statement, $this-\u003einsert-\u003egetBindValues());\n        \n        return (int) $this-\u003epdo-\u003elastInsertId();\n    }\n\n    public function updateUser(int $id, array $userData): bool\n    {\n        $statement = $this-\u003eupdate\n            -\u003etable('users')\n            -\u003ecols($userData)\n            -\u003ewhere('id = :id')\n            -\u003ebindValue('id', $id)\n            -\u003egetStatement();\n\n        return $this-\u003epdo-\u003eperform($statement, $this-\u003eupdate-\u003egetBindValues());\n    }\n}\n```\n\n## Pagination\n\nPagination service is provided for both `ExtendedPdo` raw sql and `Select` query builder.\n\n**ExtendedPdo**\n\n```php\nuse Ray\\AuraSqlModule\\Pagerfanta\\AuraSqlPagerFactoryInterface;\nuse Aura\\Sql\\ExtendedPdoInterface;\n\nclass UserListService\n{\n    public function __construct(\n        private readonly AuraSqlPagerFactoryInterface $pagerFactory,\n        private readonly ExtendedPdoInterface $pdo\n    ) {}\n\n    public function getUserList(int $page): Page\n    {\n        $sql = 'SELECT * FROM users WHERE active = :active';\n        $params = ['active' =\u003e 1];\n        $pager = $this-\u003epagerFactory-\u003enewInstance($this-\u003epdo, $sql, $params, 10, '/?page={page}\u0026category=users');\n        \n        return $pager[$page];\n    }\n}\n```\n\n**Select query builder**\n\n```php\nuse Ray\\AuraSqlModule\\Pagerfanta\\AuraSqlQueryPagerFactoryInterface;\nuse Aura\\SqlQuery\\Common\\SelectInterface;\nuse Aura\\Sql\\ExtendedPdoInterface;\n\nclass ProductListService\n{\n    public function __construct(\n        private readonly AuraSqlQueryPagerFactoryInterface $queryPagerFactory,\n        private readonly SelectInterface $select,\n        private readonly ExtendedPdoInterface $pdo\n    ) {}\n\n    public function getProductList(int $page, string $category): Page\n    {\n        $select = $this-\u003eselect\n            -\u003efrom('products')\n            -\u003ewhere('category = :category')\n            -\u003ebindValue('category', $category);\n            \n        $pager = $this-\u003equeryPagerFactory-\u003enewInstance($this-\u003epdo, $select, 10, '/?page={page}\u0026category=' . $category);\n        \n        return $pager[$page];\n    }\n}\n```\n\nAn array access with page number returns `Page` value object.\n\n```php\n/* @var Pager \\Ray\\AuraSqlModule\\Pagerfanta\\Page */\n\n// $page-\u003edata // sliced data\n// $page-\u003ecurrent;\n// $page-\u003etotal\n// $page-\u003ehasNext\n// $page-\u003ehasPrevious\n// $page-\u003emaxPerPage;\n// (string) $page // pager html\n```\n\nIt is iterable.\n\n```php\nforeach ($page as $item) {\n    // ...\n}\n```\n\n### View\n\nThe view template can be changed with binding. See more at [Pagerfanta](https://github.com/whiteoctober/Pagerfanta#views).\n\n```php\nuse Pagerfanta\\View\\Template\\TemplateInterface;\nuse Pagerfanta\\View\\Template\\TwitterBootstrap3Template;\nuse Ray\\AuraSqlModule\\Annotation\\PagerViewOption;\n\n$this-\u003ebind(TemplateInterface::class)-\u003eto(TwitterBootstrap3Template::class);\n$this-\u003ebind()-\u003eannotatedWith(PagerViewOption::class)-\u003etoInstance($pagerViewOption);\n```\n\n## Profile\n\nTo log SQL execution, install `AuraSqlProfileModule`.\nIt will be logged by a logger bound to the [PSR-3](https://www.php-fig.org/psr/psr-3/) logger. This example binds a minimal function logger created in an anonymous class.\n\n```php\nclass DevModule extends AbstractModule\n{\n    protected function configure()\n    {\n        // ...\n        $this-\u003einstall(new AuraSqlProfileModule());\n        $this-\u003ebind(LoggerInterface::class)-\u003etoInstance(\n            new class extends AbstractLogger {\n                /** @inheritDoc */\n                public function log($level, $message, array $context = [])\n                {\n                    $replace = [];\n                    foreach ($context as $key =\u003e $val) {\n                        if (! is_array($val) \u0026\u0026 (! is_object($val) || method_exists($val, '__toString'))) {\n                            $replace['{' . $key . '}'] = $val;\n                        }\n                    }\n            \n                    error_log(strtr($message, $replace));\n                }\n            }\n        );\n    }\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fray-di%2Fray.aurasqlmodule","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fray-di%2Fray.aurasqlmodule","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fray-di%2Fray.aurasqlmodule/lists"}