PHPackages                             vimeo/php-mysql-engine - 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. [Testing &amp; Quality](/categories/testing)
4. /
5. vimeo/php-mysql-engine

ActiveLibrary[Testing &amp; Quality](/categories/testing)

vimeo/php-mysql-engine
======================

A MySQL engine written in PHP for speeding up tests

0.7.14(7mo ago)560257.6k↓14%49[10 PRs](https://github.com/vimeo/php-mysql-engine/pulls)1MITPHPPHP ^7.1|^8CI passing

Since Feb 1Pushed 7mo ago22 watchersCompare

[ Source](https://github.com/vimeo/php-mysql-engine)[ Packagist](https://packagist.org/packages/vimeo/php-mysql-engine)[ RSS](/packages/vimeo-php-mysql-engine/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (5)Versions (34)Used By (1)

PHP MySQL Engine
================

[](#php-mysql-engine)

PHP MySQL Engine is a library for PHP that allows you to test database-driven applications with an in-memory simulation of MySQL 5.6. This project extends the `PDO` class and allows you to call common PDO MySQL methods. It supports a wide variety of queries, and some PDO-specific functionality like transactions and different fetch modes.

PHP MySQL Engine is based on Slack's [Hack SQL Fake](https://github.com/slackhq/hack-sql-fake) created by [Scott Sandler](https://github.com/ssandler).

You can read an article about this tool [here](https://medium.com/vimeo-engineering-blog/the-great-pretender-faster-application-tests-with-mysql-simulation-26250f13d251).

Motivation
----------

[](#motivation)

Currently there are two ways to test code that reads and writes to a database:

- Mock SQL query execution
    Mocks require an explicit list of queries that are expected to run and results to return. This leads to significant manual work setting up expectations, and tests which are fragile and must be updated even on benign changes to the code or queries. It also means the data access layer is not unit tested.
- Use an actual database
    It might make sense to test with a separate database instance – this is what we have done in the past at Vimeo. But databases like MySQL are designed to be filled with lots of long-lasting data, whereas unit tests write small amounts of very short-lived data. This means that extra care has to be taken to make sure that test databases are truncated between tests, which creates a performance issue.

PHP MySQL Engine takes a different approach - it parses and executes `SELECT`, `INSERT`, `UPDATE`, and `DELETE` queries against an in-memory "database" stored in PHP arrays. As long as the amount of data used for testing is small, this solves the problems mentioned above.

SQL Syntax Supported
--------------------

[](#sql-syntax-supported)

This library supports a wide variety of query syntax, including:

- `FROM`, `WHERE`, `GROUP BY`, `HAVING`, `ORDER BY`, `LIMIT` clauses supported as appropriate for each query type
- `JOIN` queries with all join types
- multi-queries such as subqueries, `UNION`, `UNION ALL`, `INTERSECT`, `EXCEPT`
- complex expressions such as `CASE`, `BETWEEN`, and row comparators `(1, 2, 3) < (4, 5, 6)`
- all basic operators implemented with operator precedence
- column aliases, cross-database queries
- `INSERT ... ON DUPLICATE KEY UPDATE`
- A variety of SQL functions such as `COUNT(), NULLIF(), COALESCE(), CONCAT_WS()` and many others
- Temporary variables like `@previous_name := user.name`
- Validating parser: the query parser will throw exceptions on most invalid SQL Queries, helping protect your production environment from accidental SQL syntax errors

Unsupported MySQL features
--------------------------

[](#unsupported-mysql-features)

This engine does *not* support [MySQL Stored objects](https://dev.mysql.com/doc/refman/5.6/en/stored-objects.html), which precludes the testing of stored procedures, triggers and views.

Caveat Emptor
-------------

[](#caveat-emptor)

Unlike [Psalm](https://github.com/vimeo/psalm), this package is not designed with a wide audience in mind. For a project to really benefit from this library it should already have a large number of tests that require a database connection to complete, and the project maintainers must understand the tradeoffs associated with using an unofficial MySQL implementation in their test suite.

Known issues
------------

[](#known-issues)

### Result types when not emulating prepares

[](#result-types-when-not-emulating-prepares)

By default the engine returns all data formatted as a string. If `$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false)` is called, the engine will instead infer column types (for example, `SUM(some_int_column)` will be given an `int` type). In some cases `php-mysql-engine` may do a better job of inferring correct column types than actual MySQL, which defaults to string when it can’t work out a column type. If you do strict type checks on the results you may see small discrepancies.

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

[](#installation)

```
composer require --dev vimeo/php-mysql-engine

```

Usage
-----

[](#usage)

PHP MySQL Engine works by providing a subclass of [PDO](https://www.php.net/manual/en/class.pdo.php).

You can instantiate the subclass as you would `PDO`, and use dependency injection or similar to provide that instance to your application code.

```
// use a class specific to your current PHP version (APIs changed in major versions)
$pdo = new \Vimeo\MysqlEngine\Php8\FakePdo($dsn, $user, $password);
// currently supported attributes
$pdo->setAttribute(\PDO::ATTR_CASE, \PDO::CASE_LOWER);
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
```

The rest of your code can operate as normal, using the database in the same way it is used in production.

Why doesn't it support X?
-------------------------

[](#why-doesnt-it-support-x)

This library aims to support everything its users use in MySQL, rather than every possibly feature MySQL offers. We welcome pull requests to add support for new syntax, sql functions, data types, bug fixes, and other features.

Why doesn’t this project have an issue tracker?
-----------------------------------------------

[](#why-doesnt-this-project-have-an-issue-tracker)

Maintaining open-source projects is hard work, and I don't want to make more work for me or my colleagues. Use this project very much use at your own risk.

If you want to fork the project with an issue tracker, feel free!

Contributing
------------

[](#contributing)

If you want to create a PR, please make sure it passes unit tests:

```
vendor/bin/phpunit

```

and also Psalm's checks

```
vendor/bin/psalm

```

Thanks!

###  Health Score

52

—

FairBetter than 96% of packages

Maintenance62

Regular maintenance activity

Popularity56

Moderate usage in the ecosystem

Community33

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 72% 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 ~62 days

Recently: every ~0 days

Total

28

Last Release

235d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/37a992956f2ceb043547091360fe71dacdd2b227d5450e7022b2a53660ba4e44?d=identicon)[muglug](/maintainers/muglug)

---

Top Contributors

[![muglug](https://avatars.githubusercontent.com/u/2292638?v=4)](https://github.com/muglug "muglug (249 commits)")[![aaronm67](https://avatars.githubusercontent.com/u/727029?v=4)](https://github.com/aaronm67 "aaronm67 (16 commits)")[![zonuexe](https://avatars.githubusercontent.com/u/822086?v=4)](https://github.com/zonuexe "zonuexe (9 commits)")[![Javakky-pxv](https://avatars.githubusercontent.com/u/71240288?v=4)](https://github.com/Javakky-pxv "Javakky-pxv (8 commits)")[![rtm-ctrlz](https://avatars.githubusercontent.com/u/4123596?v=4)](https://github.com/rtm-ctrlz "rtm-ctrlz (7 commits)")[![M1ke](https://avatars.githubusercontent.com/u/1226123?v=4)](https://github.com/M1ke "M1ke (6 commits)")[![sergiosalvatore](https://avatars.githubusercontent.com/u/33263?v=4)](https://github.com/sergiosalvatore "sergiosalvatore (6 commits)")[![1okey](https://avatars.githubusercontent.com/u/14160204?v=4)](https://github.com/1okey "1okey (4 commits)")[![cfebs](https://avatars.githubusercontent.com/u/302375?v=4)](https://github.com/cfebs "cfebs (4 commits)")[![dmitr1y](https://avatars.githubusercontent.com/u/12126090?v=4)](https://github.com/dmitr1y "dmitr1y (4 commits)")[![hedyyytang](https://avatars.githubusercontent.com/u/102314608?v=4)](https://github.com/hedyyytang "hedyyytang (4 commits)")[![staabm](https://avatars.githubusercontent.com/u/120441?v=4)](https://github.com/staabm "staabm (4 commits)")[![tarasom](https://avatars.githubusercontent.com/u/1064620?v=4)](https://github.com/tarasom "tarasom (4 commits)")[![kojirock5260](https://avatars.githubusercontent.com/u/6925110?v=4)](https://github.com/kojirock5260 "kojirock5260 (3 commits)")[![MelechMizrachi](https://avatars.githubusercontent.com/u/1179171?v=4)](https://github.com/MelechMizrachi "MelechMizrachi (2 commits)")[![dineshkrishnan24](https://avatars.githubusercontent.com/u/49274454?v=4)](https://github.com/dineshkrishnan24 "dineshkrishnan24 (2 commits)")[![villfa](https://avatars.githubusercontent.com/u/2891564?v=4)](https://github.com/villfa "villfa (2 commits)")[![Kenneth-Sills](https://avatars.githubusercontent.com/u/132029135?v=4)](https://github.com/Kenneth-Sills "Kenneth-Sills (2 commits)")[![Rarst](https://avatars.githubusercontent.com/u/737584?v=4)](https://github.com/Rarst "Rarst (1 commits)")[![charrondev](https://avatars.githubusercontent.com/u/1770056?v=4)](https://github.com/charrondev "charrondev (1 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/vimeo-php-mysql-engine/health.svg)

```
[![Health](https://phpackages.com/badges/vimeo-php-mysql-engine/health.svg)](https://phpackages.com/packages/vimeo-php-mysql-engine)
```

###  Alternatives

[phpspec/prophecy

Highly opinionated mocking framework for PHP 5.3+

8.5k551.7M682](/packages/phpspec-prophecy)[brianium/paratest

Parallel testing for PHP

2.5k118.8M754](/packages/brianium-paratest)[beberlei/assert

Thin assertion library for input validation in business models.

2.4k96.9M570](/packages/beberlei-assert)[mikey179/vfsstream

Virtual file system to mock the real file system in unit tests.

1.4k108.0M2.7k](/packages/mikey179-vfsstream)[orchestra/testbench

Laravel Testing Helper for Packages Development

2.2k39.1M32.1k](/packages/orchestra-testbench)[phpspec/phpspec

Specification-oriented BDD framework for PHP 7.1+

1.9k36.7M3.1k](/packages/phpspec-phpspec)

PHPackages © 2026

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