Proposal: PdoProviderInterface (PSR for providing PDO connections)

67 views
Skip to first unread message

Maxime Gosselin

unread,
Mar 11, 2026, 2:26:08 PM (2 days ago) Mar 11
to PHP Framework Interoperability Group

Hi,

I would like to propose a new PSR standardizing how PDO connections are provided between libraries.

The problem has two sides. First, passing a \PDO instance directly surrenders control over the connection lifecycle: the caller loses the ability to control when and how the connection is opened, verified, or recreated. Second, there is no standardized contract for passing a connection between libraries. Widely-used libraries such as doctrine/dbal, illuminate/database, nette/database, and cakephp/database each wrap PDO in their own connection object, with no common interface.

The proposed interface is intentionally minimal, modeled after PSR-20's ClockInterface:

==========
namespace Psr\Pdo;

interface PdoProviderInterface
{
    public function getConnection(): \PDO;
}
==========

Draft PR: https://github.com/php-fig/fig-standards/pull/1348

Background: https://maximegosselin.com/posts/proposing-a-psr-for-pdo-providers/

I intend to reach out to the Doctrine DBAL maintainers in the near future to gauge their interest.

I am looking for a sponsor and working group members.

Regards,
Maxime Gosselin

Matteo Beccati

unread,
Mar 12, 2026, 4:49:34 AM (yesterday) Mar 12
to php...@googlegroups.com
Hi Maxime,

Il 11/03/2026 19:06, Maxime Gosselin ha scritto:
> Draft PR: https://github.com/php-fig/fig-standards/pull/1348
>
> Background: https://maximegosselin.com/posts/proposing-a-psr-for-pdo-
> providers/
>
> I intend to reach out to the Doctrine DBAL maintainers in the near
> future to gauge their interest.
>
> I am looking for a sponsor and working group members.

Thanks for your proposal. I think that gauging the interest from DBAL
and a few other projects is key in order to find support and sponsors.

I personally have a few doubts on the usefulness of such interface being
maintained by FIG, but let's hear what their feedback is.



Cheers
--
Matteo

Paul Dragoonis

unread,
Mar 12, 2026, 4:54:49 AM (yesterday) Mar 12
to php...@googlegroups.com
I'm sharing the same position at Matteo.

My overall question is:
What is the impact of adding this PSR? and what's the current impact by not having it?





Cheers
--
Matteo

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/php-fig/22158d81-f778-4a2f-a119-fec5b136e492%40beccati.com.

Larry Garfield

unread,
Mar 12, 2026, 10:30:17 AM (yesterday) Mar 12
to PHP-FIG
Let me see if I'm following. The original discussion on Reddit was about a PdoInterface, which would be an Internals question and not something FIG would be involved in.

Now the proposal has shifted to effectively standardizing the "give me the connection you're already wrapping" operation that many but not all DBALs provide. The end goal is to allow an app to use Doctrine, Nette/Database, and Aura SQL all in one application, all wrapping the same PDO connection object.

(This is fundamentally different than what PSR-20 does, where every service is injected with a ClockInterface, and the clock is called repeatedly to get a timestamp value object. That's not at all the same as a way to extract one service dependency from another service.)

I can somewhat see where that would be beneficial, as opening multiple PDO connections to the DB in the same request causes all kinds of problems. However, I am not sure how wide a use case that is. Essentially every application I've seen has only a single DBAL, or it has a single DBAL plus legacy code using a raw PDO object. In neither case would being able to share the connection object between multiple DBALs be relevant.

Right now, this feels more like a theoretical improvement rather than one that addresses an extant problem in the ecosystem. Does anyone else have different experience?

--Larry Garfield

Maxime Gosselin

unread,
Mar 12, 2026, 12:40:39 PM (yesterday) Mar 12
to php...@googlegroups.com
Hi Larry (and all),

Sorry for the longer-than-usual reply, but I think a more complete answer now will help avoid misunderstandings down the road.


== On the PSR-20 parallel ==

I want to address your point about PSR-20 first, because I think there is a fundamental misunderstanding about what this interface is meant to share.

You described PdoProviderInterface as "a way to extract one service dependency from another service." That is not the intended use. The parallel with PSR-20 actually holds: just as every service that needs the current time is injected with a ClockInterface and calls now() repeatedly, every service that needs a database connection would be injected with a PdoProviderInterface and calls getConnection() each time it needs one. What is shared between services is the interface, not a \PDO instance. The provider behind the interface decides what getConnection() returns. It could be a lazy singleton, a reconnected instance, or a pooled connection. That is exactly the point.


== On why PdoProviderInterface and not PdoInterface ==

This also addresses a question raised by Alexander Makarov in the PR "Does it have to be bound to PDO?" (https://github.com/php-fig/fig-standards/pull/1348#issuecomment-4040272736)

The short answer is yes, and deliberately so. Early in my thinking I considered a PdoInterface that would mirror \PDO's full API. That approach touches PHP internals and RFC territory. It would also tightly couple the standard to PDO's own method signatures, which is a moving target. A single getConnection(): \PDO keeps the contract minimal and stable. \PDO is the only de facto standard for relational database access in PHP. This interface simply formalizes how you get access to it, not what it exposes.


== The real problem: library authors ==

With that in mind, the problem is better described as: a library should be able to benefit from another library's connection infrastructure without coupling itself to it.

If I write a query builder or an event store library, my options today are:

1. Accept a raw \PDO -- simple, but I lose lazy-connect, auto-reconnect, and pooling
2. Depend on Doctrine DBAL -- I get those benefits, but I force that dependency on everyone using my library
3. Ship adapters for Doctrine, Laravel, Nette, etc. -- I get interoperability, but I maintain N adapters forever
4. Invent my own contract -- which is what I ended up doing

PdoProviderInterface would be the missing fifth option: depend on a minimal contract, and let the consuming application plug in whichever DBAL manages the connection.


== Concrete examples from my own work ==

In Backslash PHP (the event sourcing framework I maintain), I had to invent my own PdoInterface and a PdoProxy wrapper just to support lazy-connect. A standard interface would have solved that problem. You can see it here:
https://backslashphp.github.io/docs/application-setup/defining-services/#configuring-the-pdo-connection

I also maintain an internal enterprise application (Horizon) that has grown over the years to include Laravel, Doctrine DBAL for migrations, FluentPDO for query building, and other components depending on raw PDO. Each manages or consumes a connection independently. PdoProviderInterface would be the common thread letting all of them share the same managed connection. I cannot make this codebase public, but I suspect it is not an unusual situation for applications that have evolved organically.


== Supporting research ==

To support this proposal with more than anecdotes, I put together a research repository that examines how 10 popular PHP database libraries handle connection creation, injection, and exposure:
https://github.com/maximegosselin/pdo-provider-research

It maps out the disparities between libraries and their readiness to adopt PdoProviderInterface. The patterns are consistent enough to suggest the problem is real, even if the solutions today are fragmented.

----------

I would be curious to hear from other library authors and from maintainers of applications that have grown beyond a single DBAL. This might be a problem that is common but invisible because everyone solves it in isolation.

Regards,
Maxime Gosselin

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.

Matteo Beccati

unread,
Mar 12, 2026, 1:44:39 PM (yesterday) Mar 12
to php...@googlegroups.com
Hi,

Il 12/03/2026 17:40, Maxime Gosselin ha scritto:
> In Backslash PHP (the event sourcing framework I maintain), I had to
> invent my own PdoInterface and a PdoProxy wrapper just to support lazy-
> connect. A standard interface would have solved that problem. You can
> see it here:
> https://backslashphp.github.io/docs/application-setup/defining-services/
> #configuring-the-pdo-connection <https://backslashphp.github.io/docs/
> application-setup/defining-services/#configuring-the-pdo-connection>
>
> I also maintain an internal enterprise application (Horizon) that has
> grown over the years to include Laravel, Doctrine DBAL for migrations,
> FluentPDO for query building, and other components depending on raw PDO.
> Each manages or consumes a connection independently. /
> PdoProviderInterface/ would be the common thread letting all of them
> share the same managed connection. I cannot make this codebase public,
> but I suspect it is not an unusual situation for applications that have
> evolved organically.

I personally think this is a very specific problem of your application
that can be solved with an ad-hoc solution and/or through DI.


Cheers
--
Matteo Beccati

Ralf Lang

unread,
Mar 12, 2026, 1:49:38 PM (yesterday) Mar 12
to php...@googlegroups.com
Hello Maxime, Larry et al...

I am reading this with interest but I wonder if this is actually a problem looking for a solution or the other way around.

If the use case is: Multiple frameworks share a DB connection object
then my solution would be to maintain the created DB Connection (PDO or otherwise) in a caching factory, injector with instance reuse or whatever and simply inject it into multiple framework DBALs.

But I begin to understand this is not the complete intent here. Is Pdo actually a good name? A couple of the DB drivers I deal with aren't really PDO-native. What do I win if the interface is limited to providing the DB object and then I am left with the bare thing? Also in my experience having multiple managers on the same handle isn't a good idea. DB connections are not stateless. Advanced work with relational DBs includes atomic transactions - I don't want a stranger with his own needs interact with my transaction in progress. There are cases which might benefit but it's a headache to debug once things go wrong.

Just saying.
 

Jaap van Otterdijk

unread,
Mar 12, 2026, 2:35:28 PM (yesterday) Mar 12
to PHP Framework Interoperability Group
Hi,

I was reading this proposal, and the first thing I thought, this makes a bit of sense. However the underlying problem might be a bit broader. 

Pdo is just one database driver. And while it's the main standard there is also still mysqli, and maybe some connections I'm not aware of. So an interface that just functions as a "pdo connection factory" is form my point of view a bit to small. Maybe the real power is unleashed when we come up with a database connection interface and an interface for factories that allows dbals to share connections. 

Having this said, I also recognize the point of an edge case. But I have also seen applications that would have benefited from an easier way to pool connections between different dbals. But only on migration paths. Maybe frameworks would benefit form an interface, but than again I'm searching for a problem rather than knowing the issue. 

For me to get this psr proposal started I would like to see some more data on how many people see this as an issue. Not just the people in this mailinglist. But people maintaining an application/framework/dbal who are dealing with the issue to interface with different database layers.

Regards
Jaapio

Op do 12 mrt 2026 18:49 schreef Ralf Lang <ralf...@gmail.com>:

Alexander Makarov

unread,
Mar 12, 2026, 6:21:06 PM (yesterday) Mar 12
to PHP Framework Interoperability Group
> \PDO is the only de facto standard for relational database access in PHP. 

That is not true. First of all, there are non-PDO drivers. Second, there are async drivers such as https://amphp.org/postgres.

Because modern frameworks can work in event loop mode, the connection interface should not be strictly bound to PDO.

Maxime Gosselin

unread,
Mar 12, 2026, 10:03:48 PM (yesterday) Mar 12
to PHP Framework Interoperability Group
Hi all,
 
A few responses to the recent feedback.
 
@Alexander:
I am not sure I follow the connection between event loop support and ConnectionInterface, which looks like a standard synchronous DBAL contract to me. Could you clarify?
 
About non-PDO drivers, you are right that they exist. The scope of this proposal is deliberately limited to PDO, which is the standard used internally by the large majority of PHP database libraries, including yiisoft/db itself. I have added yiisoft/db to the research repository: https://github.com/maximegosselin/pdo-provider-research
 
@Ralf:
The transaction concern is valid, but it is not specific to this proposal. Any application that shares a PDO instance between components faces the same risk today, with or without a standard interface. PdoProviderInterface does not introduce that problem. Managing transaction boundaries across components is already the developer's responsibility.
 
@Matteo, @Ralf, @Jaap:
On the "solution looking for a problem" concern: I understand the skepticism. But consider this: 10 out of 11 libraries in the research repo already expose the underlying PDO, each with a different method name -- getPdo(), getNativeConnection(), getActivePDO(), getResource(). This pattern already exists in the wild and standardizing it is the point.
 
Where I agree with you: whether the need to share a connection between libraries is common enough to justify a PSR is still an open question. My experience with Backslash and Horizon suggests it is a real problem, but I recognize that two examples are not enough.
 
@Jaap:
Your suggestion to gather more data from library and application maintainers is the right next step. If others on this list have faced this problem, I would genuinely like to hear about it. I will also reach out directly to the maintainers of the libraries in the research repo to get their feedback.
 
Regards,
Maxime Gosselin

Ralf Lang

unread,
12:54 AM (21 hours ago) 12:54 AM
to php...@googlegroups.com
The PDO interface supports the common ground among databases but it doesn't provide access to advanced features. The OCI8 driver has active oracle support and multiple features the PDO equivalent doesn't have. With mysql/maria the gap is much closer between the two choices because they are backed by the same low level driver.

Alex Makarov

unread,
5:46 AM (16 hours ago) 5:46 AM
to php...@googlegroups.com
> I am not sure I follow the connection between event loop support and ConnectionInterface, which looks like a standard synchronous DBAL contract to me. Could you clarify?

Yes. An async framework needs a non-blocking DB driver. PDO is blocking (except if you install Swoole; it replaces the PDO implementation transparently). That usually means that non-PDO driver will be used. Considering True Async RFC, raise of FrankenPHP etc. I think that's a good move to create an interface that isn't PDO-bound.

In yiisoft/db drivers are, indeed, PDO-based but we want interfaces to be PDO-agnostic: https://github.com/yiisoft/db/issues/1149

Reply all
Reply to author
Forward
0 new messages