Grammar.php
TLDR
This file defines the Illuminate\Database\Grammar
class. It provides methods for wrapping values in keyword identifiers, creating query parameter placeholders, quoting strings, escaping values, determining if a value is a raw expression, and getting the format for database stored dates.
Methods
wrapArray
This method takes an array of values and wraps each value using the wrap
method.
wrapTable
This method wraps a table name or expression in keyword identifiers. If the provided table is not an expression, it adds the table prefix to the table name before wrapping.
wrap
This method wraps a value or expression in keyword identifiers. If the value has a column alias, it separates the alias and wraps each part separately using the "as" connector. If the value is a JSON selector, it wraps each part of the selector.
columnize
This method takes an array of column names and converts them into a delimited string, wrapping each column name using the wrap
method.
parameterize
This method takes an array of values and creates query parameter placeholders for each value using the parameter
method.
parameter
This method returns the appropriate query parameter placeholder for a value. If the value is an expression, it gets the value using the getValue
method. Otherwise, it returns a "?" placeholder.
quoteString
This method quotes a string literal. If the value is an array, it recursively calls the quoteString
method on each value and returns the result as a delimited string.
escape
This method escapes a value for safe SQL embedding. It uses the escape
method of the grammar's database connection, throwing an exception if the connection is not set.
isExpression
This method determines if a given value is a raw expression.
getValue
This method transforms expressions to their scalar types. If the given expression is an expression object, it gets the value by calling the getValue
method on the expression object. Otherwise, it returns the expression as is.
getDateFormat
This method gets the format for database stored dates. It returns the string "Y-m-d H:i:s".
getTablePrefix
This method gets the table prefix used by the grammar.
setTablePrefix
This method sets the table prefix used by the grammar.
setConnection
This method sets the grammar's database connection.
Class
Grammar
The Grammar
class is an abstract class that provides common methods for database grammars. It implements the Macroable
trait, which allows adding new methods to instances of the Grammar
class at runtime. The class defines properties for the grammar's database connection and table prefix, as well as getter and setter methods for the table prefix and connection.
<?php
namespace Illuminate\Database;
use Illuminate\Contracts\Database\Query\Expression;
use Illuminate\Support\Traits\Macroable;
use RuntimeException;
abstract class Grammar
{
use Macroable;
/**
* The connection used for escaping values.
*
* @var \Illuminate\Database\Connection
*/
protected $connection;
/**
* The grammar table prefix.
*
* @var string
*/
protected $tablePrefix = '';
/**
* Wrap an array of values.
*
* @param array $values
* @return array
*/
public function wrapArray(array $values)
{
return array_map([$this, 'wrap'], $values);
}
/**
* Wrap a table in keyword identifiers.
*
* @param \Illuminate\Contracts\Database\Query\Expression|string $table
* @return string
*/
public function wrapTable($table)
{
if (! $this->isExpression($table)) {
return $this->wrap($this->tablePrefix.$table, true);
}
return $this->getValue($table);
}
/**
* Wrap a value in keyword identifiers.
*
* @param \Illuminate\Contracts\Database\Query\Expression|string $value
* @param bool $prefixAlias
* @return string
*/
public function wrap($value, $prefixAlias = false)
{
if ($this->isExpression($value)) {
return $this->getValue($value);
}
// If the value being wrapped has a column alias we will need to separate out
// the pieces so we can wrap each of the segments of the expression on its
// own, and then join these both back together using the "as" connector.
if (stripos($value, ' as ') !== false) {
return $this->wrapAliasedValue($value, $prefixAlias);
}
// If the given value is a JSON selector we will wrap it differently than a
// traditional value. We will need to split this path and wrap each part
// wrapped, etc. Otherwise, we will simply wrap the value as a string.
if ($this->isJsonSelector($value)) {
return $this->wrapJsonSelector($value);
}
return $this->wrapSegments(explode('.', $value));
}
/**
* Wrap a value that has an alias.
*
* @param string $value
* @param bool $prefixAlias
* @return string
*/
protected function wrapAliasedValue($value, $prefixAlias = false)
{
$segments = preg_split('/\s+as\s+/i', $value);
// If we are wrapping a table we need to prefix the alias with the table prefix
// as well in order to generate proper syntax. If this is a column of course
// no prefix is necessary. The condition will be true when from wrapTable.
if ($prefixAlias) {
$segments[1] = $this->tablePrefix.$segments[1];
}
return $this->wrap($segments[0]).' as '.$this->wrapValue($segments[1]);
}
/**
* Wrap the given value segments.
*
* @param array $segments
* @return string
*/
protected function wrapSegments($segments)
{
return collect($segments)->map(function ($segment, $key) use ($segments) {
return $key == 0 && count($segments) > 1
? $this->wrapTable($segment)
: $this->wrapValue($segment);
})->implode('.');
}
/**
* Wrap a single string in keyword identifiers.
*
* @param string $value
* @return string
*/
protected function wrapValue($value)
{
if ($value !== '*') {
return '"'.str_replace('"', '""', $value).'"';
}
return $value;
}
/**
* Wrap the given JSON selector.
*
* @param string $value
* @return string
*
* @throws \RuntimeException
*/
protected function wrapJsonSelector($value)
{
throw new RuntimeException('This database engine does not support JSON operations.');
}
/**
* Determine if the given string is a JSON selector.
*
* @param string $value
* @return bool
*/
protected function isJsonSelector($value)
{
return str_contains($value, '->');
}
/**
* Convert an array of column names into a delimited string.
*
* @param array $columns
* @return string
*/
public function columnize(array $columns)
{
return implode(', ', array_map([$this, 'wrap'], $columns));
}
/**
* Create query parameter place-holders for an array.
*
* @param array $values
* @return string
*/
public function parameterize(array $values)
{
return implode(', ', array_map([$this, 'parameter'], $values));
}
/**
* Get the appropriate query parameter place-holder for a value.
*
* @param mixed $value
* @return string
*/
public function parameter($value)
{
return $this->isExpression($value) ? $this->getValue($value) : '?';
}
/**
* Quote the given string literal.
*
* @param string|array $value
* @return string
*/
public function quoteString($value)
{
if (is_array($value)) {
return implode(', ', array_map([$this, __FUNCTION__], $value));
}
return "'$value'";
}
/**
* Escapes a value for safe SQL embedding.
*
* @param string|float|int|bool|null $value
* @param bool $binary
* @return string
*/
public function escape($value, $binary = false)
{
if (is_null($this->connection)) {
throw new RuntimeException("The database driver's grammar implementation does not support escaping values.");
}
return $this->connection->escape($value, $binary);
}
/**
* Determine if the given value is a raw expression.
*
* @param mixed $value
* @return bool
*/
public function isExpression($value)
{
return $value instanceof Expression;
}
/**
* Transforms expressions to their scalar types.
*
* @param \Illuminate\Contracts\Database\Query\Expression|string|int|float $expression
* @return string|int|float
*/
public function getValue($expression)
{
if ($this->isExpression($expression)) {
return $this->getValue($expression->getValue($this));
}
return $expression;
}
/**
* Get the format for database stored dates.
*
* @return string
*/
public function getDateFormat()
{
return 'Y-m-d H:i:s';
}
/**
* Get the grammar's table prefix.
*
* @return string
*/
public function getTablePrefix()
{
return $this->tablePrefix;
}
/**
* Set the grammar's table prefix.
*
* @param string $prefix
* @return $this
*/
public function setTablePrefix($prefix)
{
$this->tablePrefix = $prefix;
return $this;
}
/**
* Set the grammar's database connection.
*
* @param \Illuminate\Database\Connection $connection
* @return $this
*/
public function setConnection($connection)
{
$this->connection = $connection;
return $this;
}
}