This repository contains the idae.api PHP project — a lightweight REST / IDQL API backed by MongoDB, designed to run under the web/ document root. The codebase is organized around a router → API parser → query layer pattern and includes Docker helper scripts and test infrastructure (PHPUnit + Docker Compose).
Quick links
- Entrypoint: web/index.php
- Router: web/bin/classes/ClassRouter.php
- API dispatcher: web/bin/engine/Idae/Api/IdaeApiRest.php
- Query layer: web/bin/engine/Idae/Query/IdaeQuery.php
- Tests: web/bin/tests
- Docker compose: docker-compose.yml
The API exposes two main types of endpoints:
/api/idql/<scheme>— accepts an IDQL JSON payload describing DB operations (find, group, distinct, parallel, etc.)./api/*— generic REST paths routed toIdaeApiRest::doRest(); query params and JSON body are used depending on the HTTP method.
The project uses MongoDB as the datastore (via the mongodb/mongodb library and ext-mongodb) and contains a small Node helper process under web/bin/node for sockets/crons.
POST /api/idql/products
Request body (JSON):
{
"method": "find",
"scheme": "products",
"limit": 10,
"page": 0,
"where": {"status": "active"}
}Example curl call:
curl -X POST \
-H "Content-Type: application/json" \
-d '{"method":"find","scheme":"products","limit":10,"where":{"status":"active"}}' \
http://localhost:8081/api/idql/productsResponse format is JSON and depends on the parser output_method (commonly raw or raw_casted). See IdaeApiRest for envelope details.
This example demonstrates using parallel, group and distinct together in an IDQL POST to the /api/idql/<scheme> endpoint.
parallelrequest (two sub-queries:find+distinct)
Request (POST /api/idql/dashboard):
{
"parallel": [
{"method":"find","scheme":"users","limit":5,"where":{"active":1},"proj":{"idusers":1,"nomusers":1,"email":1}},
{"method":"distinct","scheme":"products","distinct":"category","where":{"status":"active"}}
],
"scheme": "dashboard"
}curl:
curl -X POST \
-H "Content-Type: application/json" \
-d '{"parallel":[{"method":"find","scheme":"users","limit":5,"where":{"active":1}},{"method":"distinct","scheme":"products","distinct":"category","where":{"status":"active"}}],"scheme":"dashboard"}' \
http://localhost:8081/api/idql/dashboardExpected response (raw envelope):
{
"rs": {
"0": [
{"idusers":123,"nomusers":"Dupont","email":"dupont@example.com"},
{"idusers":124,"nomusers":"Martin","email":"martin@example.com"}
],
"1": ["electronics","books","home"]
},
"options": { /* api options echoed */ },
"query": { /* parsed idql echo */ },
"record_count": 2
}grouprequest (aggregation)
Request (POST /api/idql/orders):
{
"method":"group",
"scheme":"orders",
"group":"iddate",
"where": {"status":"completed"},
"limit": 10
}curl:
curl -X POST -H "Content-Type: application/json" -d '{"method":"group","scheme":"orders","group":"iddate","where":{"status":"completed"},"limit":10}' http://localhost:8081/api/idql/ordersExpected response (excerpt):
{
"rs": [
{"_id":{"month":5,"year":2025},"count":42,"group":[ /* docs */ ]},
{"_id":{"month":6,"year":2025},"count":37,"group":[ /* docs */ ]}
],
"options": { },
"query": { },
"record_count": 2
}Notes:
parallelis executed sequentially byIdaeApiRest::doQuery()(recursive iteration) and returns an object indexed by position.groupuses the aggregation pipeline inIdaeQuery::group()and returns documents of the form{_id, count, group}.- Projected fields may include
id<scheme>(e.g.idusers) —IdaeApiRestaddsid<scheme>to the projection when a projection is supplied.
Any method to /api/<...> is routed into the REST handler. Example GET:
curl "http://localhost:8081/api/products?limit=10&status=active"t'as riePOST example with body:
curl -X POST http://localhost:8081/api/products \
-H "Content-Type: application/json" \
-d '{"name":"New product","price":12.5}'The REST handler maps the input into IdaeQuery calls according to the scheme configuration.
The repo includes a docker-compose.yml describing two services: app (PHP + Apache) and mongo (MongoDB). By default the compose file mounts an init script that creates a test DB and test user for integration tests.
Start services:
docker compose up -d --buildTo use a host-installed MongoDB instead of the included mongo service, set the MDB_HOST environment variable to host.docker.internal (Windows) or your host IP. Example:
docker compose up -d --build
docker compose exec app bash -lc "export MDB_HOST=host.docker.internal && composer install"There is an override docker-compose.override.yml provided to run Mongo with --noauth for local development. That override intentionally avoids mounting the init script.
Project tests live under web/bin/tests. PHPUnit configuration: web/bin/phpunit.xml.
Unit tests run quickly inside the app container:
docker compose exec app bash -lc "cd /var/www/html/web/bin && ./vendor/bin/phpunit --testsuite unit -c phpunit.xml"Integration tests require a Mongo instance reachable from the app container. Two options:
- Use the included
mongoservice and the default init script (createsidae_testDB andidae_test_user). - Use a host Mongo and set
MDB_HOST=host.docker.internal; a fixture loader is provided to insert test data into the target DB.
Fixture loader (idempotent): web/bin/tests/fixtures/fixture_loader.php
Run it inside the app container (example using host-mapped Mongo):
docker compose exec app bash -lc "cd /var/www/html/web/bin && MDB_HOST=host.docker.internal MDB_USER=admin MDB_PASS=gwetme2011 php tests/fixtures/fixture_loader.php"Then run integration tests:
docker compose exec app bash -lc "cd /var/www/html/web/bin && MDB_HOST=host.docker.internal MDB_USER=admin MDB_PASS=gwetme2011 php vendor/phpunit/phpunit/phpunit --testsuite integration -c phpunit.xml"Notes: some environments require ext-mongodb / libmongoc built with SSL to use SCRAM authentication. For local dev we provide a no-auth override and the fixture loader to keep tests reproducible.
The application reads its runtime constants from web/bin/config/constants.php. Important env vars you may set in Docker or your environment:
MDB_HOST— Mongo host (defaultmongoin compose). Usehost.docker.internalto connect to host Mongo from container.MDB_USER,MDB_PASSWORD— Mongo admin/user credentials.MDB_PREFIX— optional DB prefix used by the app.
You can provide overrides by exporting environment variables before starting containers or by editing web/bin/config/env_constants.php which is included when present.
- Database access is centralized in
web/bin/engine/Idae/Query/IdaeQuery.php. - The connection singleton is implemented in
web/bin/engine/Idae/Connect/IdaeConnect.php. - API parsing and routing are in
web/bin/engine/Idae/Api. - Templates and view fragments live under
web/bin/templates.
If you add new schemes or change the API parsing behavior, follow existing patterns (IdaeApiParser → IdaeApiRest → IdaeQuery) to keep behavior consistent.
- Clone repository and open at project root.
- Build and run containers with Docker Compose.
- Run
composer installin the container or locally (project vendors are installed by the build step in Dockerfile by default). - Run unit tests, then integration tests with the fixture loader if using a host Mongo.
Suggested commands (copy/paste):
# Build and start
docker compose up -d --build
# Install dependencies inside container (if needed)
docker compose exec app bash -lc "cd /var/www/html/web/bin && composer install --no-interaction"
# Load fixtures (host Mongo example)
docker compose exec app bash -lc "cd /var/www/html/web/bin && MDB_HOST=host.docker.internal MDB_USER=admin MDB_PASS=gwetme2011 php tests/fixtures/fixture_loader.php"
# Run tests
docker compose exec app bash -lc "cd /var/www/html/web/bin && php vendor/phpunit/phpunit/phpunit --testsuite unit -c phpunit.xml"
docker compose exec app bash -lc "cd /var/www/html/web/bin && MDB_HOST=host.docker.internal MDB_USER=admin MDB_PASS=gwetme2011 php vendor/phpunit/phpunit/phpunit --testsuite integration -c phpunit.xml"-
If integration tests fail with authentication errors mentioning SCRAM_SHA and libmongoc SSL, the PHP container's Mongo driver has been built without SSL/SASL support. Fix options:
- Use host Mongo (host.docker.internal) and admin creds (quick workaround).
- Rebuild the PHP image ensuring
libssl-devand SASL build dependencies are present andpecl install mongodbpicks up SSL (longer).
-
If containers cannot resolve the
mongoservice name, ensure you rundocker composefrom the repository root and that the network is up (docker compose up -d).
- Add a small
Makefileor Composer script to runfixture_loader.phpautomatically before integration tests. - Add a GitHub Actions workflow that builds the PHP image, starts services, runs the fixture loader, and executes both test suites.