Database - phpgt/WebEngine GitHub Wiki

WebEngine uses phpgt/database as its database layer, so the ideas here are the WebEngine way of working with queries and migrations.

If you want the lower-level component details, the full Database docs live at https://www.php.gt/docs/database/.

What WebEngine gives us

In a plain phpgt/database project we construct Settings, instantiate Database, and call the migrator ourselves.

In WebEngine, much of that wiring is already handled:

  • configuration is read from config.ini
  • query files live in the project query/ directory
  • the database service is available in page logic
  • migrations are exposed through gt migrate

That means we can focus mainly on query organisation and application logic.

Configuring the connection

Database settings belong in the [database] section of config.ini.

SQLite example:

[database]
driver=sqlite
schema=app.sqlite

MySQL example:

[database]
driver=mysql
host=localhost
schema=app_db
port=3306
username=app_user
password=app_pass

Useful keys:

  • driver
  • schema
  • host
  • port
  • username
  • password
  • query_path
  • migration_path
  • migration_table
  • dev_migration_path
  • dev_migration_table

For the full component-level explanation of connection settings, see https://www.php.gt/docs/database/configuration-and-connections/.

Writing queries

Query files normally live in query/.

For example, if we add:

query/user/getById.sql

we can call it from page logic like this:

public function go():void {
	$row = $this->database->fetch("user/getById", 42);
}

This keeps SQL out of page logic and makes the query easy to find on disk.

For more about collections, naming and PHP query classes, see https://www.php.gt/docs/database/query-collections/.

Binding values

The same two binding styles are available in WebEngine:

  • positional placeholders with ?
  • named placeholders with :name

Example:

$row = $this->database->fetch("user/getByEmail", [
	"email" => "[email protected]",
	"isActive" => true,
]);

query/user/getByEmail.sql:

select
	id,
	email,
	name
	
from
	user
	
where
	email = :email
and
	isActive = :isActive
	
limit 1

For the full rules around special and dynamic bindings, see https://www.php.gt/docs/database/parameter-binding/.

Working with results

The database service returns the same Row and ResultSet objects as the standalone package.

That means we can use helpers such as:

  • fetch()
  • fetchAll()
  • fetchString()
  • fetchInt()
  • fetchDateTime()

For a full explanation, see:

Migrations

WebEngine exposes database migrations through gt migrate.

The default migration directory is:

query/_migration/

And branch-local dev migrations can live in:

query/_migration/dev/

Common commands:

gt migrate
gt migrate --force
gt migrate --reset
gt migrate --dev
gt migrate --dev-merge

This gives us a clean workflow:

  • use gt migrate for normal schema updates
  • use gt migrate --dev while a feature branch is still changing
  • use gt migrate --dev-merge when the branch-local migrations are ready to become canonical

For the full migration rules and integrity checks, see https://www.php.gt/docs/database/database-migrations/.

[!TIP] If you are new to the framework, keep the WebEngine view simple: write queries in query/, call them from page logic, and let gt migrate manage schema changes. The lower-level Database docs are there when you need more detail.


Next, move on to Page logic to see where this database service fits into the wider request flow.