# catfan/Medoo: a single-file PHP database layer for MySQL, PostgreSQL and SQLite

> Medoo wraps PDO in a small PHP class with a query-builder API. It suits small PHP apps that want readable SQL without a full ORM, and it is a poor fit for teams that need migrations, relations and lazy loading.

**catfan/Medoo** — The lightweight PHP database framework to accelerate the development.

- Repository: https://github.com/catfan/Medoo
- Website: https://medoo.in
- Stars: 4,953 · Forks: 1,129
- Language: PHP
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/catfan-medoo

## The problem Medoo solves: PDO without the boilerplate

Raw PDO in PHP means writing a SQL string, preparing it, binding each parameter, executing, and then fetching in the shape you actually want. That is fine for one query and tedious for fifty. Medoo keeps PDO underneath but replaces the string-and-bind cycle with method calls that take a table name, a column list and a condition array. The README describes it as "a lightweight single-file package that keeps dependencies to a minimum", and that is the whole pitch: you get a query builder, not a framework.

The audience is narrow and identifiable. It is a PHP developer on a small application, a script, an internal tool or a legacy codebase where adding Doctrine or Eloquent would mean adopting an entity model, a configuration layer and a migration system at the same time. Medoo asks for PHP 7.3 or later and the PDO extension, and nothing else. If your data model is tables and rows rather than objects and graphs, the abstraction matches the way you already think.

## How the query API maps onto PDO

A Medoo instance holds a connection and exposes methods named after SQL verbs. The README's example uses insert and select. The first argument is the table, the second is the column list, and the third is a where-style condition array. Values in that array become bound parameters rather than string concatenation, which is the mechanism that keeps the common case safe from injection.

The condition arrays are where the design earns its keep. The related searches include "Medoo between", which points at the operator syntax: instead of a plain equality array, you pass a nested array with an operator name and a value, and the builder emits the corresponding SQL clause. This is the part worth reading the documentation for, because the same array shape is reused across select, update and delete, so learning it once covers most of the API.

Multi-engine support is handled by the type key in the constructor. The README lists MySQL, MariaDB, PostgreSQL, SQLite, MSSQL, Oracle and Sybase. That breadth is real but it is also the source of the project's testing burden: the contribution guidelines ask that a pull request be checked against multiple database engines, which tells you the maintainers treat portability as a per-change obligation rather than a settled property. The repository carries phpstan.neon.dist and phpstan-tests.neon.dist at the top level, and the v2.6.0 release is titled "PHPStan Level 10", so static analysis is part of the release process rather than an afterthought.

## Installing Medoo with Composer and running a first query

Installation goes through Composer. The README gives the require command directly:

```bash
composer require catfan/medoo
```

It then notes that you run composer update afterwards. In a fresh project the require step is usually enough, but the README lists both, so follow it if your composer.json already pins other packages.

Once the package is in vendor, the autoloader and the Medoo namespace are all you need. The constructor takes an array whose type key selects the driver, and the rest of the keys are connection parameters:

```php
require 'vendor/autoload.php';

use Medoo\Medoo;

$database = new Medoo([
    'type' => 'mysql',
    'host' => 'localhost',
    'database' => 'name',
    'username' => 'your_username',
    'password' => 'your_password'
]);
```

With the connection open, an insert and a select look like this, taken from the README's own example:

```php
$database->insert('account', [
    'user_name' => 'foo',
    'email' => 'foo@bar.com'
]);

$data = $database->select('account', [
    'user_name',
    'email'
], [
    'user_id' => 50
]);
```

The select call returns an array of rows, which the README serialises with json_encode. If you run this against an empty account table you get an empty JSON array, not an error, so an empty result and a broken query are not distinguished by the return value alone. Check the error accessor on the instance when a result looks wrong.

For SQLite the same constructor shape applies with type set to sqlite and a file path in place of host and credentials. That is the fastest way to try the API without provisioning a server.

## Where Medoo stops, and why that matters

Medoo is not an ORM and the README never claims otherwise. There is no entity class, no relationship declaration, no lazy loading, and no migration tool in the repository layout: the top level holds src/, tests/, the PHPStan and PHPUnit configuration files, and the code-style config. Schema changes are your problem, managed by hand or by whatever migration tool you bring.

That has a practical consequence. As soon as a query needs a window function, a recursive CTE, a vendor-specific hint or a carefully tuned join order, you leave the array API and write SQL. The README's feature list mentions being "designed for complex SQL, data mapping, and prepared statements", so raw SQL is an intended escape hatch rather than a failure. But the further your application drifts toward analytical queries, the more the builder becomes a wrapper you pass through rather than a tool you use.

The second limitation is the portability promise itself. Supporting eight engines from one API means the lowest common denominator shapes the generated SQL, and engine-specific behaviour has to be handled case by case. The contribution guidelines asking for multi-engine compatibility checks are a direct signal that this is ongoing work, not a guarantee you can assume. If you commit to Medoo on MySQL today and plan to move to MSSQL next year, treat that move as a testing project, not a configuration change.

## Medoo compared with a full ORM such as Doctrine or Eloquent

The real alternative for most PHP teams is a full ORM. Doctrine DBAL sits closer to Medoo in spirit: a database abstraction layer with a query builder, no entity mapping unless you add the ORM on top. Eloquent goes the other way, binding tables to model classes and giving you relationships, accessors and events.

The difference is what you write. With Eloquent you define a model class per table and then query through it, so the mapping is declared once and reused. With Medoo you write the table name at every call site. That is less ceremony for a handful of tables and more repetition for thirty. In exchange, Medoo never hides the query: what you pass in is close to what runs, and there is no identity map or change-tracking layer between your code and the database.

If your application already lives inside Laravel or Symfony, adopting Medoo means running a second data-access path alongside the framework's own, which is usually a worse trade than picking one. Medoo's README does say it fits naturally into Laravel, CodeIgniter, Yii and Slim, and that is true at the technical level, but fitting into a framework and belonging to it are different things.

## Maintenance, licence and what an upgrade costs

The repository is not archived, and the last push was on 2026-08-22, which coincides with the v2.6.0 release. The two releases before it, v2.5.0 and v2.4.0, landed on 2026-07-13 and 2026-05-14. The release titles are descriptive rather than cosmetic: v2.4.0 is labelled "Improve Performance", v2.5.0 "Compatibility", and v2.6.0 "PHPStan Level 10". That last one matters for upgrade cost, because raising the static analysis level can surface type errors in code that previously passed, and it signals that the public API is being held to a stricter contract over time.

The licence is MIT, stated in the README and present as LICENSE.md at the repository root. MIT permits commercial and personal use, modification and redistribution with the copyright notice retained. That is the extent of what the repository tells you; it is not legal advice, and if you redistribute Medoo inside a product you should read LICENSE.md yourself rather than a summary.

Upgrade cost is low by construction. There is no migration to run against your own database when you bump the library, and no generated code to regenerate. The risk sits in the API surface and in engine behaviour: a change to how condition arrays are interpreted, or to the SQL emitted for a given engine, is the kind of thing that shows up as a failing query rather than a failing build. The tests directory and the PHPUnit configuration mean the project tests itself, not your application.

## Conclusion

Adopt Medoo when you are writing a small or mid-sized PHP service and want parameterised queries without an ORM, and when your team is comfortable reading raw SQL for anything the API does not cover. Do not adopt it if you expect schema migrations, relationship mapping or lazy loading; the README lists none of those, and its feature list is about query construction and engine compatibility. Before committing, verify two things in your own environment: that the PDO driver for your engine is enabled, since the README states PDO is a requirement, and that every query you plan to run is expressible through the array API or through the raw query path, because that boundary decides how much SQL you end up writing by hand.

## FAQ

### What is Medoo in PHP?

Medoo is a lightweight PHP database framework that wraps PDO in a query-builder API. The README describes it as a single-file package with minimal dependencies, supporting MySQL, MariaDB, PostgreSQL, SQLite, MSSQL, Oracle, Sybase and others.

### How do I install Medoo?

Install it with Composer using composer require catfan/medoo, then run composer update as the README instructs. It needs PHP 7.3 or later and the PDO extension enabled.

### What databases does Medoo support?

The README lists MySQL, MariaDB, PostgreSQL, SQLite, MSSQL, Oracle and Sybase. The engine is chosen with the type key in the constructor array.

### Does Medoo handle database migrations?

No. The README and the repository layout show no migration tool, so schema changes are managed by you or by a separate tool. Medoo covers query construction, not schema management.

## Sources

- [catfan/Medoo on GitHub](https://github.com/catfan/Medoo)
- [License: MIT](https://github.com/catfan/Medoo/blob/master/LICENSE)
- [Project website](https://medoo.in)
- [README](https://github.com/catfan/Medoo/blob/master/README.md)
- [Releases](https://github.com/catfan/Medoo/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/catfan-medoo
