Documentation

BelongsTo extends AbstractRelationship
in package

Relationship class for "belongs to" relationships

Tags
category

Pop

author

Nick Sagona, III nick@popphp.org

copyright

Copyright (c) 2009-2026 Nick Sagona, III

license

https://www.popphp.org/license New BSD License

version
7.0.0

Table of Contents

Constants

COMPOSITE_KEY_DELIMITER  = "\x1f"
Delimiter used to join multiple column values into one composite lookup key

Properties

$child  : Record|null
Child record
$children  : array<string|int, mixed>
Relationship children (list of dotted child paths to eager-load under this relationship)
$foreignKey  : string|array<string|int, mixed>|null
Foreign key
$foreignTable  : string|null
Foreign table class
$options  : array<string|int, mixed>|null
Relationship options

Methods

__construct()  : mixed
Constructor
buildCompositeKey()  : string
Build a single composite lookup key from an ordered list of column values
getChild()  : Record|null
Get child record
getChildRelationships()  : array<string|int, mixed>
Get child relationships
getEagerRelationships()  : array<string|int, mixed>
Get eager relationships
getEmptyRelationshipValue()  : mixed
Get the value to use when no eager-loaded result exists for a given leaf record
getForeignKey()  : string|array<string|int, mixed>|null
Get foreign key
getForeignTable()  : string|null
Get foreign table class
getOptions()  : array<string|int, mixed>|null
Get options
getParent()  : Record|null
Get parent
setChildRelationships()  : static
Set children child relationships
tupleFor()  : array<string|int, mixed>|null
Build an ordered tuple of values for the given columns from a record (either a Record instance or a plain array row). Returns null if any one of the columns is missing or null, i.e. the record has no usable composite key and should be skipped.
applyEagerIdFilter()  : void
Apply the eager-load id filter to a SELECT's WHERE clause and collect its bound values.
assertKeyCardinality()  : void
Validate that an array foreign-key column count matches the target table's own primary-key column count. A plain string $foreignKey is always treated as cardinality 1.
assertTupleCardinality()  : void
Validate that the tuples in an eager-load id list have the same number of components as the array foreign key they will be bound to. A plain string $foreignKey (cardinality 1) and an empty $ids list are always valid.
bindPlaceholder()  : string
Bind a single value as a query parameter and return the placeholder token that must be rendered in its place.
bindPlaceholders()  : array<string|int, mixed>
Bind a flat list of values for a single column and return their placeholder tokens
hydrateChildRelationships()  : void
Hydrate nested child relationships onto a flat list of leaf records, resolving each named child relationship once (accumulated by name) and distributing every one of them onto every leaf record — so multiple differently-named children under this relationship don't overwrite each other.

Constants

COMPOSITE_KEY_DELIMITER

Delimiter used to join multiple column values into one composite lookup key

public string COMPOSITE_KEY_DELIMITER = "\x1f"

Properties

$children

Relationship children (list of dotted child paths to eager-load under this relationship)

protected array<string|int, mixed> $children = []

$foreignKey

Foreign key

protected string|array<string|int, mixed>|null $foreignKey = null

Methods

__construct()

Constructor

public __construct(Record $child, string $foreignTable, string|array<string|int, mixed> $foreignKey[, array<string|int, mixed>|null $options = null ]) : mixed

Instantiate the relationship object

Parameters
$child : Record
$foreignTable : string
$foreignKey : string|array<string|int, mixed>
$options : array<string|int, mixed>|null = null

buildCompositeKey()

Build a single composite lookup key from an ordered list of column values

public static buildCompositeKey(array<string|int, mixed> $values) : string
Parameters
$values : array<string|int, mixed>
Return values
string

getChildRelationships()

Get child relationships

public getChildRelationships() : array<string|int, mixed>
Return values
array<string|int, mixed>

getEagerRelationships()

Get eager relationships

public getEagerRelationships(array<string|int, mixed> $ids) : array<string|int, mixed>
Parameters
$ids : array<string|int, mixed>
Tags
throws
Exception
Return values
array<string|int, mixed>

getEmptyRelationshipValue()

Get the value to use when no eager-loaded result exists for a given leaf record

public getEmptyRelationshipValue() : mixed

getForeignKey()

Get foreign key

public getForeignKey() : string|array<string|int, mixed>|null
Return values
string|array<string|int, mixed>|null

getForeignTable()

Get foreign table class

public getForeignTable() : string|null
Return values
string|null

getOptions()

Get options

public getOptions() : array<string|int, mixed>|null
Return values
array<string|int, mixed>|null

getParent()

Get parent

public getParent([array<string|int, mixed>|null $options = null ]) : Record|null
Parameters
$options : array<string|int, mixed>|null = null
Return values
Record|null

setChildRelationships()

Set children child relationships

public setChildRelationships(array<string|int, mixed> $children) : static
Parameters
$children : array<string|int, mixed>
Return values
static

tupleFor()

Build an ordered tuple of values for the given columns from a record (either a Record instance or a plain array row). Returns null if any one of the columns is missing or null, i.e. the record has no usable composite key and should be skipped.

public static tupleFor(mixed $record, array<string|int, mixed> $columns) : array<string|int, mixed>|null
Parameters
$record : mixed
$columns : array<string|int, mixed>
Return values
array<string|int, mixed>|null

applyEagerIdFilter()

Apply the eager-load id filter to a SELECT's WHERE clause and collect its bound values.

protected applyEagerIdFilter(Sql $sql, string|array<string|int, mixed> $key, array<string|int, mixed> $ids, array<string|int, mixed> &$params) : void

A single-column key renders as one "column IN (...)" predicate. A composite key renders as one AND-nested group of per-tuple OR-nested equality groups, so that whatever gets appended to the WHERE clause afterward is ANDed against the whole "matches any of these id tuples" block rather than becoming a sibling OR at the top level. It renders identically when there is no sibling predicate.

Parameters
$sql : Sql
$key : string|array<string|int, mixed>
$ids : array<string|int, mixed>
$params : array<string|int, mixed>

assertKeyCardinality()

Validate that an array foreign-key column count matches the target table's own primary-key column count. A plain string $foreignKey is always treated as cardinality 1.

protected assertKeyCardinality(string|array<string|int, mixed> $foreignKey, array<string|int, mixed> $targetPrimaryKeys) : void
Parameters
$foreignKey : string|array<string|int, mixed>
$targetPrimaryKeys : array<string|int, mixed>
Tags
throws
Exception

assertTupleCardinality()

Validate that the tuples in an eager-load id list have the same number of components as the array foreign key they will be bound to. A plain string $foreignKey (cardinality 1) and an empty $ids list are always valid.

protected assertTupleCardinality(array<string|int, mixed> $ids, string|array<string|int, mixed> $foreignKey) : void
Parameters
$ids : array<string|int, mixed>
$foreignKey : string|array<string|int, mixed>
Tags
throws
Exception

bindPlaceholder()

Bind a single value as a query parameter and return the placeholder token that must be rendered in its place.

protected static bindPlaceholder(Sql $sql, string $column, mixed $value, array<string|int, mixed> &$params) : string

A bare placeholder character is NOT a usable placeholder on every dialect: only MySQL/SQL Server take a bare '?'. PostgreSQL needs a positional '$N' and SQLite/PDO need a named ':name', so the token has to be generated here rather than repeating whatever Sql::getPlaceholder() returns. The Sql object's own parameter counter is used to number (PostgreSQL) and to uniquely name (SQLite/PDO) every parameter in the statement, so callers can bind several groups of parameters into one query without colliding.

The generated names deliberately start with the counter, i.e. with a digit, which is exactly what keeps them from ever colliding with the column-derived names that Sql\Parser\Expression::parseShorthand() emits for the same statement.

Parameters
$sql : Sql
$column : string
$value : mixed
$params : array<string|int, mixed>
Return values
string

bindPlaceholders()

Bind a flat list of values for a single column and return their placeholder tokens

protected static bindPlaceholders(Sql $sql, string $column, array<string|int, mixed> $values, array<string|int, mixed> &$params) : array<string|int, mixed>
Parameters
$sql : Sql
$column : string
$values : array<string|int, mixed>
$params : array<string|int, mixed>
Return values
array<string|int, mixed>

hydrateChildRelationships()

Hydrate nested child relationships onto a flat list of leaf records, resolving each named child relationship once (accumulated by name) and distributing every one of them onto every leaf record — so multiple differently-named children under this relationship don't overwrite each other.

protected hydrateChildRelationships(array<string|int, mixed> $leafRecords, string|array<string|int, mixed> $primaryKeyColumn) : void

The column used to query and match a given child relationship is decided per relationship name, not once for all of them: "to-one by foreign key" children (HasOneOf and BelongsTo) are keyed by the leaf record's own foreign key column — the column holding the value that identifies which foreign row to fetch — while every other kind is keyed by the leaf record's primary key.

Parameters
$leafRecords : array<string|int, mixed>
$primaryKeyColumn : string|array<string|int, mixed>

        
On this page

Search results