PHP.GT

Writing query classes

Query classes are the centre of this library. They are small PHP classes whose methods each describe one part of an SQL statement.

The base query types

SqlBuilder provides these abstract query bases:

  • GT\SqlBuilder\Query\SelectQuery
  • GT\SqlBuilder\Query\InsertQuery
  • GT\SqlBuilder\Query\UpdateQuery
  • GT\SqlBuilder\Query\DeleteQuery
  • GT\SqlBuilder\Query\Table\CreateTableQuery
  • GT\SqlBuilder\Query\Table\AlterTableQuery
  • GT\SqlBuilder\Query\Table\DropTableQuery

Each base type knows how to assemble its own SQL statement.

SelectQuery

SelectQuery is the most feature-rich query type.

The available methods are:

  • select(): array
  • from(): array
  • innerJoin(): array
  • crossJoin(): array
  • leftJoin(): array
  • leftOuterJoin(): array
  • where(): array
  • groupBy(): array
  • having(): array
  • orderBy(): array
  • limit(): ?int
  • offset(): ?int
  • preQuery(): string
  • postQuery(): string

Most of these default to an empty array or null, so you only override what you need.

use GT\SqlBuilder\Query\SelectQuery;

class StudentSelect extends SelectQuery {
	public function select():array {
		return [
			"id",
			"name",
			"dateOfBirth",
		];
	}

	public function from():array {
		return [
			"student",
		];
	}

	public function where():array {
		return [
			"deletedAt is null",
		];
	}
}

Extending a query

Inheritance is the main design idea behind query classes.

class StudentInDistrictSelect extends StudentSelect {
	public function where():array {
		return array_merge(parent::where(), [
			":district",
		]);
	}
}

That renders the base where clause first, then your additional one.

InsertQuery

InsertQuery can be defined in two main ways:

  1. with columns() and values()
  2. with set()
use GT\SqlBuilder\Query\InsertQuery;

class InsertStudent extends InsertQuery {
	public function into():array {
		return [
			"student",
		];
	}

	public function set():array {
		return [
			"name" => ":name",
			"dateOfBirth" => ":dateOfBirth",
		];
	}
}

When set() is present and columns() / values() are empty, the query uses set() to infer both lists.

InsertQuery also supports select() for insert ... select ... statements. That is covered in Subqueries and composition.

UpdateQuery

UpdateQuery provides:

  • table(): array
  • set(): array
  • where(): array
  • preQuery(): string
  • postQuery(): string
use GT\SqlBuilder\Query\UpdateQuery;

class MarkStudentProcessed extends UpdateQuery {
	public function table():array {
		return [
			"student",
		];
	}

	public function set():array {
		return [
			":processedAt",
		];
	}

	public function where():array {
		return [
			":id",
		];
	}
}

That renders the set() shorthand as processedAt = :processedAt.

DeleteQuery

DeleteQuery is intentionally small:

  • from(): array
  • where(): array
  • preQuery(): string
  • postQuery(): string
use GT\SqlBuilder\Query\DeleteQuery;

class DeleteStudent extends DeleteQuery {
	public function from():array {
		return [
			"student",
		];
	}

	public function where():array {
		return [
			"id = :id",
		];
	}
}

preQuery() and postQuery()

All query bases inherit these two hooks from SqlQuery:

  • preQuery()
  • postQuery()

They return plain strings that are inserted before or after the main statement.

That is mostly useful for comments or engine-specific clauses:

public function preQuery():string {
	return "/* reporting query */";
}

Subqueries

SelectQuery accepts a boolean constructor argument. When true, the final SQL is wrapped in parentheses so it can be embedded inside another query.

$subQuery = new class(true) extends SelectQuery {
	// ...
};

We will use that properly in Subqueries and composition.

The library does not validate SQL semantics

The library assembles query text, but it does not know whether:

  • the table exists
  • the selected columns are valid
  • a group by matches the selected columns
  • the target database supports your syntax

If you prefer inline query construction, continue with Working with builders.