{$p} = null; } return $this; } public function create(string $model_class, array $data = null): Model { return BaseModel::factory($model_class)->create($data); } protected $class; public function find(string $model_class): Model { if (!class_exists($model_class)) { throw new \InvalidArgumentException('El modelo ' . $model_class . ' no existe.'); } $this->reset(); $this->class = $model_class; return $this; } protected $columns; public function select($columns): Model { if ($this->columns === null) { $this->columns = []; } if (!is_array($columns)) { $columns = [$columns]; } foreach ($columns as $c) { $col = (object) [ 'table' => '', 'column' => $c ]; if (is_array($c)) { $col = (object) [ 'table' => $c['table'] ?? $c[0], 'column' => $c['column'] ?? $c[1] ]; } $this->columns []= $col; } return $this; } protected $joins; public function join(array $joins): Model { if ($this->joins === null) { $this->joins = []; } foreach ($joins as $j) { $join = (object) [ 'table' => $j['table'] ?? $j[0], 'from' => $j['from'] ?? $j[1], 'to' => $j['to'] ?? $j[2], 'sym' => $j['sym'] ?? ($j[3] ?? '='), 'alias' => $j['alias'] ?? '', 'type' => strtolower($j['type']) ?? '', 'params' => $j['params'] ?? '' ]; $this->joins []= $join; } return $this; } protected $conditions; public function where(array $conditions): Model { if ($this->conditions === null) { $this->conditions = []; } foreach ($conditions as $c) { $cond = (object) [ 'column' => $c['column'] ?? $c[0], 'value' => $c['value'] ?? $c[1], 'sym' => strtolower($c['sym'] ?? ($c[2] ?? '=')), 'type' => strtolower($c['type']) ?? '' ]; $this->conditions []= $cond; } return $this; } protected $grouping; public function group($groups): Model { if ($this->grouping === null) { $this->grouping = []; } if (!is_array($groups)) { $groups = [$groups]; } foreach ($groups as $g) { $this->grouping []= $g; } return $this; } protected $ordering; public function order($orders): Model { if ($this->ordering === null) { $this->ordering = []; } if (!is_array($orders)) { $orders = [$orders]; } foreach ($orders as $o) { $order = (object) [ 'column' => $o, 'direction' => 'asc' ]; if (is_array($o)) { $order = (object) [ 'column' => $o['column'] ?? $o[0], 'direction' => strtolower($o['direction']) ?? $o[1] ]; } $this->ordering []= $order; } return $this; } protected $limit; public function limit(int $limit): Model { $this->limit = $limit; } protected $offset; public function offset(int $offset): Model { $this->offset = $offset; } protected function parseSelect(ORM $orm): ORM { if ($this->columns === null) { return $orm; } foreach ($this->columns as $col) { $orm = $orm->select(trim(implode('.', $col), '.')); } return $orm; } protected function parseJoin(ORM $orm): ORM { if ($this->joins === null) { return $orm; } foreach ($this->joins as $join) { $method = 'join'; switch ($join->type) { case 'raw': $method = 'rawJoin'; break; case 'inner': $method = 'innerJoin'; break; case 'left': case 'left outer': case 'left_outer': case 'leftouter': $method = 'leftOuterJoin'; break; case 'right': case 'right outer': case 'right_outer': case 'rightouter': $method = 'rightOuterJoin'; break; case 'full': case 'full outer': case 'full_outer': case 'fullouter': $method = 'fullOuterJoin'; break; } if ($join->type == 'raw') { $orm = $orm->{$method}($join->table, [$join->from, $join->symb, $join->to], $join->alias, $join->params); } elseif ($join->alias === '') { $orm = $orm->{$method}($join->table, [$join->from, $join->symb, $join->to], $join->alias); } else { $orm = $orm->{$method}($join->table, [$join->from, $join->symb, $join->to]); } } return $orm; } protected function parseWhere(ORM $orm): ORM { if ($this->conditions === null) { return $orm; } foreach ($this->conditions as $cond) { $method = 'where'; switch ($cond->sym) { case '<': $method = 'whereLt'; break; case '<=': $method = 'whereLte'; break; case '>': $method = 'whereGt'; break; case '>=': $method = 'whereGte'; break; case '!=': $method = 'whereNotEqual'; break; case 'like': $method = 'whereLike'; break; case 'not like': case 'not_like': case 'notlike': $method = 'whereNotLike'; break; } switch ($cond->type) { case 'equal': $method = 'whereEqual'; break; case 'not equal': case 'not_equal': case 'notequal': $method = 'whereNotEqual'; break; case 'less': case 'less than': case 'less_than': case 'lessthan': case 'lt': $method = 'whereLt'; break; case 'less equal': case 'less_equal': case 'lessequal': case 'less than equal': case 'less_than_equal': case 'lessthanequal': case 'lte': $method = 'whereLte'; break; case 'greater': case 'greater than': case 'greater_than': case 'greaterthan': case 'gt': $method = 'whereGt'; break; case 'greater equal': case 'greater_equal': case 'greaterequal': case 'greater than equal': case 'greater_than_equal': case 'greaterthanequal': case 'gte': $method = 'whereGte'; break; case 'like': $method = 'whereLike'; break; case 'not like': case 'not_like': case 'notlike': $method = 'whereNotLike'; break; case 'in': $method = 'whereIn'; break; case 'not in': case 'not_in': case 'notin': $method = 'whereNotIn'; break; case 'raw': $method = 'rawWhere'; break; } $orm = $orm->{$method}($cond->column, $cond->value); } return $orm; } protected function parseGroup(ORM $orm): ORM { if ($this->grouping === null) { return $orm; } foreach ($this->grouping as $group) { if (strpos($group, '(') !== false) { $orm = $orm->groupByExpr($group); } else { $orm = $orm->groupBy($group); } } return $orm; } protected function parseOrder(ORM $orm): ORM { if ($this->ordering === null) { return $orm; } foreach ($this->ordering as $order) { if (strpos($order->column, '(') !== false) { $orm = $orm->orderByExpr($order->column); continue; } switch ($order->direction) { case 'asc': case 'ascending': $orm = $orm->orderByAsc($order->column); break; case 'desc': case 'descending': $orm = $orm->orderByDesc($order->column); break; } } return $orm; } protected function parseLimit(ORM $orm): ORM { if ($this->limit === null) { return $orm; } return $orm->limit($this->limit); } protected function parseOffset(ORM $orm): ORM { if ($this->offset === null) { return $orm; } return $orm->offset($this->offset); } public function one($id = null): ModelInterface { $result = $this->build()->findOne($id); $result->setFactory($this); return $result; } public function many(): array { $results = $this->build()->findMany(); foreach ($results as &$r) { $r->setFactory($this); } return $results; } public function array(): array { $results = $this->build()->findArray(); return $results; } protected function build(): ORM { $orm = BaseModel::factory($this->class); $methods = [ 'select', 'join', 'where', 'group', 'order', 'limit', 'offset' ]; foreach ($methods as $m) { $method = 'parse' . ucfirst($m); $orm = $this->{$method}($orm); } return $orm; } }