Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

[reading and analysis of laravel3.0.0 source code] query syntax class

wx5bffdbaf11b62 2021-07-26 11:19:07 阅读数:4 评论数:0 点赞数:0 收藏数:0

<?php namespace Laravel\Database\Query\Grammars;
use Laravel\Database\Query;
use Laravel\Database\Expression;
class Grammar extends \Laravel\Database\Grammar {
/**
* All of the query componenets in the order they should be built.
* All query components are built in the order they should be .
* @var array
*/
protected $components = array(
'aggregate', 'selects', 'from', 'joins', 'wheres',
'groupings', 'orderings', 'limit', 'offset',
);
/**
* Compile a SQL SELECT statement from a Query instance.
* from Query Instance compilation SQL SELECT sentence
* @param Query $query
* @return string
*/
public function select(Query $query)
{
return $this->concatenate($this->components($query));
}
/**
* Generate the SQL for every component of the query.
* Generate... For each component of the query SQL.
* @param Query $query
* @return array
*/
final protected function components($query)
{
// Each portion of the statement is compiled by a function corresponding
// to an item in the components array. This lets us to keep the creation
// of the query very granular and very flexible.
// Each part of the statement is represented by a corresponding to components Function compilation of an item in the array . This allows us to create queries with great refinement and flexibility .
//
// Note that each component also connects to a public property on the
// query instance, allowing us to pass the correct data into each
// of the compiler functions.
// Please note that , Each component is also connected to public properties on the query instance , Allows us to pass the correct data to each compiler function .
foreach ($this->components as $component)
{
if ( ! is_null($query->$component))
{
$sql[$component] = call_user_func(array($this, $component), $query);
}
}
return (array) $sql;
}
/**
* Concatenate an array of SQL segments, removing those that are empty.
* Connect a group of SQL paragraph , Delete those empty segments .
* @param array $components
* @return string
*/
final protected function concatenate($components)
{
return implode(' ', array_filter($components, function($value)
{
return (string) $value !== '';
}));
}
/**
* Compile the SELECT clause for a query.
* Compile for query SELECT Clause .
* @param Query $query
* @return string
*/
protected function selects(Query $query)
{
if ( ! is_null($query->aggregate)) return;
$select = ($query->distinct) ? 'SELECT DISTINCT ' : 'SELECT ';
return $select.$this->columnize($query->selects);
}
/**
* Compile an aggregating SELECT clause for a query.
* Compile aggregates for queries SELECT Clause .
* @param Query $query
* @return string
*/
protected function aggregate(Query $query)
{
$column = $this->columnize($query->aggregate['columns']);
if ($query->distinct and $column !== '*') $column = 'DISTINCT '.$column;
return 'SELECT '.$query->aggregate['aggregator'].'('.$column.') AS '.$this->wrap('aggregate');
}
/**
* Compile the FROM clause for a query.
* Compile for query FROM Clause .
* @param Query $query
* @return string
*/
protected function from(Query $query)
{
return 'FROM '.$this->wrap_table($query->from);
}
/**
* Compile the JOIN clauses for a query.
* Compile for query JOIN Clause .
* @param Query $query
* @return string
*/
protected function joins(Query $query)
{
// We need to iterate through each JOIN clause that is attached to the
// query an translate it into SQL. The table and the columns will be
// wrapped in identifiers to avoid naming collisions.
// We need to iterate through each... Attached to the query JOIN Clause and convert it to SQL. Tables and columns will be included in identifiers to avoid naming conflicts .
// Once all of the JOINs have been compiled, we can concatenate them
// together using a single space, which should give us the complete
// set of joins in valid SQL that can appended to the query.
// Once you compile all JOIN, We can use a single space to connect them together , This should provide us with valid information that can be attached to the query SQL Complete connection set in .
foreach ($query->joins as $join)
{
$table = $this->wrap_table($join->table);
$clauses = array();
// Each JOIN statement may have multiple clauses, so we will
// iterate through each clause creating the conditions then
// we will concatenate them all together.
// Every JOIN A statement may have multiple clauses , So we'll walk through each clause to create a condition , And then connect them together .
foreach ($join->clauses as $clause)
{
extract($clause);
$column1 = $this->wrap($column1);
$column2 = $this->wrap($column2);
$clauses[] = "{$connector} {$column1} {$operator} {$column2}";
}
// The first clause will have a connector on the front,
// but it is not needed on the first condition, so we
// will strip it off of the condition before adding
// it to the array of joins.
// The first clause will be preceded by a connector , But you don't need it under the first condition , So we'll strip it from the condition before adding it to the join array .
$search = array('AND ', 'OR ');
$clauses[0] = str_replace($search, '', $clauses[0]);
$clauses = implode(' ', $clauses);
$sql[] = "{$join->type} JOIN {$table} ON {$clauses}";
}
// Finally, we should have an array of JOIN clauses
// that we can implode together and return as the
// complete SQL for the JOIN of the query.
// Last , We should have one JOIN Clause array , We can put them together as a query JOIN Integrity SQL return .
return implode(' ', $sql);
}
/**
* Compile the WHERE clause for a query.
* Compile for query WHERE Clause .
* @param Query $query
* @return string
*/
final protected function wheres(Query $query)
{
if (is_null($query->wheres)) return '';
// Each WHERE clause array has a "type" that is assigned by the query
// builder, and each type has its own compiler function. We will call
// the appropriate compiler for each where clause in the query.
// Every WHERE Each clause array has a clause assigned by the query builder “ type ”, Each type has its own compiler function .
// We will for each in the query where Clause to call the appropriate compiler .
// Keeping each particular where clause in its own "compiler" allows
// us to keep the query generation process very granular, making it
// easier to customize derived grammars for other databases.
// Put each specific where The clause remains in its own “ compiler ” in ,
// We can keep the query generation process in a very fine state , This makes it easier to customize the derived syntax for other databases .
foreach ($query->wheres as $where)
{
$sql[] = $where['connector'].' '.$this->{$where['type']}($where);
}
if (isset($sql))
{
// We attach the boolean connector to every where segment just
// for convenience. Once we have built the entire clause we'll
// remove the first instance of a connector from the clause.
// For convenience , We attach Boolean connectors to each where paragraph . Once we build the entire clause , We will remove the first instance of the connector from the clause .
return 'WHERE '.preg_replace('/AND |OR /', '', implode(' ', $sql), 1);
}
}
/**
* Compile a nested WHERE clause.
* Compile nested WHERE Clause .
* @param array $where
* @return string
*/
protected function where_nested($where)
{
return '('.substr($this->wheres($where['query']), 6).')';
}
/**
* Compile a simple WHERE clause.
* Compile a simple WHERE Clause .
* @param array $where
* @return string
*/
protected function where($where)
{
$parameter = $this->parameter($where['value']);
return $this->wrap($where['column']).' '.$where['operator'].' '.$parameter;
}
/**
* Compile a WHERE IN clause.
* Compile one WHERE IN Clause .
* @param array $where
* @return string
*/
protected function where_in($where)
{
$parameters = $this->parameterize($where['values']);
return $this->wrap($where['column']).' IN ('.$parameters.')';
}
/**
* Compile a WHERE NOT IN clause.
* Compile one WHERE NOT IN Clause .
* @param array $where
* @return string
*/
protected function where_not_in($where)
{
$parameters = $this->parameterize($where['values']);
return $this->wrap($where['column']).' NOT IN ('.$parameters.')';
}
/**
* Compile a WHERE NULL clause.
* Compile one WHERE NULL Clause .
* @param array $where
* @return string
*/
protected function where_null($where)
{
return $this->wrap($where['column']).' IS NULL';
}
/**
* Compile a WHERE NULL clause.
* Compile one WHERE NULL Clause .
* @param array $where
* @return string
*/
protected function where_not_null($where)
{
return $this->wrap($where['column']).' IS NOT NULL';
}
/**
* Compile a raw WHERE clause.
* Compile an original WHERE Clause .
* @param array $where
* @return string
*/
final protected function where_raw($where)
{
return $where['sql'];
}
/**
* Compile the GROUP BY clause for a query.
* Compile for query GROUP BY Clause .
* @param Query $query
* @return string
*/
protected function groupings(Query $query)
{
return 'GROUP BY '.$this->columnize($query->groupings);
}
/**
* Compile the ORDER BY clause for a query.
* Compile for query ORDER BY Clause .
* @param Query $query
* @return string
*/
protected function orderings(Query $query)
{
foreach ($query->orderings as $ordering)
{
$direction = strtoupper($ordering['direction']);
$sql[] = $this->wrap($ordering['column']).' '.$direction;
}
return 'ORDER BY '.implode(', ', $sql);
}
/**
* Compile the LIMIT clause for a query.
* Compile for query LIMIT Clause .
* @param Query $query
* @return string
*/
protected function limit(Query $query)
{
return 'LIMIT '.$query->limit;
}
/**
* Compile the OFFSET clause for a query.
* Compile for query OFFSET Clause .
* @param Query $query
* @return string
*/
protected function offset(Query $query)
{
return 'OFFSET '.$query->offset;
}
/**
* Compile a SQL INSERT statment from a Query instance.
* from Query Instance compilation SQL INSERT sentence .
* This method handles the compilation of single row inserts and batch inserts.
* This method handles the compilation of single line insertion and batch insertion .
* @param Query $query
* @param array $values
* @return string
*/
public function insert(Query $query, $values)
{
$table = $this->wrap_table($query->from);
// Force every insert to be treated like a batch insert. This simply makes
// creating the SQL syntax a little easier on us since we can always treat
// the values as if it is an array containing multiple inserts.
// Force each insert to be treated as a batch insert . It just makes it easier for us to create SQL grammar , Because we can always think of values as arrays containing multiple inserts .
if ( ! is_array(reset($values))) $values = array($values);
// Since we only care about the column names, we can pass any of the insert
// arrays into the "columnize" method. The columns should be the same for
// every insert to the table so we can just use the first record.
// Because we only care about listing , We can pass any inserted array to “columnize” Method .
// Every time you insert a table, the columns should be the same , So we can only use the first record .
$columns = $this->columnize(array_keys(reset($values)));
// Build the list of parameter place-holders of values bound to the query.
// Each insert should have the same number of bound paramters, so we can
// just use the first array of values.
// Build a list of parameter placeholders bound to the value of the query . Each insert should have the same number of binding parameters , So we can only use the first value array .
$parameters = $this->parameterize(reset($values));
$parameters = implode(', ', array_fill(0, count($values), "($parameters)"));
return "INSERT INTO {$table} ({$columns}) VALUES {$parameters}";
}
/**
* Compile a SQL UPDATE statment from a Query instance.
* from Query Instance compilation SQL UPDATE sentence .
* @param Query $query
* @param array $values
* @return string
*/
public function update(Query $query, $values)
{
$table = $this->wrap_table($query->from);
// Each column in the UPDATE statement needs to be wrapped in keyword
// identifiers, and a place-holder needs to be created for each value
// in the array of bindings. Of course, if the value of the binding
// is an expression, the expression string will be injected.
// UPDATE Each column in the statement needs to be included in the keyword identifier , And you need to create a placeholder for each value in the binding array .
// Of course , If the bound value is an expression , The expression string will be injected .
foreach ($values as $column => $value)
{
$columns[] = $this->wrap($column).' = '.$this->parameter($value);
}
$columns = implode(', ', $columns);
// UPDATE statements may be constrained by a WHERE clause, so we'll
// run the entire where compilation process for those contraints.
// This is easily achieved by passing the query to the "wheres"
// method which will call all of the where compilers.
// UPDATE Statements may be subject to WHERE Clause constraints , So we'll run the whole... For these constraints where The build process .
// This can be done by passing the query to “wheres” Method to easily implement , This method will call all where compiler .
return trim("UPDATE {$table} SET {$columns} ".$this->wheres($query));
}
/**
* Compile a SQL DELETE statment from a Query instance.
* from Query Instance compilation SQL DELETE sentence .
* @param Query $query
* @return string
*/
public function delete(Query $query)
{
$table = $this->wrap_table($query->from);
// Like the UPDATE statement, the DELETE statement is constrained
// by WHERE clauses, so we'll need to run the "wheres" method to
// make the WHERE clauses for the query.
// And UPDATE The sentence is the same ,DELETE Statement affected WHERE Clause constraints , So we need to run “wheres” Method to create WHERE Clause .
return trim("DELETE FROM {$table} ".$this->wheres($query));
}
/**
* Transform an SQL short-cuts into real SQL for PDO.
* take SQL Shortcut converted to for PDO The real SQL.
* @param string $sql
* @param array $bindings
* @return string
*/
public function shortcut($sql, $bindings)
{
// Laravel provides an easy short-cut notation for writing raw
// WHERE IN statements. If (...) is in the query, it will be
// replaced with the correct number of parameters based on
// the bindings for the query.
// Laravel Write the original WHERE IN Statement provides a simple shortcut .
// If (...) In the query , It will be replaced with the correct number of parameters based on the query binding .
if (strpos($sql, '(...)') !== false)
{
for ($i = 0; $i < count($bindings); $i++)
{
// If the binding is an array, we can just assume it's
// used to fill a "where in" condition, so we'll just
// replace the next place-holder in the query.
// If the binding is an array , We can assume that it is used to fill “where in” Conditions , So we'll replace the next placeholder in the query .
if (is_array($bindings[$i]))
{
$parameters = $this->parameterize($bindings[$i]);
$sql = preg_replace('~\(\.\.\.\)~', "({$parameters})", $sql, 1);
}
}
}
return trim($sql);
}
}

github Address : https://github.com/liu-shilong/laravel3-scr   

Copyright statement
In this paper,the author:[wx5bffdbaf11b62],Reprint please bring the original link, thank you

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;