Skip to content
Merged
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
78 changes: 78 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: CI

on:
push:
branches: ["main", "master"]
pull_request:

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: ["8.3", "8.4"]
db: ["mysql", "postgres"]

services:
mysql:
image: mariadb:10.11
ports:
- "3306:3306"
env:
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
postgres:
image: postgres:16
ports:
- "5432:5432"
env:
POSTGRES_DB: categorytest
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres

steps:
- uses: actions/checkout@v4

- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: pdo, pdo_mysql, pdo_pgsql

- name: Install dependencies
run: composer install --no-interaction --no-progress

- name: Static analysis
run: vendor/bin/phpstan analyse -c phpstan.neon

- name: Format check
run: vendor/bin/php-cs-fixer fix --dry-run --diff

- name: Configure DB env
run: |
if [ "${{ matrix.db }}" = "mysql" ]; then
echo "MODEL_ORM_TEST_DSN=mysql:host=127.0.0.1;port=3306" >> "$GITHUB_ENV"
echo "MODEL_ORM_TEST_USER=root" >> "$GITHUB_ENV"
echo "MODEL_ORM_TEST_PASS=" >> "$GITHUB_ENV"
else
echo "MODEL_ORM_TEST_DSN=pgsql:host=127.0.0.1;port=5432;dbname=categorytest" >> "$GITHUB_ENV"
echo "MODEL_ORM_TEST_USER=postgres" >> "$GITHUB_ENV"
echo "MODEL_ORM_TEST_PASS=postgres" >> "$GITHUB_ENV"
fi

- name: Wait for database
run: |
if [ "${{ matrix.db }}" = "mysql" ]; then
for i in {1..30}; do
nc -z 127.0.0.1 3306 && break
sleep 1
done
else
for i in {1..30}; do
nc -z 127.0.0.1 5432 && break
sleep 1
done
fi

- name: Run tests
run: vendor/bin/phpunit -c phpunit.xml.dist
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
### Composer template
composer.phar
/vendor/
.phpunit.cache
.php-cs-fixer.cache

# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
Expand Down Expand Up @@ -60,4 +62,3 @@ composer.phar
# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
# composer.lock

18 changes: 18 additions & 0 deletions .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

$finder = PhpCsFixer\Finder::create()
->in([
__DIR__ . '/src',
__DIR__ . '/tests',
__DIR__ . '/test-src',
])
->name('*.php')
->ignoreDotFiles(true)
->ignoreVCS(true);

return (new PhpCsFixer\Config())
->setRiskyAllowed(false)
->setRules([
'@PSR12' => true,
])
->setFinder($finder);
38 changes: 38 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Repository Guidelines

## Project Structure & Module Organization
- `src/` holds the library source (primary entry: `src/Model/Model.php`) under the `Freshsauce\\` namespace.
- `tests/` contains PHPUnit tests (e.g., `tests/Model/CategoryTest.php`).
- `test-src/` provides example models used by tests (`App\\` namespace).
- Root config files: `composer.json`, `phpunit.xml.dist`, and `docker-compose.yml`.

## Build, Test, and Development Commands
- `composer install` installs dependencies (PHP >= 8.3, `ext-pdo`, PHPUnit 10).
- `vendor/bin/phpunit -c phpunit.xml.dist` runs the test suite.
- `vendor/bin/phpstan analyse -c phpstan.neon` runs static analysis.
- `vendor/bin/php-cs-fixer fix` formats the codebase (use `--dry-run --diff` in CI).
- `docker-compose up -d` starts local MariaDB and PostgreSQL instances (ports 3306 and 5432).

## Coding Style & Naming Conventions
- PHP code uses 4-space indentation and namespaces.
- Class names are `StudlyCaps` (e.g., `Model`, `CategoryTest`); methods are `camelCase`.
- Table config is set via static properties like `static protected $_tableName`.
- Follow PSR-4 autoloading (`Freshsauce\\` -> `src/`, `App\\` -> `test-src/`).

## Testing Guidelines
- PHPUnit 10 is the test runner; tests live in `tests/`.
- Test classes are named `*Test` and extend `PHPUnit\Framework\TestCase`.
- Tests can run against MySQL/MariaDB or PostgreSQL; configure via env vars:
- `MODEL_ORM_TEST_DSN` (e.g., `mysql:host=127.0.0.1;port=3306` or `pgsql:host=127.0.0.1;port=5432;dbname=categorytest`)
- `MODEL_ORM_TEST_USER`, `MODEL_ORM_TEST_PASS`
- MySQL tests create/drop `categorytest`; PostgreSQL tests create/drop the `categories` table.

## Commit & Pull Request Guidelines
- Commit messages in this repo are short, descriptive sentences (e.g., “Fix test”, “Scrutinizer adjustments”).
- Prefer imperative or present-tense summaries without a required prefix.
- PRs should include a concise description, testing notes (`vendor/bin/phpunit -c phpunit.xml.dist`), and any DB/setup changes.

## Configuration & Local Setup Tips
- Default test connection assumes MySQL on `127.0.0.1:3306` with `root`/empty password.
- For PostgreSQL, use the Docker defaults (`postgres`/`postgres`) and `dbname=categorytest`.
- Ensure ports `3306` and/or `5432` are free and reachable from PHP.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Changelog

## Unreleased
- Require PHP 8.3+ and modernize PHPUnit to 10.x.
- Add PostgreSQL compatibility alongside MySQL/MariaDB.
- Improve identifier quoting and driver-specific schema discovery.
- Update tests to support configurable DB backends.
- Add GitHub Actions CI matrix for PHP and database drivers.
29 changes: 29 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Contributing

Thanks for contributing to `model-orm-php`.

## Setup
- PHP 8.3+ with PDO and the driver you intend to test (`pdo_mysql` or `pdo_pgsql`).
- Install dependencies: `composer install`.
- Start local DBs (optional): `docker-compose up -d`.

## Tests
- Run: `vendor/bin/phpunit -c phpunit.xml.dist`.
- Use env overrides to target a DB:
- `MODEL_ORM_TEST_DSN` (e.g., `mysql:host=127.0.0.1;port=3306` or `pgsql:host=127.0.0.1;port=5432;dbname=categorytest`)
- `MODEL_ORM_TEST_USER`, `MODEL_ORM_TEST_PASS`

## Static Analysis
- Run: `vendor/bin/phpstan analyse -c phpstan.neon` (use `--debug` if your environment blocks parallel workers).

## Formatting
- Format: `vendor/bin/php-cs-fixer fix`.
- Check only: `vendor/bin/php-cs-fixer fix --dry-run --diff`.

## Code Style
- Keep changes minimal and consistent with existing conventions (4-space indent, `StudlyCaps` classes, `camelCase` methods).
- Update or add tests for behavior changes.

## Pull Requests
- Explain the change and include test results.
- Note any DB/schema assumptions and compatibility impacts.
34 changes: 28 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ PHP Model class which provides
* raw database queries with escaped parameters
* helpers for finding one or more records returning rows as instances of the Model class
* throws exception on query error
* Requires PHP >= 5.3
* Currenlty only tested with MySQL through the PDO drivers
* Requires PHP >= 8.3
* Supports MySQL/MariaDB and PostgreSQL via PDO

Usage
=====

With a mysql database as such on your localhost
With a MySQL database as such on your localhost

CREATE DATABASE categorytest;
CREATE TABLE `categories` (
Expand All @@ -30,13 +30,35 @@ With a mysql database as such on your localhost
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

require_once('vendor/autoload.php');
Db\Model::connectDb('mysql:dbname=categorytest;host=127.0.0.1','root',''); // db connection for all sub-classes
Freshsauce\Model\Model::connectDb('mysql:dbname=categorytest;host=127.0.0.1','root',''); // db connection for all sub-classes

// minimum model definition
class Category extends db\Model {
class Category extends Freshsauce\Model\Model {
static protected $_tableName = 'categories'; // database table name
}

PostgreSQL example schema and connection

CREATE TABLE categories (
id SERIAL PRIMARY KEY,
name VARCHAR(120) NULL,
updated_at TIMESTAMP NULL,
created_at TIMESTAMP NULL
);

Freshsauce\Model\Model::connectDb('pgsql:host=127.0.0.1;port=5432;dbname=categorytest','postgres','postgres');

Testing
=======

Run PHPUnit with optional environment overrides for the DB connection:

MODEL_ORM_TEST_DSN=mysql:host=127.0.0.1;port=3306
MODEL_ORM_TEST_USER=root
MODEL_ORM_TEST_PASS=

vendor/bin/phpunit -c phpunit.xml.dist

Save & Update records
=====================

Expand Down Expand Up @@ -176,4 +198,4 @@ date strings are parsed into a unix date via PHPs incredibly flexible strtotime(
db\Model::datetimeToMysqldatetime('2012 Sept 13th 12:00'); // returns '2012-09-13 12:00:00'
db\Model::datetimeToMysqldatetime('next Monday'); // returns next monday midnight in the format 'YYYY-MM-DD HH:MM:SS'
db\Model::datetimeToMysqldatetime(gmdate()); // returns the current date time in the format 'YYYY-MM-DD HH:MM:SS'


17 changes: 14 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "Freshsauce/Model",
"name": "freshsauce/model",
"type": "library",
"description": "PHP Model class",
"keywords": [
Expand All @@ -23,7 +23,7 @@
},
"require": {
"ext-pdo": "*",
"php" : ">=5.4"
"php" : ">=8.3"
},
"autoload": {
"psr-4": {
Expand All @@ -32,6 +32,17 @@
}
},
"require-dev": {
"phpunit/phpunit": "^5.4"
"phpunit/phpunit": "^10.5",
"phpstan/phpstan": "^1.11",
"friendsofphp/php-cs-fixer": "^3.50"
},
"suggest": {
"ext-pdo_mysql": "Required for MySQL/MariaDB support",
"ext-pdo_pgsql": "Required for PostgreSQL support"
},
"config": {
"platform": {
"php": "8.3.0"
}
}
}
Loading