Skip to content

Commit

Permalink
Init Remap
Browse files Browse the repository at this point in the history
  • Loading branch information
xepozz committed Mar 16, 2024
0 parents commit 84e6a7c
Show file tree
Hide file tree
Showing 13 changed files with 545 additions and 0 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/phpunit.yaml
@@ -0,0 +1,41 @@
on:
pull_request:
push:

name: "PHPUnit"

jobs:
phpunit:
name: PHP ${{ matrix.php }}-${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
php:
- "8.0"
- "8.1"
- "8.2"
- "8.3"
steps:
- name: Checkout
uses: actions/checkout@v2.3.4

- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: composer:v2
coverage: pcov

- name: Install dependencies
run: composer install

- name: Run tests with code coverage.
run: vendor/bin/phpunit --coverage-clover=coverage.xml --colors=always

- name: Upload coverage to Codecov.
if: matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v3
with:
files: ./coverage.xml
34 changes: 34 additions & 0 deletions .github/workflows/psalm.yaml
@@ -0,0 +1,34 @@
on:
pull_request:
push:

name: "Psalm"

jobs:
phpunit:
name: PHP ${{ matrix.php }}-${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
php:
- "8.0"
- "8.1"
- "8.2"
- "8.3"
steps:
- name: Checkout
uses: actions/checkout@v2.3.4

- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: composer:v2

- name: Install dependencies
run: composer install

- name: Run psalm.
run: vendor/bin/psalm --shepherd --stats --output-format=github --php-version=${{ matrix.php }}
5 changes: 5 additions & 0 deletions .gitignore
@@ -0,0 +1,5 @@
/vendor/
.idea
composer.lock
.phpunit.result.cache
.phpunit.cache
104 changes: 104 additions & 0 deletions README.md
@@ -0,0 +1,104 @@
# User ID tracing

The library allows you to track the unique user in the application.

[![Latest Stable Version](https://poser.pugx.org/xepozz/remap/v/stable.svg)](https://packagist.org/packages/xepozz/remap)
[![Total Downloads](https://poser.pugx.org/xepozz/remap/downloads.svg)](https://packagist.org/packages/xepozz/remap)
[![phpunit](https://github.com/xepozz/remap/workflows/PHPUnit/badge.svg)](https://github.com/xepozz/remap/actions)
[![codecov](https://codecov.io/gh/xepozz/remap/branch/master/graph/badge.svg?token=UREXAOUHTJ)](https://codecov.io/gh/xepozz/remap)
[![type-coverage](https://shepherd.dev/github/xepozz/remap/coverage.svg)](https://shepherd.dev/github/xepozz/remap)

## Installation

```bash
composer req xepozz/remap
```

## Description

The library allows you to map data from the database to objects.

The main goal is to simplify the process of querying long SQL queries and mapping the result to objects.

The mapper is designed to be used with querying of many objects at once.
It uses `\Generator` to fetch data from the database and map it to objects one by one, so it's memory efficient.

Under the hood, it uses:
- [yiisoft/db](https://github.com/yiisoft/db) to fetch data from the database
- [yiisoft/hydrator](https://github.com/yiisoft/hydrator) to map data to objects.

## Usage

Pass a class name and a query to the `Remap`.

```php
final class Todo
{
public int $id;
public string $title;
public int $status;
public int $created_at;
}
```

```php
$sql = 'SELECT id, title, status, created_at FROM todo WHERE id = :id LIMIT 1';
$params = ['id' => 1];

$remap->map(Todo::class, $sql, $params); // returns \Generator of Todo objects
```

### Tips

#### Define query-related methods in the class

```php
final class Todo
{
public int $id;
public string $title;
public int $status;
public int $created_at;

public static function selectOne(int $id): array
{
return [
'SELECT id, title, status, created_at FROM todo WHERE id = :id LIMIT 1',
['id' => $id],
];
}

public static function selectAll(): string
{
return 'SELECT id, title, status, created_at FROM todo';
}
}
```

And now it's easy to use:

```php
$remap->map(Todo::class, ...Todo::selectOne(1));
$remap->map(Todo::class, Todo::selectOne(1)); // or shorter
$remap->map(Todo::class, Todo::selectAll());
```

#### Unpack and store the result

```php
$remap->map(...)
```

Always returns a generator. If you want to get an array of objects, use `iterator_to_array`:

```php
$result = iterator_to_array(
$remap->map(Todo::class, Todo::selectOne(1))
);
```

Or shorter:

```php
$result = [...$remap->map(Todo::class, Todo::selectOne(1))];
```
29 changes: 29 additions & 0 deletions composer.json
@@ -0,0 +1,29 @@
{
"name": "xepozz/remap",
"type": "library",
"require": {
"yiisoft/hydrator": "dev-master",
"yiisoft/db": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^10.5",
"vimeo/psalm": "^5.23",
"yiisoft/db-sqlite": "^1.0"
},
"autoload": {
"psr-4": {
"Xepozz\\Remap\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Xepozz\\Remap\\Tests\\": "tests/"
}
},
"authors": [
{
"name": "Dmitrii Derepko",
"email": "xepozz@list.ru"
}
]
}
25 changes: 25 additions & 0 deletions phpunit.xml.dist
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
colors="true"
failOnRisky="false"
failOnWarning="false"
stopOnFailure="false"
executionOrder="random"
resolveDependencies="true"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
cacheDirectory=".phpunit.cache"
>
<php>
<ini name="error_reporting" value="-1"/>
</php>
<testsuites>
<testsuite name="Tests">
<directory>./tests</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory>./src</directory>
</include>
</source>
</phpunit>
17 changes: 17 additions & 0 deletions psalm.xml
@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<psalm
errorLevel="2"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
findUnusedBaselineEntry="true"
findUnusedCode="false"
>
<projectFiles>
<directory name="src" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
</psalm>
40 changes: 40 additions & 0 deletions src/Remap.php
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Xepozz\Remap;

use Throwable;
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidConfigException;
use Yiisoft\Hydrator\HydratorInterface;

final class Remap
{
public function __construct(
private readonly HydratorInterface $hydrator,
private readonly ConnectionInterface $connection,
) {
}

/**
* @template T
* @param class-string<T> $class
* @return iterable<T>
* @throws Throwable
* @throws Exception
* @throws InvalidConfigException
*/
public function map(string $class, string|array $sql, array $params = []): iterable
{
if (is_array($sql)) {
$params = $sql[1] ?? $params;
$sql = $sql[0];
}
$iterator = $this->connection->createCommand($sql, $params)->query();
foreach ($iterator as $row) {
yield $this->hydrator->create($class, $row);
}
}
}
1 change: 1 addition & 0 deletions tests/.gitignore
@@ -0,0 +1 @@
database.

0 comments on commit 84e6a7c

Please sign in to comment.