Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 42 additions & 12 deletions .docker/php/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,23 +1,53 @@
ARG PHP_VERSION=8.1
FROM php:${PHP_VERSION}-cli-alpine
FROM php:${PHP_VERSION}-cli-bookworm

RUN apk add --no-cache \
libpq-dev \
libzip-dev \
git \
zip \
unzip && \
rm -rf /var/cache/apk/* && \
rm -rf /tmp/*
# Update dependencies list
RUN apt-get clean all \
&& apt-get update \
&& apt-get autoremove

# Base dependencies
RUN apt-get install -y --no-install-recommends \
apt-transport-https \
ca-certificates \
curl \
gnupg \
libpq-dev \
libzip-dev \
git \
zip \
unzip

# PHP extensions
RUN docker-php-ext-install -j$(nproc) pdo pdo_mysql pdo_pgsql zip mysqli pgsql

# Microsoft repo (Debian 12 / bookworm)
RUN set -eux; \
mkdir -p /etc/apt/keyrings; \
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc \
| gpg --dearmor > /etc/apt/keyrings/microsoft.gpg; \
chmod 0644 /etc/apt/keyrings/microsoft.gpg; \
echo "deb [arch=amd64,arm64 signed-by=/etc/apt/keyrings/microsoft.gpg] https://packages.microsoft.com/debian/12/prod bookworm main" \
> /etc/apt/sources.list.d/microsoft-prod.list; \
apt-get update; \
ACCEPT_EULA=Y apt-get install -y --no-install-recommends msodbcsql18 mssql-tools18; \
echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' > /etc/profile.d/mssql-tools.sh;

# PHP SQL Server extensions
RUN apt-get update && apt-get install -y --no-install-recommends \
unixodbc unixodbc-dev \
$PHPIZE_DEPS
RUN pecl install sqlsrv pdo_sqlsrv \
&& docker-php-ext-enable sqlsrv pdo_sqlsrv

# Create user
ARG PUID=1000
ARG PGID=1000
RUN addgroup -g ${PGID} -S php && \
adduser -u ${PUID} -S -G php -h /home/php -s /bin/bash php && \
mkdir -p /app && chown -R php:php /app
RUN groupadd -g ${PGID} php && \
useradd -l -u ${PUID} -g php php && \
install -d -m 0755 -o php -g php /home/php

# Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
RUN chown php:php /usr/bin/composer

Expand Down
14 changes: 12 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ on:
paths-ignore:
- doc/**
branches:
- main
- v*.*
- '**'

env:
php-extensions: mbstring, intl, mysqli, pgsql, sqlsrv-5.10.0beta2
Expand All @@ -22,6 +21,10 @@ jobs:

runs-on: ubuntu-latest

if: |
github.event_name != 'pull_request'
|| github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name

strategy:
matrix:
php-version: [ '8.1', '8.2', '8.3', '8.4' ]
Expand Down Expand Up @@ -55,6 +58,10 @@ jobs:
tests:
name: Tests

if: |
github.event_name != 'pull_request'
|| github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name

strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -211,6 +218,9 @@ jobs:
name: Code coverage finish
needs: tests
runs-on: ubuntu-latest
if: |
github.event_name != 'pull_request'
|| github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
steps:
- name: Coveralls Finished
env:
Expand Down
1 change: 1 addition & 0 deletions .phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ parameters:
- { identifier: method.internalClass }
- { identifier: new.internalClass }
- '#Call to static method Tester\\Assert::type\(\).+will always evaluate to true\.#'
- '#^Access to deprecated static property \$collectionGetByWithLimitClause of class Nextras\\Orm\\FeatureToggle(.+)#'

services:
-
Expand Down
10 changes: 10 additions & 0 deletions contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ To set up tests configuration, copy [databases.sample.ini](tests/databases.sampl

```ini
; databases.ini example
[array]

[mysql]
driver = mysqli
host = "mysql"
Expand All @@ -37,6 +39,14 @@ host = "pgsql"
database = nextras_orm_test
username = postgres
password = postgres

[sqlsrv]
driver = sqlsrv
host = "sqlsrv"
username = SA
password = "YourStrong!Passw0rd"
database = nextras_orm_test
TrustServerCertificate = true
```

```bash
Expand Down
15 changes: 14 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ services:
--innodb-doublewrite=0
--skip-log-bin
pgsql:
image: postgres:${PGSQL_VERSION:-latest}
image: postgres:${PGSQL_VERSION:-17}
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
Expand All @@ -22,6 +22,19 @@ services:
-c fsync=off
-c synchronous_commit=off
-c full_page_writes=off
sqlsrv:
image: mcr.microsoft.com/mssql/server:${MSSQL_VERSION:-2025-latest}
environment:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: ${MSSQL_SA_PASSWORD:-YourStrong!Passw0rd}
MSSQL_PID: "Developer"
tmpfs:
- /var/opt/mssql:rw,uid=10001,gid=0,mode=0775,size=1g
healthcheck:
test: ["CMD-SHELL", "pidof sqlservr >/dev/null || exit 1"]
interval: 5s
timeout: 3s
retries: 30
php:
build:
context: .docker/php
Expand Down
20 changes: 18 additions & 2 deletions src/Collection/DbalCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Nextras\Orm\Exception\InvalidStateException;
use Nextras\Orm\Exception\MemberAccessException;
use Nextras\Orm\Exception\NoResultException;
use Nextras\Orm\FeatureToggle;
use Nextras\Orm\Mapper\Dbal\DbalMapper;
use Nextras\Orm\Mapper\IRelationshipMapper;
use function count;
Expand Down Expand Up @@ -71,13 +72,28 @@ public function __construct(

public function getBy(array $conds): ?IEntity
{
return $this->findBy($conds)->fetch();
$collection = $this->findBy($conds);
if (FeatureToggle::$collectionGetByWithLimitClause
// Skipped for SqlServer because it does not support syntax generated by nextras/dbal
&& $this->connection->getPlatform()->getName() !== SqlServerPlatform::NAME
) {
$collection = $collection->limitBy(1);
}

return $collection->fetch();
}


public function getByChecked(array $conds): IEntity
{
return $this->findBy($conds)->fetchChecked();
$collection = $this->findBy($conds);
if (FeatureToggle::$collectionGetByWithLimitClause
// Skipped for SqlServer because it does not support syntax generated by nextras/dbal
&& $this->connection->getPlatform()->getName() !== SqlServerPlatform::NAME) {
$collection = $collection->limitBy(1);
}

return $collection->fetchChecked();
}


Expand Down
11 changes: 11 additions & 0 deletions src/FeatureToggle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php declare(strict_types=1);

namespace Nextras\Orm;

final class FeatureToggle
{

/** @deprecated This switch will be removed in 6.0, limit will be always enabled */
public static bool $collectionGetByWithLimitClause = true;

}
1 change: 1 addition & 0 deletions tests/databases.sample.ini
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ host = "localhost"
username = SA
password = "YourStrong!Passw0rd"
database = nextras_orm_test
TrustServerCertificate = true
6 changes: 3 additions & 3 deletions tests/db/mssql-reset.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
$connection->reconnectWithConfig(
['database' => 'tempdb'] + $connection->getConfig()
);
$connection->query('DROP DATABASE nextras_orm_test');
$connection->query('CREATE DATABASE nextras_orm_test');
$connection->query('DROP DATABASE IF EXISTS %table', $dbname);
$connection->query('CREATE DATABASE %table', $dbname);
$connection->reconnectWithConfig(
['database' => 'nextras_orm_test'] + $connection->getConfig()
['database' => $dbname] + $connection->getConfig()
);
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1 LIMIT 1;
START TRANSACTION;
UPDATE "books" SET "price" = 1000, "price_currency" = 'CZK' WHERE "id" = 1;
COMMIT;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1 LIMIT 1;
START TRANSACTION;
UPDATE "books" SET "price" = NULL, "price_currency" = NULL WHERE "id" = 1;
COMMIT;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1 LIMIT 1;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1 LIMIT 1;
START TRANSACTION;
UPDATE "books" SET "price" = 1000, "price_currency" = 'CZK', "orig_price_cents" = 330, "orig_price_currency" = 'EUR' WHERE "id" = 1;
COMMIT;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1 LIMIT 1;
Original file line number Diff line number Diff line change
@@ -1 +1 @@
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1 LIMIT 1;
Original file line number Diff line number Diff line change
@@ -1 +1 @@
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1 LIMIT 1;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
SELECT "books".* FROM "books" AS "books" WHERE "books"."price" >= 1000;
SELECT COUNT(*) AS count FROM (SELECT "books"."id" FROM "books" AS "books" WHERE "books"."price" >= 1000) temp;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1 LIMIT 1;
START TRANSACTION;
UPDATE "books" SET "price" = 1000, "price_currency" = 'CZK' WHERE "id" = 1;
COMMIT;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
SELECT "books".* FROM "books" AS "books" ORDER BY "books"."price" ASC;
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" = 1;
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" = 1 LIMIT 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."author_id" IN (1) ORDER BY "books"."id" DESC, "books"."price" DESC;
SELECT
"authors".*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" = 1;
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" = 1 LIMIT 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."author_id" IN (1) ORDER BY "books"."id" DESC;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 3;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 3 LIMIT 1;
START TRANSACTION;
INSERT INTO "eans" ("code", "type") VALUES ('123', 2);
SELECT CURRVAL('public.eans_id_seq');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 923;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 923;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 923 LIMIT 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 923 LIMIT 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1 LIMIT 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1 LIMIT 1;
Original file line number Diff line number Diff line change
@@ -1 +1 @@
SELECT "publishers".* FROM "publishers" AS "publishers" WHERE "publishers"."publisher_id" = 1;
SELECT "publishers".* FROM "publishers" AS "publishers" WHERE "publishers"."publisher_id" = 1 LIMIT 1;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" = 1;
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" = 1 LIMIT 1;
SELECT COUNT(*) AS count FROM (SELECT "books"."id" FROM "books" AS "books" WHERE "books"."author_id" = 1) temp;
SELECT "books".* FROM "books" AS "books" WHERE "books"."author_id" = 1;
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" = 2;
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" = 2 LIMIT 1;
SELECT COUNT(*) AS count FROM (SELECT "books"."id" FROM "books" AS "books" WHERE "books"."author_id" IN (1, 2)) temp;
SELECT "books".* FROM "books" AS "books" WHERE "books"."author_id" IN (1, 2);
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1 LIMIT 1;
START TRANSACTION;
INSERT INTO "eans" ("code", "type") VALUES ('123', 2);
SELECT CURRVAL('public.eans_id_seq');
UPDATE "books" SET "ean_id" = 1 WHERE "id" = 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 2;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 2 LIMIT 1;
INSERT INTO "eans" ("code", "type") VALUES ('456', 1);
SELECT CURRVAL('public.eans_id_seq');
UPDATE "books" SET "ean_id" = 2 WHERE "id" = 2;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1;
SELECT "books".* FROM "books" AS "books" WHERE "books"."id" = 1 LIMIT 1;
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" IN (1);
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" IN (1);
SELECT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ COMMIT;
START TRANSACTION;
INSERT INTO "user_stats" ("user_id", "date", "value") VALUES (1, '2018-09-09 08:09:02.000000'::timestamptz, 100);
COMMIT;
SELECT "user_stats".* FROM "user_stats" AS "user_stats" WHERE ("user_stats"."user_id" = 1) AND ("user_stats"."date" = '2018-09-09 08:09:02.000000'::timestamptz);
SELECT "user_stats".* FROM "user_stats" AS "user_stats" WHERE ("user_stats"."user_id" = 1) AND ("user_stats"."date" = '2018-09-09 08:09:02.000000'::timestamptz) LIMIT 1;
START TRANSACTION;
UPDATE "user_stats" SET "value" = 101 WHERE "user_id" = 1 AND "date" = '2018-09-09 08:09:02.000000'::timestamptz;
COMMIT;
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ COMMIT;
START TRANSACTION;
INSERT INTO "user_stats_x" ("user_id", "date", "value") VALUES (1, '2019-01-01'::date, 100);
COMMIT;
SELECT "user_stats_x".* FROM "user_stats_x" AS "user_stats_x" WHERE "user_stats_x"."date" = '2019-01-01'::date;
SELECT "user_stats_x".* FROM "user_stats_x" AS "user_stats_x" WHERE "user_stats_x"."date" = '2019-01-01'::date LIMIT 1;
START TRANSACTION;
UPDATE "user_stats_x" SET "value" = 200 WHERE "user_id" = 1 AND "date" = '2019-01-01'::date;
COMMIT;
SELECT "user_stats_x".* FROM "user_stats_x" AS "user_stats_x" WHERE "user_stats_x"."date" = '2019-01-01'::date;
SELECT "user_stats_x".* FROM "user_stats_x" AS "user_stats_x" WHERE "user_stats_x"."date" = '2019-01-01'::date LIMIT 1;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SELECT "tag_followers".* FROM "tag_followers" AS "tag_followers" WHERE ("tag_followers"."tag_id" = 3) AND ("tag_followers"."author_id" = 1);
SELECT "tag_followers".* FROM "tag_followers" AS "tag_followers" WHERE ("tag_followers"."tag_id" = 3) AND ("tag_followers"."author_id" = 1) LIMIT 1;
SELECT "tags".* FROM "tags" AS "tags" WHERE "tags"."id" IN (3);
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" IN (1);
SELECT "tag_followers".* FROM "tag_followers" AS "tag_followers" WHERE ("tag_followers"."author_id" = 1) AND ("tag_followers"."tag_id" = 3);
SELECT "tag_followers".* FROM "tag_followers" AS "tag_followers" WHERE ("tag_followers"."author_id" = 1) AND ("tag_followers"."tag_id" = 3) LIMIT 1;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SELECT "tag_followers".* FROM "tag_followers" AS "tag_followers" WHERE ("tag_followers"."author_id", "tag_followers"."tag_id") IN ((1, 3));
SELECT "tag_followers".* FROM "tag_followers" AS "tag_followers" WHERE ("tag_followers"."author_id", "tag_followers"."tag_id") IN ((1, 3)) LIMIT 1;
SELECT "tags".* FROM "tags" AS "tags" WHERE "tags"."id" IN (3);
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" IN (1);
SELECT "tag_followers".* FROM "tag_followers" AS "tag_followers" WHERE ("tag_followers"."author_id", "tag_followers"."tag_id") IN ((3, 1));
SELECT "tag_followers".* FROM "tag_followers" AS "tag_followers" WHERE ("tag_followers"."author_id", "tag_followers"."tag_id") IN ((3, 1)) LIMIT 1;
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ SELECT CURRVAL('public.publishers_publisher_id_seq');
INSERT INTO "books" ("title", "author_id", "translator_id", "next_part", "ean_id", "publisher_id", "genre", "published_at", "printed_at", "thread_id", "price", "price_currency", "orig_price_cents", "orig_price_currency") VALUES ('Book 6', 3, NULL, NULL, NULL, 4, 'fantasy', '2021-12-14 21:10:02.000000'::timestamp, NULL, NULL, 150, 'CZK', NULL, NULL);
SELECT CURRVAL('public.books_id_seq');
COMMIT;
SELECT "books".* FROM "books" AS "books" WHERE "books"."title" = 'Book 6';
SELECT "books".* FROM "books" AS "books" WHERE "books"."title" = 'Book 6' LIMIT 1;
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ INSERT INTO "books" ("title", "author_id", "translator_id", "next_part", "ean_id
SELECT CURRVAL('public.books_id_seq');
UPDATE "books" SET "genre" = 'romance' WHERE "id" = 5;
COMMIT;
SELECT "books".* FROM "books" AS "books" WHERE "books"."title" = 'Book 5';
SELECT "books".* FROM "books" AS "books" WHERE "books"."title" = 'Book 5' LIMIT 1;
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
START TRANSACTION;
INSERT INTO "time_series" ("date", "value") VALUES ('2022-03-06 03:03:03.000000'::timestamptz, 3);
COMMIT;
SELECT "time_series".* FROM "time_series" AS "time_series" WHERE "time_series"."date" = '2022-03-06 03:03:03.000000'::timestamptz;
SELECT "time_series".* FROM "time_series" AS "time_series" WHERE "time_series"."date" = '2022-03-06 03:03:03.000000'::timestamptz LIMIT 1;
START TRANSACTION;
UPDATE "time_series" SET "value" = 5 WHERE "date" = '2022-03-06 03:03:03.000000'::timestamptz;
COMMIT;
SELECT "time_series".* FROM "time_series" AS "time_series" WHERE "time_series"."date" = '2022-03-06 03:03:03.000000'::timestamptz;
SELECT "time_series".* FROM "time_series" AS "time_series" WHERE "time_series"."date" = '2022-03-06 03:03:03.000000'::timestamptz LIMIT 1;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" = 1;
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" = 1 LIMIT 1;
SELECT "tag_followers".* FROM "tag_followers" AS "tag_followers" WHERE "tag_followers"."author_id" IN (1);
SELECT "authors".* FROM "public"."authors" AS "authors" WHERE "authors"."id" IN (1);
SELECT "tags".* FROM "tags" AS "tags" WHERE "tags"."id" IN (1);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
SELECT "tags".* FROM "tags" AS "tags" WHERE "tags"."id" = 1;
SELECT "tags".* FROM "tags" AS "tags" WHERE "tags"."id" = 2;
SELECT "tags".* FROM "tags" AS "tags" WHERE "tags"."id" = 1 LIMIT 1;
SELECT "tags".* FROM "tags" AS "tags" WHERE "tags"."id" = 2 LIMIT 1;
Loading