<?php namespace nur\m\base; use nur\A; use nur\b\ValueException; use nur\iter; use nur\m\IConn; abstract class EntityManager { const TABLE_NAME = null; const PK_KEY = null; const PK_AUTO = null; /** * retourner les champs de la clé primaire * - soit une valeur chaine si c'est une clé simple * - soit un tableau si c'est une clé composite */ protected static function get_pk_key($row, $pk_key=null) { if ($pk_key === null) $pk_key = static::PK_KEY; if (is_array($pk_key) && count($pk_key) == 1) $pk_key = iter::first($pk_key); if ($pk_key === false) { # si $pk_key est false, alors toute la ligne est une clé: prendre les noms # des colonnes $pk_key = array_keys(A::with($row)); if (is_array($pk_key) && count($pk_key) == 1) $pk_key = iter::first($pk_key); } return $pk_key; } /** * Obtenir la valeur de la clé primaire d'une ligne. * * - Si $pk_key vaut false, considérer que la clé est l'ensemble des colonnes. * - Si la clé est composite, retourner un tableau associatif avec toutes les * valeurs * - Sinon retourner uniquement la valeur de la clé. */ protected static function get_pk_value($row, $pk_key=null) { $pk_key = self::get_pk_key($row, $pk_key); if (is_array($pk_key)) { if (!is_array($row)) throw ValueException::invalid_value($row, "row"); $pk_value = []; foreach ($pk_key as $col) { $pk_value[$col] = A::get($row, $col); } return $pk_value; } elseif (is_array($row)) { return A::get($row, $pk_key); } else { return $row; } } /** * obtenir un tableau bindings pour filtrer une table sur la valeur de la clé * primaire */ protected static function get_pk_bindings($row, $pk_key=null): array { $pk_value = self::get_pk_value($row, $pk_key); if (is_array($pk_value)) return $pk_value; $pk_key = self::get_pk_key($row, $pk_key); return [$pk_key => $pk_value]; } /** * Obtenir la valeur de la clé primaire d'une ligne sous forme de chaine. * * Si la clé est composite, séparer chaque valeur par un tiret '-' pour faire * une seule chaine. */ protected static function get_pk_string($row, $pk_key=null): string { $pk_value = self::get_pk_value($row, $pk_key); if (is_array($pk_value)) $pk_string = implode("-", $pk_value); else $pk_string = strval($pk_value); return $pk_string; } protected static function map_pks(iterable $rows, $pk_key=null): array { $mapped_rows = []; foreach ($rows as $row) { $pk_string = self::get_pk_string($row, $pk_key); $mapped_rows[$pk_string] = $row; } return $mapped_rows; } protected static function sql_select_all(&$filter=null): string { $sql = "select * from ". static::TABLE_NAME; if ($filter !== null) { if (!is_array($filter)) $filter = self::get_pk_bindings($filter); $and = " where"; foreach ($filter as $col => $value) { $sql .= "$and $col = :$col"; $and = " and"; } } return $sql; } abstract static function conn(IConn $pdo=null): IConn; static function select_all($filter=null, $map_key=null): array { $sql = self::sql_select_all($filter); $rows = static::conn()->query($sql, $filter)->execute(); return self::map_pks($rows, $map_key); } static function select_all_val(string $key, $filter=null): array { $sql = self::sql_select_all($filter); $rows = static::conn()->query($sql, $filter)->execute(); $vals = []; foreach ($rows as $row) { $vals[] = A::get($row, $key); } return $vals; } static function select_first($filter=null, $default=null) { $sql = self::sql_select_all($filter); return static::conn()->query($sql, $filter)->first($default); } static function select_first_val(string $key, $filter=null, $default=null) { $sql = self::sql_select_all($filter); $first = static::conn()->query($sql, $filter)->first($default); return A::get($first, $key, $default); } static function select_one($filter=null, $default=null, ?bool $rewind=null): array { $sql = self::sql_select_all($filter); return static::conn()->query($sql, $filter)->one($default, $rewind); } }