hoyvoy / laravel-cross-database-subqueries

Eloquent cross database compatibility in subqueries
MIT License
103 stars 45 forks source link

Add POC for cross-server whereHas/whereDoesntHave #17

Open mortenscheel opened 4 years ago

mortenscheel commented 4 years ago

Hi. I just learned about cross-database whereHas earlier today. I always assumed that it was impossible, so it was a nice surprise. But I was quickly disappointed when I realized it only works when the database connections are on the same server. I mean, it's kind of obvious that it has to be that way, but I had hoped I could use it in a project where I get Users from an old remote WordPress server (using Corcel).

Just for fun I tried messing around with the QueryBuilder, and I think I might have found a workaround to perform whereHas queries on relationships that are on a completely separate DB servers. But it's the first time I've ever hacked on the QueryBuilder, so I might have broken stuff that I'm not even aware of. ...So I decided to write this PR with a proof of concept, hoping that you could maybe take a look and see if it would make sense to continue working on it, and eventually merge it into your package?

The way it works is quite simple. In the Builder::has() method, I check if the two models are hosted on different servers. If they are, using a subquery won't work, so in stead of calling your addHasWhere(), I perform a workaround:

  1. Execute a separate query on the related model to obtain ids (matching the whereHas callback if one is provided).
  2. Return a new QueryBuilder where the foreign key must be one of the ids found in step 1 (or not, in case of doesntHave(), in which case null values are also allowed).

I realize this hack doesn't scale very well, but I don't know - maybe it's better than nothing.