I've been lucky enough to get my first job as a junior PHP developer. I am concerned I'm not good enough. I would like to brush up on my coding skills and get as much constructive criticism as I can.
This is a SQL query builder, built for MySQL that provides a fluent, chaining API to build a query, and allows you to output the raw SQL. How can I improve the quality of it, as well as any features you can think of that I can try to practice.
API:
$qb = new QueryBuilder('users');
$qb
->where('username', 'googun')
->orWhere('username', 'janetjackson')
->select(['id', 'username', 'email'])
->orderBy('id', 'DESC')
->limit(5);
QueryBuilder class:
<?php
class QueryBuilder {
private $tableName;
private $whereClauses;
private $selectColumns;
private $maxResults;
private $orderBy;
public function __construct($tableName) {
$this->tableName = $tableName;
$this->whereClauses = [];
$this->selectColumns = ['*'];
$this->maxResults = -1;
}
public function where($column, $valueOrOperator, $value = null) : QueryBuilder {
if ($value == null) {
return $this->appendWhere($column, '=', $valueOrOperator);
}
return $this->appendWhere($column, $valueOrOperator, $value);
}
private function appendWhere($column, $operator, $value, $join = 'AND') : QueryBuilder {
$this->whereClauses[] = [
'column' => $column,
'operator' => $operator,
'value' => $value,
'join' => $join
];
return $this;
}
private function whereRaw($rawSql) : QueryBuilder {
$this->whereClauses[] = [
'raw_sql' => $rawSql,
'join' => 'AND'
];
return $this;
}
public function orWhere($column, $valueOrOperator, $value = null) : QueryBuilder {
if ($value == null) {
return $this->appendWhere($column, '=', $valueOrOperator, 'OR');
}
return $this->appendWhere($column, $valueOrOperator, $value);
}
public function orWhereRaw($rawSql) : QueryBuilder {
$this->whereClauses[] = [
'raw_sql' => $rawSql,
'join' => 'OR'
];
return $this;
}
public function select(array $columns) : QueryBuilder {
$this->selectColumns = $columns;
return $this;
}
public function limit(int $amount) : QueryBuilder {
$this->maxResults = $amount;
return $this;
}
public function orderBy(string $column, string $direction) {
$this->orderBy = $column . ' ' . $direction;
return $this;
}
public function buildDefaultQuery() : string {
return 'SELECT ' . implode(',', $this->selectColumns) . ' FROM ' . $this->tableName . ' ';
}
public function parseClauseValue($value) : string {
return is_numeric($value) ? $value : '\'' . $value . '\'';
}
public function appendWhereClausesToQuery($query) : string {
$query .= 'WHERE ';
foreach ($this->whereClauses as $key => $clause) {
if ($key >= 1) {
$query .= ' ' . $clause['join'] . ' ';
}
if (array_key_exists('raw_sql', $clause)) {
$query .= $clause['raw_sql'];
}
else {
$parsedValue = $this->parseClauseValue($clause['value']);
$query .= $clause['column'] . ' ' . $clause['operator'] . ' ' . $parsedValue;
}
}
return $query;
}
public function appendOrderByToQuery($query) : string {
$query .= ' ORDER BY ' . $this->orderBy;
return $query;
}
public function appendLimitSqlToQuery($query) : string {
$query .= ' LIMIT ' . $this->maxResults . ';';
return $query;
}
public function toSql() {
$query = $this->buildDefaultQuery();
if (count($this->whereClauses) > 0) {
$query = $this->appendWhereClausesToQuery($query);
}
if (strlen($this->orderBy) > 0) {
$query = $this->appendOrderByToQuery($query);
}
if ($this->maxResults >= 0) {
$query = $this->appendLimitSqlToQuery($query);
}
return $query;
}
}