initial commit of laravel!
This commit is contained in:
58
system/db/connector.php
Normal file
58
system/db/connector.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php namespace System\DB;
|
||||
|
||||
class Connector {
|
||||
|
||||
/**
|
||||
* The PDO connection options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $options = array(
|
||||
\PDO::ATTR_CASE => \PDO::CASE_LOWER,
|
||||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
||||
\PDO::ATTR_ORACLE_NULLS => \PDO::NULL_NATURAL,
|
||||
\PDO::ATTR_STRINGIFY_FETCHES => false,
|
||||
);
|
||||
|
||||
/**
|
||||
* Establish a PDO database connection.
|
||||
*
|
||||
* @param object $config
|
||||
* @return PDO
|
||||
*/
|
||||
public static function connect($config)
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Establish a SQLite PDO connection.
|
||||
// ---------------------------------------------------
|
||||
if ($config->driver == 'sqlite')
|
||||
{
|
||||
return new \PDO('sqlite:'.APP_PATH.'db/'.$config->database.'.sqlite', null, null, static::$options);
|
||||
}
|
||||
// ---------------------------------------------------
|
||||
// Establish a MySQL or Postgres PDO connection.
|
||||
// ---------------------------------------------------
|
||||
elseif ($config->driver == 'mysql' or $config->driver == 'pgsql')
|
||||
{
|
||||
$connection = new \PDO($config->driver.':host='.$config->host.';dbname='.$config->database, $config->username, $config->password, static::$options);
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Set the correct character set.
|
||||
// ---------------------------------------------------
|
||||
if (isset($config->charset))
|
||||
{
|
||||
$connection->prepare("SET NAMES '".$config->charset."'")->execute();
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
// ---------------------------------------------------
|
||||
// If the driver isn't supported, bail out.
|
||||
// ---------------------------------------------------
|
||||
else
|
||||
{
|
||||
throw new \Exception('Database driver '.$config->driver.' is not supported.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
353
system/db/eloquent.php
Normal file
353
system/db/eloquent.php
Normal file
@@ -0,0 +1,353 @@
|
||||
<?php namespace System\DB;
|
||||
|
||||
abstract class Eloquent {
|
||||
|
||||
/**
|
||||
* Indicates if the model exists in the database.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $exists = false;
|
||||
|
||||
/**
|
||||
* The model attributes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $attributes = array();
|
||||
|
||||
/**
|
||||
* The model's dirty attributes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $dirty = array();
|
||||
|
||||
/**
|
||||
* The model's ignored attributes.
|
||||
*
|
||||
* Ignored attributes will not be saved to the database, and
|
||||
* are primarily used to hold relationships.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $ignore = array();
|
||||
|
||||
/**
|
||||
* The relationships that should be eagerly loaded.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $includes = array();
|
||||
|
||||
/**
|
||||
* The relationship type the model is currently resolving.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $relating;
|
||||
|
||||
/**
|
||||
* The foreign key of the "relating" relationship.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $relating_key;
|
||||
|
||||
/**
|
||||
* The table name of the model being resolved. Used during many-to-many eager loading.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $relating_table;
|
||||
|
||||
/**
|
||||
* The model query instance.
|
||||
*
|
||||
* @var Query
|
||||
*/
|
||||
public $query;
|
||||
|
||||
/**
|
||||
* Create a new model instance and set the relationships
|
||||
* that should be eagerly loaded.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function with()
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Create a new model instance.
|
||||
// -----------------------------------------------------
|
||||
$model = Eloquent\Factory::make(get_called_class());
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Set the eager relationships.
|
||||
// -----------------------------------------------------
|
||||
$model->includes = func_get_args();
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a model by the primary key.
|
||||
*
|
||||
* @param int $id
|
||||
* @return mixed
|
||||
*/
|
||||
public static function find($id)
|
||||
{
|
||||
return Eloquent\Factory::make(get_called_class())->where('id', '=', $id)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of models from the database.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function _get()
|
||||
{
|
||||
return Eloquent\Hydrate::from($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first model result
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function _first()
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Load the hydrated models.
|
||||
// -----------------------------------------------------
|
||||
$results = Eloquent\Hydrate::from($this->take(1));
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Return the first result.
|
||||
// -----------------------------------------------------
|
||||
if (count($results) > 0)
|
||||
{
|
||||
reset($results);
|
||||
|
||||
return current($results);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the query for a 1:1 relationship.
|
||||
*
|
||||
* @param string $model
|
||||
* @return mixed
|
||||
*/
|
||||
public function has_one($model)
|
||||
{
|
||||
return Eloquent\Relate::has_one($model, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the query for a 1:* relationship.
|
||||
*
|
||||
* @param string $model
|
||||
* @return mixed
|
||||
*/
|
||||
public function has_many($model)
|
||||
{
|
||||
return Eloquent\Relate::has_many($model, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the query for a 1:1 belonging relationship.
|
||||
*
|
||||
* @param string $model
|
||||
* @return mixed
|
||||
*/
|
||||
public function belongs_to($model)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Get the calling function name.
|
||||
// -----------------------------------------------------
|
||||
list(, $caller) = debug_backtrace(false);
|
||||
|
||||
return Eloquent\Relate::belongs_to($caller, $model, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the query for a *:* relationship.
|
||||
*
|
||||
* @param string $model
|
||||
* @return mixed
|
||||
*/
|
||||
public function has_many_and_belongs_to($model)
|
||||
{
|
||||
return Eloquent\Relate::has_many_and_belongs_to($model, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the model to the database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
Eloquent\Warehouse::store($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method for retrieving model attributes.
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Check the ignored attributes first.
|
||||
// -----------------------------------------------------
|
||||
if (array_key_exists($key, $this->ignore))
|
||||
{
|
||||
return $this->ignore[$key];
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Is the attribute actually a relationship?
|
||||
// -----------------------------------------------------
|
||||
if (method_exists($this, $key))
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Get the query / model for the relationship.
|
||||
// -----------------------------------------------------
|
||||
$model = $this->$key();
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Return the relationship results.
|
||||
// -----------------------------------------------------
|
||||
return ($this->relating == 'has_one' or $this->relating == 'belongs_to')
|
||||
? $this->ignore[$key] = $model->first()
|
||||
: $this->ignore[$key] = $model->get();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Check the "regular" attributes.
|
||||
// -----------------------------------------------------
|
||||
return (array_key_exists($key, $this->attributes)) ? $this->attributes[$key] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for setting model attributes.
|
||||
*/
|
||||
public function __set($key, $value)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Is the key actually a relationship?
|
||||
// -----------------------------------------------------
|
||||
if (method_exists($this, $key))
|
||||
{
|
||||
$this->ignore[$key] = $value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Add the value to the attributes.
|
||||
// -----------------------------------------------------
|
||||
$this->attributes[$key] = $value;
|
||||
$this->dirty[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for determining if a model attribute is set.
|
||||
*/
|
||||
public function __isset($key)
|
||||
{
|
||||
return (array_key_exists($key, $this->attributes) or array_key_exists($key, $this->ignore));
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for unsetting model attributes.
|
||||
*/
|
||||
public function __unset($key)
|
||||
{
|
||||
unset($this->attributes[$key]);
|
||||
unset($this->ignore[$key]);
|
||||
unset($this->dirty[$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for handling dynamic method calls.
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Is the "get" method being called?
|
||||
// -----------------------------------------------------
|
||||
if ($method == 'get')
|
||||
{
|
||||
return $this->_get();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Is the "first" method being called?
|
||||
// -----------------------------------------------------
|
||||
if ($method == 'first')
|
||||
{
|
||||
return $this->_first();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// If the method is an aggregate function, just return
|
||||
// the aggregate value from the query.
|
||||
// -----------------------------------------------------
|
||||
if (in_array($method, array('count', 'sum', 'min', 'max', 'avg')))
|
||||
{
|
||||
return call_user_func_array(array($this->query, $method), $parameters);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Pass the method call to the query instance.
|
||||
// -----------------------------------------------------
|
||||
call_user_func_array(array($this->query, $method), $parameters);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for handling dynamic static method calls.
|
||||
*/
|
||||
public static function __callStatic($method, $parameters)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Create a new model instance.
|
||||
// -----------------------------------------------------
|
||||
$model = Eloquent\Factory::make(get_called_class());
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Do we need to return the entire table?
|
||||
// -----------------------------------------------------
|
||||
if ($method == 'get')
|
||||
{
|
||||
return $model->_get();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Do we need to return the first model from the table?
|
||||
// -----------------------------------------------------
|
||||
if ($method == 'first')
|
||||
{
|
||||
return $model->_first();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// If the method is an aggregate function, just return
|
||||
// the aggregate value from the query.
|
||||
// -----------------------------------------------------
|
||||
if (in_array($method, array('count', 'sum', 'min', 'max', 'avg')))
|
||||
{
|
||||
return call_user_func_array(array($model->query, $method), $parameters);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Pass the method call to the query instance.
|
||||
// -----------------------------------------------------
|
||||
call_user_func_array(array($model->query, $method), $parameters);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
}
|
||||
26
system/db/eloquent/factory.php
Normal file
26
system/db/eloquent/factory.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php namespace System\DB\Eloquent;
|
||||
|
||||
class Factory {
|
||||
|
||||
/**
|
||||
* Factory for creating new model instances.
|
||||
*
|
||||
* @param string $class
|
||||
* @return object
|
||||
*/
|
||||
public static function make($class)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Create a new model instance.
|
||||
// -----------------------------------------------------
|
||||
$model = new $class;
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Set the active query instance on the model.
|
||||
// -----------------------------------------------------
|
||||
$model->query = \System\DB\Query::table(Meta::table($class));
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
}
|
||||
272
system/db/eloquent/hydrate.php
Normal file
272
system/db/eloquent/hydrate.php
Normal file
@@ -0,0 +1,272 @@
|
||||
<?php namespace System\DB\Eloquent;
|
||||
|
||||
class Hydrate {
|
||||
|
||||
/**
|
||||
* Load the array of hydrated models.
|
||||
*
|
||||
* @param object $eloquent
|
||||
* @return array
|
||||
*/
|
||||
public static function from($eloquent)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Load the base models.
|
||||
// -----------------------------------------------------
|
||||
$results = static::base(get_class($eloquent), $eloquent->query->get());
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Load all of the eager relationships.
|
||||
// -----------------------------------------------------
|
||||
if (count($results) > 0)
|
||||
{
|
||||
foreach ($eloquent->includes as $include)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Verify the relationship is defined.
|
||||
// -----------------------------------------------------
|
||||
if ( ! method_exists($eloquent, $include))
|
||||
{
|
||||
throw new \Exception("Attempting to eager load [$include], but the relationship is not defined.");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Eagerly load the relationship.
|
||||
// -----------------------------------------------------
|
||||
static::eagerly($eloquent, $include, $results);
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate the base models for a query.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array $models
|
||||
* @return array
|
||||
*/
|
||||
private static function base($class, $models)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Initialize the hydrated model array.
|
||||
// -----------------------------------------------------
|
||||
$results = array();
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Hydrate the models from the results.
|
||||
// -----------------------------------------------------
|
||||
foreach ($models as $model)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Instantiate a new model instance.
|
||||
// -----------------------------------------------------
|
||||
$result = new $class;
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Set the model's attributes.
|
||||
// -----------------------------------------------------
|
||||
$result->attributes = (array) $model;
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Indicate that the model already exists.
|
||||
// -----------------------------------------------------
|
||||
$result->exists = true;
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Add the hydrated model to the array of models.
|
||||
// The array is keyed by the primary keys of the models.
|
||||
// -----------------------------------------------------
|
||||
$results[$result->id] = $result;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly load a relationship.
|
||||
*
|
||||
* @param object $eloquent
|
||||
* @param string $include
|
||||
* @param array $results
|
||||
* @return void
|
||||
*/
|
||||
private static function eagerly($eloquent, $include, &$results)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Get the relationship Eloquent model.
|
||||
//
|
||||
// We spoof the "belongs_to" key to allow the query
|
||||
// to be fetched without any problems.
|
||||
// -----------------------------------------------------
|
||||
$eloquent->attributes[$spoof = $include.'_id'] = 0;
|
||||
|
||||
$model = $eloquent->$include();
|
||||
|
||||
unset($eloquent->attributes[$spoof]);
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Reset the WHERE clause on the query.
|
||||
// -----------------------------------------------------
|
||||
$model->query->where = 'WHERE 1 = 1';
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Reset the bindings on the query.
|
||||
// -----------------------------------------------------
|
||||
$model->query->bindings = array();
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Initialize the relationship on the parent models.
|
||||
// -----------------------------------------------------
|
||||
foreach ($results as &$result)
|
||||
{
|
||||
$result->ignore[$include] = (strpos($eloquent->relating, 'has_many') === 0) ? array() : null;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Eagerly load a 1:1 or 1:* relationship.
|
||||
// -----------------------------------------------------
|
||||
if ($eloquent->relating == 'has_one' or $eloquent->relating == 'has_many')
|
||||
{
|
||||
static::eagerly_load_one_or_many($eloquent->relating_key, $eloquent->relating, $include, $model, $results);
|
||||
}
|
||||
// -----------------------------------------------------
|
||||
// Eagerly load a 1:1 (belonging) relationship.
|
||||
// -----------------------------------------------------
|
||||
elseif ($eloquent->relating == 'belongs_to')
|
||||
{
|
||||
static::eagerly_load_belonging($eloquent->relating_key, $include, $model, $results);
|
||||
}
|
||||
// -----------------------------------------------------
|
||||
// Eagerly load a *:* relationship.
|
||||
// -----------------------------------------------------
|
||||
else
|
||||
{
|
||||
static::eagerly_load_many_to_many($eloquent->relating_key, $eloquent->relating_table, strtolower(get_class($eloquent)).'_id', $include, $model, $results);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly load a 1:1 or 1:* relationship.
|
||||
*
|
||||
* @param string $relating_key
|
||||
* @param string $relating
|
||||
* @param string $include
|
||||
* @param object $model
|
||||
* @param array $results
|
||||
* @return void
|
||||
*/
|
||||
private static function eagerly_load_one_or_many($relating_key, $relating, $include, $model, &$results)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Get the related models.
|
||||
// -----------------------------------------------------
|
||||
$inclusions = $model->where_in($relating_key, array_keys($results))->get();
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Match the child models with their parent.
|
||||
// -----------------------------------------------------
|
||||
foreach ($inclusions as $key => $inclusion)
|
||||
{
|
||||
if ($relating == 'has_one')
|
||||
{
|
||||
$results[$inclusion->$relating_key]->ignore[$include] = $inclusion;
|
||||
}
|
||||
else
|
||||
{
|
||||
$results[$inclusion->$relating_key]->ignore[$include][$inclusion->id] = $inclusion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly load a 1:1 belonging relationship.
|
||||
*
|
||||
* @param string $relating_key
|
||||
* @param string $include
|
||||
* @param object $model
|
||||
* @param array $results
|
||||
* @return void
|
||||
*/
|
||||
private static function eagerly_load_belonging($relating_key, $include, $model, &$results)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Gather the keys from the parent models.
|
||||
// -----------------------------------------------------
|
||||
$keys = array();
|
||||
|
||||
foreach ($results as &$result)
|
||||
{
|
||||
$keys[] = $result->$relating_key;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Get the related models.
|
||||
// -----------------------------------------------------
|
||||
$inclusions = $model->where_in('id', array_unique($keys))->get();
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Match the child models with their parent.
|
||||
// -----------------------------------------------------
|
||||
foreach ($results as &$result)
|
||||
{
|
||||
$result->ignore[$include] = $inclusions[$result->$relating_key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly load a many-to-many relationship.
|
||||
*
|
||||
* @param string $relating_key
|
||||
* @param string $relating_table
|
||||
* @param string $foreign_key
|
||||
* @param string $include
|
||||
* @param object $model
|
||||
* @param array $results
|
||||
* @return void
|
||||
*/
|
||||
private static function eagerly_load_many_to_many($relating_key, $relating_table, $foreign_key, $include, $model, &$results)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Reset the SELECT clause.
|
||||
// -----------------------------------------------------
|
||||
$model->query->select = null;
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Retrieve the raw results as stdClasses.
|
||||
//
|
||||
// We also add the foreign key to the select which will allow us
|
||||
// to match the models back to their parents.
|
||||
// -----------------------------------------------------
|
||||
$inclusions = $model->query->where_in($relating_key, array_keys($results))->get(Meta::table(get_class($model)).'.*', $relating_table.'.'.$foreign_key);
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Get the class name of the related model.
|
||||
// -----------------------------------------------------
|
||||
$class = get_class($model);
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Create the related models.
|
||||
// -----------------------------------------------------
|
||||
foreach ($inclusions as $inclusion)
|
||||
{
|
||||
$related = new $class;
|
||||
|
||||
$related->exists = true;
|
||||
$related->attributes = (array) $inclusion;
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Remove the foreign key from the attributes since it
|
||||
// was only added to the query to help us match the models.
|
||||
// -----------------------------------------------------
|
||||
unset($related->attributes[$foreign_key]);
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Add the related model to the parent model's array.
|
||||
// -----------------------------------------------------
|
||||
$results[$inclusion->$foreign_key]->ignore[$include][$inclusion->id] = $related;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
24
system/db/eloquent/meta.php
Normal file
24
system/db/eloquent/meta.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php namespace System\DB\Eloquent;
|
||||
|
||||
class Meta {
|
||||
|
||||
/**
|
||||
* Get the table name for a model.
|
||||
*
|
||||
* @param string $class
|
||||
* @return string
|
||||
*/
|
||||
public static function table($class)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Check for a table name override.
|
||||
// -----------------------------------------------------
|
||||
if (property_exists($class, 'table'))
|
||||
{
|
||||
return $class::$table;
|
||||
}
|
||||
|
||||
return \System\Str::lower(\System\Inflector::plural($class));
|
||||
}
|
||||
|
||||
}
|
||||
132
system/db/eloquent/relate.php
Normal file
132
system/db/eloquent/relate.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php namespace System\DB\Eloquent;
|
||||
|
||||
class Relate {
|
||||
|
||||
/**
|
||||
* Retrieve the query for a 1:1 relationship.
|
||||
*
|
||||
* @param string $model
|
||||
* @param object $eloquent
|
||||
* @return mixed
|
||||
*/
|
||||
public static function has_one($model, $eloquent)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Set the relating type.
|
||||
// -----------------------------------------------------
|
||||
$eloquent->relating = __FUNCTION__;
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Return the Eloquent model.
|
||||
// -----------------------------------------------------
|
||||
return static::has_one_or_many($model, $eloquent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the query for a 1:* relationship.
|
||||
*
|
||||
* @param string $model
|
||||
* @param object $eloquent
|
||||
* @return mixed
|
||||
*/
|
||||
public static function has_many($model, $eloquent)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Set the relating type.
|
||||
// -----------------------------------------------------
|
||||
$eloquent->relating = __FUNCTION__;
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Return the Eloquent model.
|
||||
// -----------------------------------------------------
|
||||
return static::has_one_or_many($model, $eloquent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the query for a 1:1 or 1:* relationship.
|
||||
*
|
||||
* @param string $model
|
||||
* @param object $eloquent
|
||||
* @return mixed
|
||||
*/
|
||||
private static function has_one_or_many($model, $eloquent)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Set the relating key.
|
||||
// -----------------------------------------------------
|
||||
$eloquent->relating_key = \System\Str::lower(get_class($eloquent)).'_id';
|
||||
|
||||
return Factory::make($model)->where($eloquent->relating_key, '=', $eloquent->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the query for a 1:1 belonging relationship.
|
||||
*
|
||||
* @param array $caller
|
||||
* @param string $model
|
||||
* @param object $eloquent
|
||||
* @return mixed
|
||||
*/
|
||||
public static function belongs_to($caller, $model, $eloquent)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Set the relating type.
|
||||
// -----------------------------------------------------
|
||||
$eloquent->relating = __FUNCTION__;
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Set the relating key.
|
||||
// -----------------------------------------------------
|
||||
$eloquent->relating_key = $caller['function'].'_id';
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Return the Eloquent model.
|
||||
// -----------------------------------------------------
|
||||
return Factory::make($model)->where('id', '=', $eloquent->attributes[$eloquent->relating_key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the query for a *:* relationship.
|
||||
*
|
||||
* @param string $model
|
||||
* @param object $eloquent
|
||||
* @return mixed
|
||||
*/
|
||||
public static function has_many_and_belongs_to($model, $eloquent)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Get the models involved in the relationship.
|
||||
// -----------------------------------------------------
|
||||
$models = array(\System\Str::lower($model), \System\Str::lower(get_class($eloquent)));
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Sort the model names involved in the relationship.
|
||||
// -----------------------------------------------------
|
||||
sort($models);
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Get the intermediate table name, which is the names
|
||||
// of the two related models alphabetized.
|
||||
// -----------------------------------------------------
|
||||
$eloquent->relating_table = implode('_', $models);
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Set the relating type.
|
||||
// -----------------------------------------------------
|
||||
$eloquent->relating = __FUNCTION__;
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Set the relating key.
|
||||
// -----------------------------------------------------
|
||||
$eloquent->relating_key = $eloquent->relating_table.'.'.\System\Str::lower(get_class($eloquent)).'_id';
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Return the Eloquent model.
|
||||
// -----------------------------------------------------
|
||||
return Factory::make($model)
|
||||
->select(Meta::table($model).'.*')
|
||||
->join($eloquent->relating_table, Meta::table($model).'.id', '=', $eloquent->relating_table.'.'.\System\Str::lower($model).'_id')
|
||||
->where($eloquent->relating_key, '=', $eloquent->id);
|
||||
}
|
||||
|
||||
}
|
||||
66
system/db/eloquent/warehouse.php
Normal file
66
system/db/eloquent/warehouse.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php namespace System\DB\Eloquent;
|
||||
|
||||
class Warehouse {
|
||||
|
||||
/**
|
||||
* Save an Eloquent model to the database.
|
||||
*
|
||||
* @param object $eloquent
|
||||
* @return void
|
||||
*/
|
||||
public static function store($eloquent)
|
||||
{
|
||||
// -----------------------------------------------------
|
||||
// Get the model name.
|
||||
// -----------------------------------------------------
|
||||
$model = get_class($eloquent);
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Get a fresh query instance for the model.
|
||||
// -----------------------------------------------------
|
||||
$eloquent->query = \System\DB\Query::table(Meta::table($model));
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Set the activity timestamps.
|
||||
// -----------------------------------------------------
|
||||
if (property_exists($model, 'timestamps') and $model::$timestamps)
|
||||
{
|
||||
static::timestamp($eloquent);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// If the model exists in the database, update it.
|
||||
// Otherwise, insert the model and set the ID.
|
||||
// -----------------------------------------------------
|
||||
if ($eloquent->exists)
|
||||
{
|
||||
return $eloquent->query->where('id', '=', $eloquent->attributes['id'])->update($eloquent->dirty);
|
||||
}
|
||||
else
|
||||
{
|
||||
$eloquent->attributes['id'] = $eloquent->query->insert_get_id($eloquent->attributes);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
// Set the existence flag to true.
|
||||
// -----------------------------------------------------
|
||||
$eloquent->exists = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the activity timestamps on a model.
|
||||
*
|
||||
* @param object $eloquent
|
||||
* @return void
|
||||
*/
|
||||
private static function timestamp($eloquent)
|
||||
{
|
||||
$eloquent->updated_at = date('Y-m-d H:i:s');
|
||||
|
||||
if ( ! $eloquent->exists)
|
||||
{
|
||||
$eloquent->created_at = $eloquent->updated_at;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
593
system/db/query.php
Normal file
593
system/db/query.php
Normal file
@@ -0,0 +1,593 @@
|
||||
<?php namespace System\DB;
|
||||
|
||||
class Query {
|
||||
|
||||
/**
|
||||
* The database connection name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
/**
|
||||
* The SELECT clause.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $select;
|
||||
|
||||
/**
|
||||
* Indicates if the query should return distinct results.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $distinct = false;
|
||||
|
||||
/**
|
||||
* The FROM clause.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $from;
|
||||
|
||||
/**
|
||||
* The table name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $table;
|
||||
|
||||
/**
|
||||
* The WHERE clause.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $where = 'WHERE 1 = 1';
|
||||
|
||||
/**
|
||||
* The ORDER BY columns.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $orderings = array();
|
||||
|
||||
/**
|
||||
* The LIMIT value.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $limit;
|
||||
|
||||
/**
|
||||
* The OFFSET value.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $offset;
|
||||
|
||||
/**
|
||||
* The query value bindings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $bindings = array();
|
||||
|
||||
/**
|
||||
* Create a new query instance.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $connection
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($table, $connection = null)
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Set the database connection name.
|
||||
// ---------------------------------------------------
|
||||
$this->connection = (is_null($connection)) ? \System\Config::get('db.default') : $connection;
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Build the FROM clause.
|
||||
// ---------------------------------------------------
|
||||
$this->from = 'FROM '.$this->wrap($this->table = $table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new query instance.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $connection
|
||||
* @return Query
|
||||
*/
|
||||
public static function table($table, $connection = null)
|
||||
{
|
||||
return new static($table, $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the query to return distinct results.
|
||||
*
|
||||
* @return Query
|
||||
*/
|
||||
public function distinct()
|
||||
{
|
||||
$this->distinct = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add columns to the SELECT clause.
|
||||
*
|
||||
* @return Query
|
||||
*/
|
||||
public function select()
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Handle DISTINCT selections.
|
||||
// ---------------------------------------------------
|
||||
$this->select = ($this->distinct) ? 'SELECT DISTINCT ' : 'SELECT ';
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Wrap all of the columns in keyword identifiers.
|
||||
// ---------------------------------------------------
|
||||
$this->select .= implode(', ', array_map(array($this, 'wrap'), func_get_args()));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a join to the query.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $column1
|
||||
* @param string $operator
|
||||
* @param string $column2
|
||||
* @param string $type
|
||||
* @return Query
|
||||
*/
|
||||
public function join($table, $column1, $operator, $column2, $type = 'INNER')
|
||||
{
|
||||
$this->from .= ' '.$type.' JOIN '.$this->wrap($table).' ON '.$this->wrap($column1).' '.$operator.' '.$this->wrap($column2);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a left join to the query.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $column1
|
||||
* @param string $operator
|
||||
* @param string $column2
|
||||
* @return Query
|
||||
*/
|
||||
public function left_join($table, $column1, $operator, $column2)
|
||||
{
|
||||
return $this->join($table, $column1, $operator, $column2, 'LEFT');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a raw where condition to the query.
|
||||
*
|
||||
* @param string $where
|
||||
* @param array $bindings
|
||||
* @param string $connector
|
||||
* @return Query
|
||||
*/
|
||||
public function raw_where($where, $bindings = array(), $connector = 'AND')
|
||||
{
|
||||
$this->where .= ' '.$connector.' '.$where;
|
||||
$this->bindings = array_merge($this->bindings, $bindings);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a raw or where condition to the query.
|
||||
*
|
||||
* @param string $where
|
||||
* @param array $bindings
|
||||
* @return Query
|
||||
*/
|
||||
public function raw_or_where($where, $bindings = array())
|
||||
{
|
||||
return $this->raw_where($where, $bindings, 'OR');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a where condition to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $operator
|
||||
* @param mixed $value
|
||||
* @param string $connector
|
||||
* @return Query
|
||||
*/
|
||||
public function where($column, $operator, $value, $connector = 'AND')
|
||||
{
|
||||
$this->where .= ' '.$connector.' '.$this->wrap($column).' '.$operator.' ?';
|
||||
$this->bindings[] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an or where condition to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $operator
|
||||
* @param mixed $value
|
||||
* @return Query
|
||||
*/
|
||||
public function or_where($column, $operator, $value)
|
||||
{
|
||||
return $this->where($column, $operator, $value, 'OR');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a where in condition to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param array $values
|
||||
* @param string $connector
|
||||
* @return Query
|
||||
*/
|
||||
public function where_in($column, $values, $connector = 'AND')
|
||||
{
|
||||
$this->where .= ' '.$connector.' '.$this->wrap($column).' IN ('.$this->parameterize($values).')';
|
||||
$this->bindings = array_merge($this->bindings, $values);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an or where in condition to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param array $values
|
||||
* @return Query
|
||||
*/
|
||||
public function or_where_in($column, $values)
|
||||
{
|
||||
return $this->where_in($column, $values, 'OR');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a where not in condition to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param array $values
|
||||
* @param string $connector
|
||||
* @return Query
|
||||
*/
|
||||
public function where_not_in($column, $values, $connector = 'AND')
|
||||
{
|
||||
$this->where .= ' '.$connector.' '.$this->wrap($column).' NOT IN ('.$this->parameterize($values).')';
|
||||
$this->bindings = array_merge($this->bindings, $values);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an or where not in condition to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param array $values
|
||||
* @return Query
|
||||
*/
|
||||
public function or_where_not_in($column, $values)
|
||||
{
|
||||
return $this->where_not_in($column, $values, 'OR');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a where null condition to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $connector
|
||||
* @return Query
|
||||
*/
|
||||
public function where_null($column, $connector = 'AND')
|
||||
{
|
||||
$this->where .= ' '.$connector.' '.$this->wrap($column).' IS NULL';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an or where null condition to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @return Query
|
||||
*/
|
||||
public function or_where_null($column)
|
||||
{
|
||||
return $this->where_null($column, 'OR');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a where not null condition to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $connector
|
||||
* @return Query
|
||||
*/
|
||||
public function where_not_null($column, $connector = 'AND')
|
||||
{
|
||||
$this->where .= ' '.$connector.' '.$this->wrap($column).' IS NOT NULL';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an or where not null condition to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @return Query
|
||||
*/
|
||||
public function or_where_not_null($column)
|
||||
{
|
||||
return $this->where_not_null($column, 'OR');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an ordering to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $direction
|
||||
* @return Query
|
||||
*/
|
||||
public function order_by($column, $direction)
|
||||
{
|
||||
$this->orderings[] = $this->wrap($column).' '.\System\Str::upper($direction);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query offset.
|
||||
*
|
||||
* @param int $value
|
||||
* @return Query
|
||||
*/
|
||||
public function skip($value)
|
||||
{
|
||||
$this->offset = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query limit.
|
||||
*
|
||||
* @param int $value
|
||||
* @return Query
|
||||
*/
|
||||
public function take($value)
|
||||
{
|
||||
$this->limit = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a record by the primary key.
|
||||
*
|
||||
* @param int $id
|
||||
* @return object
|
||||
*/
|
||||
public function find($id)
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Set the primary key.
|
||||
// ---------------------------------------------------
|
||||
$this->where('id', '=', $id);
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Get the first result.
|
||||
// ---------------------------------------------------
|
||||
return $this->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as a SELECT statement and return the first result.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function first()
|
||||
{
|
||||
return (count($results = call_user_func_array(array($this->take(1), 'get'), func_get_args())) > 0) ? $results[0] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as a SELECT statement.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Initialize the SELECT clause if it's null.
|
||||
// ---------------------------------------------------
|
||||
if (is_null($this->select))
|
||||
{
|
||||
call_user_func_array(array($this, 'select'), (count(func_get_args()) > 0) ? func_get_args() : array('*'));
|
||||
}
|
||||
|
||||
return \System\DB::query(Query\Compiler::select($this), $this->bindings, $this->connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an aggregate value.
|
||||
*
|
||||
* @param string $aggregate
|
||||
* @param string $column
|
||||
* @return mixed
|
||||
*/
|
||||
private function aggregate($aggregator, $column)
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Build the SELECT clause.
|
||||
// ---------------------------------------------------
|
||||
$this->select = 'SELECT '.$aggregator.'('.$this->wrap($column).') AS '.$this->wrap('aggregate');
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Execute the statement.
|
||||
// ---------------------------------------------------
|
||||
$results = \System\DB::query(Query\Compiler::select($this), $this->bindings);
|
||||
|
||||
return $results[0]->aggregate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an INSERT statement.
|
||||
*
|
||||
* @param array $values
|
||||
* @return bool
|
||||
*/
|
||||
public function insert($values)
|
||||
{
|
||||
return \System\DB::query(Query\Compiler::insert($this, $values), array_values($values), $this->connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an INSERT statement and get the insert ID.
|
||||
*
|
||||
* @param array $values
|
||||
* @return int
|
||||
*/
|
||||
public function insert_get_id($values)
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Compile the SQL statement.
|
||||
// ---------------------------------------------------
|
||||
$sql = Query\Compiler::insert($this, $values);
|
||||
|
||||
// ---------------------------------------------------
|
||||
// The Postgres PDO implementation does not cleanly
|
||||
// implement the last insert ID function. So, we'll
|
||||
// use the RETURNING clause available in Postgres.
|
||||
// ---------------------------------------------------
|
||||
if (\System\DB::connection($this->connection)->getAttribute(\PDO::ATTR_DRIVER_NAME) == 'pgsql')
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Add the RETURNING clause to the SQL.
|
||||
// ---------------------------------------------------
|
||||
$sql .= ' RETURNING '.$this->wrap('id');
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Prepare the PDO statement.
|
||||
// ---------------------------------------------------
|
||||
$query = \System\DB::connection($this->connection)->prepare($sql);
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Execute the PDO statement.
|
||||
// ---------------------------------------------------
|
||||
$query->execute(array_values($values));
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Fetch the insert ID from the results.
|
||||
// ---------------------------------------------------
|
||||
$result = $query->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
return $result['id'];
|
||||
}
|
||||
// ---------------------------------------------------
|
||||
// When using MySQL or SQLite, we can just use the PDO
|
||||
// last insert ID function.
|
||||
// ---------------------------------------------------
|
||||
else
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Execute the statement.
|
||||
// ---------------------------------------------------
|
||||
\System\DB::query($sql, array_values($values), $this->connection);
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Get the last insert ID.
|
||||
// ---------------------------------------------------
|
||||
return \System\DB::connection($this->connection)->lastInsertId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as an UPDATE statement.
|
||||
*
|
||||
* @param array $values
|
||||
* @return bool
|
||||
*/
|
||||
public function update($values)
|
||||
{
|
||||
return \System\DB::query(Query\Compiler::update($this, $values), array_merge(array_values($values), $this->bindings), $this->connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as a DELETE statement.
|
||||
*
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($id = null)
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Set the primary key.
|
||||
// ---------------------------------------------------
|
||||
if ( ! is_null($id))
|
||||
{
|
||||
$this->where('id', '=', $id);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Execute the statement.
|
||||
// ---------------------------------------------------
|
||||
return \System\DB::query(Query\Compiler::delete($this), $this->bindings, $this->connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a value in keyword identifiers.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $wrap
|
||||
* @return string
|
||||
*/
|
||||
public function wrap($value, $wrap = '"')
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// If the application is using MySQL, we need to use
|
||||
// a non-standard keyword identifier.
|
||||
// ---------------------------------------------------
|
||||
if (\System\DB::connection($this->connection)->getAttribute(\PDO::ATTR_DRIVER_NAME) == 'mysql')
|
||||
{
|
||||
$wrap = '`';
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Wrap the element in keyword identifiers.
|
||||
// ---------------------------------------------------
|
||||
return implode('.', array_map(function($segment) use ($wrap) {return ($segment != '*') ? $wrap.$segment.$wrap : $segment;}, explode('.', $value)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create query parameters from an array of values.
|
||||
*
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
public function parameterize($values)
|
||||
{
|
||||
return implode(', ', array_fill(0, count($values), '?'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for handling dynamic functions.
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Handle any of the aggregate functions.
|
||||
// ---------------------------------------------------
|
||||
if (in_array($method, array('count', 'min', 'max', 'avg', 'sum')))
|
||||
{
|
||||
return ($method == 'count') ? $this->aggregate(\System\Str::upper($method), '*') : $this->aggregate(\System\Str::upper($method), $parameters[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new \Exception("Method [$method] is not defined on the Query class.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
116
system/db/query/compiler.php
Normal file
116
system/db/query/compiler.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php namespace System\DB\Query;
|
||||
|
||||
class Compiler {
|
||||
|
||||
/**
|
||||
* Build a SQL SELECT statement.
|
||||
*
|
||||
* @param Query $query
|
||||
* @return string
|
||||
*/
|
||||
public static function select($query)
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Add the SELECT, FROM, and WHERE clauses.
|
||||
// ---------------------------------------------------
|
||||
$sql = $query->select.' '.$query->from.' '.$query->where;
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Add the ORDER BY clause.
|
||||
// ---------------------------------------------------
|
||||
if (count($query->orderings) > 0)
|
||||
{
|
||||
$sql .= ' ORDER BY '.implode(', ', $query->orderings);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Add the LIMIT.
|
||||
// ---------------------------------------------------
|
||||
if ( ! is_null($query->limit))
|
||||
{
|
||||
$sql .= ' LIMIT '.$query->limit;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Add the OFFSET.
|
||||
// ---------------------------------------------------
|
||||
if ( ! is_null($query->offset))
|
||||
{
|
||||
$sql .= ' OFFSET '.$query->offset;
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a SQL INSERT statement.
|
||||
*
|
||||
* @param Query $query
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
public static function insert($query, $values)
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Start the query. Add the table name.
|
||||
// ---------------------------------------------------
|
||||
$sql = 'INSERT INTO '.$query->table.' (';
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Wrap each column name in keyword identifiers.
|
||||
// ---------------------------------------------------
|
||||
$columns = array();
|
||||
|
||||
foreach (array_keys($values) as $column)
|
||||
{
|
||||
$columns[] = $query->wrap($column);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Concatenate the column names and values.
|
||||
// ---------------------------------------------------
|
||||
return $sql .= implode(', ', $columns).') VALUES ('.$query->parameterize($values).')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a SQL UPDATE statement.
|
||||
*
|
||||
* @param Query $query
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
public static function update($query, $values)
|
||||
{
|
||||
// ---------------------------------------------------
|
||||
// Start the query. Add the table name.
|
||||
// ---------------------------------------------------
|
||||
$sql = 'UPDATE '.$query->table.' SET ';
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Wrap each column name in keyword identifiers.
|
||||
// ---------------------------------------------------
|
||||
$columns = array();
|
||||
|
||||
foreach (array_keys($values) as $column)
|
||||
{
|
||||
$columns[] = $query->wrap($column).' = ?';
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Concatenate the column names and the WHERE clause.
|
||||
// ---------------------------------------------------
|
||||
return $sql .= implode(', ', $columns).' '.$query->where;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a SQL DELETE statement.
|
||||
*
|
||||
* @param Query $query
|
||||
* @return string
|
||||
*/
|
||||
public static function delete($query)
|
||||
{
|
||||
return 'DELETE FROM '.$query->wrap($query->table).' '.$query->where;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user