Merge remote-tracking branch 'laravel/develop' into develop
This commit is contained in:
commit
f16ac134ee
|
@ -11,22 +11,90 @@
|
||||||
| the "singular" and "plural" methods on the Str class to convert a given
|
| the "singular" and "plural" methods on the Str class to convert a given
|
||||||
| word from singular to plural and vice versa.
|
| word from singular to plural and vice versa.
|
||||||
|
|
|
|
||||||
| This simple array is in constrast to the complicated regular expression
|
| Note that the regular expressions are only for inflecting English words.
|
||||||
| patterns used by other frameworks. We think you'll enjoy the speed and
|
| To inflect a non-English string, simply add its singular and plural
|
||||||
| simplicity of this solution.
|
| form to the array of "irregular" word forms.
|
||||||
|
|
|
||||||
| When adding a word to the array, the key should be the singular form,
|
|
||||||
| while the array value should be the plural form. We've included an
|
|
||||||
| example to get you started!
|
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'inflection' => array(
|
'plural' => array(
|
||||||
|
'/(quiz)$/i' => "$1zes",
|
||||||
|
'/^(ox)$/i' => "$1en",
|
||||||
|
'/([m|l])ouse$/i' => "$1ice",
|
||||||
|
'/(matr|vert|ind)ix|ex$/i' => "$1ices",
|
||||||
|
'/(x|ch|ss|sh)$/i' => "$1es",
|
||||||
|
'/([^aeiouy]|qu)y$/i' => "$1ies",
|
||||||
|
'/(hive)$/i' => "$1s",
|
||||||
|
'/(?:([^f])fe|([lr])f)$/i' => "$1$2ves",
|
||||||
|
'/(shea|lea|loa|thie)f$/i' => "$1ves",
|
||||||
|
'/sis$/i' => "ses",
|
||||||
|
'/([ti])um$/i' => "$1a",
|
||||||
|
'/(tomat|potat|ech|her|vet)o$/i' => "$1oes",
|
||||||
|
'/(bu)s$/i' => "$1ses",
|
||||||
|
'/(alias)$/i' => "$1es",
|
||||||
|
'/(octop)us$/i' => "$1i",
|
||||||
|
'/(ax|test)is$/i' => "$1es",
|
||||||
|
'/(us)$/i' => "$1es",
|
||||||
|
'/s$/i' => "s",
|
||||||
|
'/$/' => "s"
|
||||||
|
),
|
||||||
|
|
||||||
'user' => 'users',
|
'singular' => array(
|
||||||
'person' => 'people',
|
'/(quiz)zes$/i' => "$1",
|
||||||
'comment' => 'comments',
|
'/(matr)ices$/i' => "$1ix",
|
||||||
|
'/(vert|ind)ices$/i' => "$1ex",
|
||||||
|
'/^(ox)en$/i' => "$1",
|
||||||
|
'/(alias)es$/i' => "$1",
|
||||||
|
'/(octop|vir)i$/i' => "$1us",
|
||||||
|
'/(cris|ax|test)es$/i' => "$1is",
|
||||||
|
'/(shoe)s$/i' => "$1",
|
||||||
|
'/(o)es$/i' => "$1",
|
||||||
|
'/(bus)es$/i' => "$1",
|
||||||
|
'/([m|l])ice$/i' => "$1ouse",
|
||||||
|
'/(x|ch|ss|sh)es$/i' => "$1",
|
||||||
|
'/(m)ovies$/i' => "$1ovie",
|
||||||
|
'/(s)eries$/i' => "$1eries",
|
||||||
|
'/([^aeiouy]|qu)ies$/i' => "$1y",
|
||||||
|
'/([lr])ves$/i' => "$1f",
|
||||||
|
'/(tive)s$/i' => "$1",
|
||||||
|
'/(hive)s$/i' => "$1",
|
||||||
|
'/(li|wi|kni)ves$/i' => "$1fe",
|
||||||
|
'/(shea|loa|lea|thie)ves$/i' => "$1f",
|
||||||
|
'/(^analy)ses$/i' => "$1sis",
|
||||||
|
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => "$1$2sis",
|
||||||
|
'/([ti])a$/i' => "$1um",
|
||||||
|
'/(n)ews$/i' => "$1ews",
|
||||||
|
'/(h|bl)ouses$/i' => "$1ouse",
|
||||||
|
'/(corpse)s$/i' => "$1",
|
||||||
|
'/(us)es$/i' => "$1",
|
||||||
|
'/(us|ss)$/i' => "$1",
|
||||||
|
'/s$/i' => "",
|
||||||
|
),
|
||||||
|
|
||||||
|
'irregular' => array(
|
||||||
|
'child' => 'children',
|
||||||
|
'foot' => 'feet',
|
||||||
|
'goose' => 'geese',
|
||||||
|
'man' => 'men',
|
||||||
|
'move' => 'moves',
|
||||||
|
'person' => 'people',
|
||||||
|
'sex' => 'sexes',
|
||||||
|
'tooth' => 'teeth',
|
||||||
|
),
|
||||||
|
|
||||||
|
'uncountable' => array(
|
||||||
|
'audio',
|
||||||
|
'equipment',
|
||||||
|
'deer',
|
||||||
|
'fish',
|
||||||
|
'gold',
|
||||||
|
'information',
|
||||||
|
'money',
|
||||||
|
'rice',
|
||||||
|
'police',
|
||||||
|
'series',
|
||||||
|
'sheep',
|
||||||
|
'species',
|
||||||
),
|
),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -84,6 +84,33 @@ protected function grammar()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a callback wrapped in a database transaction.
|
||||||
|
*
|
||||||
|
* @param Closure $callback
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function transaction($callback)
|
||||||
|
{
|
||||||
|
$this->pdo->beginTransaction();
|
||||||
|
|
||||||
|
// After beginning the database transaction, we will call the Closure
|
||||||
|
// so that it can do its database work. If an exception occurs we'll
|
||||||
|
// rollback the transaction and re-throw back to the developer.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
call_user_func($callback);
|
||||||
|
}
|
||||||
|
catch (\Exception $e)
|
||||||
|
{
|
||||||
|
$this->pdo->rollBack();
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->pdo->commit();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a SQL query against the connection and return a single column result.
|
* Execute a SQL query against the connection and return a single column result.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?php namespace Laravel\Database\Eloquent;
|
<?php namespace Laravel\Database\Eloquent;
|
||||||
|
|
||||||
|
use Laravel\Str;
|
||||||
use Laravel\Database;
|
use Laravel\Database;
|
||||||
use Laravel\Database\Eloquent\Relationships\Has_Many_And_Belongs_To;
|
use Laravel\Database\Eloquent\Relationships\Has_Many_And_Belongs_To;
|
||||||
|
|
||||||
|
@ -103,17 +104,6 @@ public function __construct($attributes = array(), $exists = false)
|
||||||
$this->fill($attributes);
|
$this->fill($attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the accessible attributes for the given model.
|
|
||||||
*
|
|
||||||
* @param array $attributes
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function accessible($attributes)
|
|
||||||
{
|
|
||||||
static::$accessible = $attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hydrate the model with an array of attributes.
|
* Hydrate the model with an array of attributes.
|
||||||
*
|
*
|
||||||
|
@ -157,6 +147,17 @@ public function fill($attributes)
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the accessible attributes for the given model.
|
||||||
|
*
|
||||||
|
* @param array $attributes
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function accessible($attributes)
|
||||||
|
{
|
||||||
|
static::$accessible = $attributes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new model and store it in the database.
|
* Create a new model and store it in the database.
|
||||||
*
|
*
|
||||||
|
@ -211,9 +212,7 @@ public static function find($id, $columns = array('*'))
|
||||||
*/
|
*/
|
||||||
public static function all()
|
public static function all()
|
||||||
{
|
{
|
||||||
$model = new static;
|
return with(new static)->query()->get();
|
||||||
|
|
||||||
return $model->query()->get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -420,6 +419,16 @@ public function dirty()
|
||||||
return ! $this->exists or $this->original !== $this->attributes;
|
return ! $this->exists or $this->original !== $this->attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the table associated with the model.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function table()
|
||||||
|
{
|
||||||
|
return static::$table ?: strtolower(Str::plural(basename(get_class($this))));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the dirty attributes for the model.
|
* Get the dirty attributes for the model.
|
||||||
*
|
*
|
||||||
|
@ -501,6 +510,14 @@ public function __get($key)
|
||||||
return $this->relationships[$key];
|
return $this->relationships[$key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Next we'll check if the requested key is in the array of attributes
|
||||||
|
// for the model. These are simply regular properties that typically
|
||||||
|
// correspond to a single column on the database for the model.
|
||||||
|
elseif (array_key_exists($key, $this->attributes))
|
||||||
|
{
|
||||||
|
return $this->{"get_{$key}"}();
|
||||||
|
}
|
||||||
|
|
||||||
// If the item is not a loaded relationship, it may be a relationship
|
// If the item is not a loaded relationship, it may be a relationship
|
||||||
// that hasn't been loaded yet. If it is, we will lazy load it and
|
// that hasn't been loaded yet. If it is, we will lazy load it and
|
||||||
// set the value of the relationship in the relationship array.
|
// set the value of the relationship in the relationship array.
|
||||||
|
|
|
@ -243,7 +243,7 @@ protected function query()
|
||||||
*
|
*
|
||||||
* @return Connection
|
* @return Connection
|
||||||
*/
|
*/
|
||||||
protected function connection()
|
public function connection()
|
||||||
{
|
{
|
||||||
return Database::connection($this->model->connection());
|
return Database::connection($this->model->connection());
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,13 @@ public function results()
|
||||||
/**
|
/**
|
||||||
* Update the parent model of the relationship.
|
* Update the parent model of the relationship.
|
||||||
*
|
*
|
||||||
* @param array $attributes
|
* @param Model|array $attributes
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function update($attributes)
|
public function update($attributes)
|
||||||
{
|
{
|
||||||
|
$attributes = ($attributes instanceof Model) ? $attributes->get_dirty() : $attributes;
|
||||||
|
|
||||||
return $this->model->update($this->foreign_value(), $attributes);
|
return $this->model->update($this->foreign_value(), $attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?php namespace Laravel\Database\Eloquent\Relationships;
|
<?php namespace Laravel\Database\Eloquent\Relationships;
|
||||||
|
|
||||||
|
use Laravel\Str;
|
||||||
use Laravel\Database\Eloquent\Model;
|
use Laravel\Database\Eloquent\Model;
|
||||||
use Laravel\Database\Eloquent\Pivot;
|
use Laravel\Database\Eloquent\Pivot;
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ public function __construct($model, $associated, $table, $foreign, $other)
|
||||||
/**
|
/**
|
||||||
* Determine the joining table name for the relationship.
|
* Determine the joining table name for the relationship.
|
||||||
*
|
*
|
||||||
* By default, the name is the models sorted and concatenated with an underscore.
|
* By default, the name is the models sorted and joined with underscores.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -78,7 +79,7 @@ public function results()
|
||||||
* @param array $joining
|
* @param array $joining
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function add($id, $attributes = array())
|
public function attach($id, $attributes = array())
|
||||||
{
|
{
|
||||||
$joining = array_merge($this->join_record($id), $attributes);
|
$joining = array_merge($this->join_record($id), $attributes);
|
||||||
|
|
||||||
|
@ -88,12 +89,20 @@ public function add($id, $attributes = array())
|
||||||
/**
|
/**
|
||||||
* Insert a new record for the association.
|
* Insert a new record for the association.
|
||||||
*
|
*
|
||||||
* @param array $attributes
|
* @param Model|array $attributes
|
||||||
* @param array $joining
|
* @param array $joining
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function insert($attributes, $joining = array())
|
public function insert($attributes, $joining = array())
|
||||||
{
|
{
|
||||||
|
// If the attributes are actually an instance of a model, we'll just grab the
|
||||||
|
// array of attributes off of the model for saving, allowing the developer
|
||||||
|
// to easily validate the joining models before inserting them.
|
||||||
|
if ($attributes instanceof Model)
|
||||||
|
{
|
||||||
|
$attributes = $attributes->attributes;
|
||||||
|
}
|
||||||
|
|
||||||
$model = $this->model->create($attributes);
|
$model = $this->model->create($attributes);
|
||||||
|
|
||||||
// If the insert was successful, we'll insert a record into the joining table
|
// If the insert was successful, we'll insert a record into the joining table
|
||||||
|
@ -138,9 +147,6 @@ protected function join_record($id)
|
||||||
*/
|
*/
|
||||||
protected function insert_joining($attributes)
|
protected function insert_joining($attributes)
|
||||||
{
|
{
|
||||||
// All joining tables get creation and update timestamps automatically even though
|
|
||||||
// some developers may not need them. This just provides them if necessary since
|
|
||||||
// it would be a pain for the developer to maintain them manually.
|
|
||||||
$attributes['created_at'] = $this->model->get_timestamp();
|
$attributes['created_at'] = $this->model->get_timestamp();
|
||||||
|
|
||||||
$attributes['updated_at'] = $attributes['created_at'];
|
$attributes['updated_at'] = $attributes['created_at'];
|
||||||
|
|
|
@ -7,11 +7,13 @@ class Has_One_Or_Many extends Relationship {
|
||||||
/**
|
/**
|
||||||
* Insert a new record for the association.
|
* Insert a new record for the association.
|
||||||
*
|
*
|
||||||
* @param array $attributes
|
* @param Model|array $attributes
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function insert($attributes)
|
public function insert($attributes)
|
||||||
{
|
{
|
||||||
|
$attributes = ($attributes instanceof Model) ? $attributes->attributes : $attributes;
|
||||||
|
|
||||||
$attributes[$this->foreign_key()] = $this->base->get_key();
|
$attributes[$this->foreign_key()] = $this->base->get_key();
|
||||||
|
|
||||||
return $this->model->create($attributes);
|
return $this->model->create($attributes);
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
<?php namespace Laravel;
|
||||||
|
|
||||||
|
class Pluralizer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "strings" configuration array.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cached copies of the plural inflections.
|
||||||
|
*/
|
||||||
|
protected $plural = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cached copies of the singular inflections.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $singular = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new pluralizer instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($config)
|
||||||
|
{
|
||||||
|
$this->config = $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the singular form of the given word.
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function singular($value)
|
||||||
|
{
|
||||||
|
// First we'll check the cache of inflected values. We cache each word that
|
||||||
|
// is inflected so we don't have to spin through the regular expressions
|
||||||
|
// each time we need to inflect a given value for the developer.
|
||||||
|
if (isset($this->singular[$value]))
|
||||||
|
{
|
||||||
|
return $this->singular[$value];
|
||||||
|
}
|
||||||
|
|
||||||
|
// English words may be automatically inflected using regular expressions.
|
||||||
|
// If the word is english, we'll just pass off the word to the automatic
|
||||||
|
// inflection method and return the result, which is cached.
|
||||||
|
$irregular = $this->config['irregular'];
|
||||||
|
|
||||||
|
$result = $this->auto($value, $this->config['singular'], $irregular);
|
||||||
|
|
||||||
|
return $this->singular[$value] = $result ?: $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the plural form of the given word.
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @param int $count
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function plural($value, $count = 2)
|
||||||
|
{
|
||||||
|
if ((int) $count == 1) return $value;
|
||||||
|
|
||||||
|
// First we'll check the cache of inflected values. We cache each word that
|
||||||
|
// is inflected so we don't have to spin through the regular expressions
|
||||||
|
// each time we need to inflect a given value for the developer.
|
||||||
|
if (isset($this->plural[$value]))
|
||||||
|
{
|
||||||
|
return $this->plural[$value];
|
||||||
|
}
|
||||||
|
|
||||||
|
// English words may be automatically inflected using regular expressions.
|
||||||
|
// If the word is english, we'll just pass off the word to the automatic
|
||||||
|
// inflection method and return the result, which is cached.
|
||||||
|
$irregular = array_flip($this->config['irregular']);
|
||||||
|
|
||||||
|
$result = $this->auto($value, $this->config['plural'], $irregular);
|
||||||
|
|
||||||
|
return $this->plural[$value] = $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform auto inflection on an English word.
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
* @param array $source
|
||||||
|
* @param array $irregular
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function auto($value, $source, $irregular)
|
||||||
|
{
|
||||||
|
// If the word hasn't been cached, we'll check the list of words that
|
||||||
|
// that are "uncountable". This should be a quick look up since we
|
||||||
|
// can just hit the array directly for the value.
|
||||||
|
if (in_array(strtolower($value), $this->config['uncountable']))
|
||||||
|
{
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next we will check the "irregular" patterns, which contains words
|
||||||
|
// like "children" and "teeth" which can not be inflected using the
|
||||||
|
// typically used regular expression matching approach.
|
||||||
|
foreach ($irregular as $irregular => $pattern)
|
||||||
|
{
|
||||||
|
if (preg_match($pattern = '/'.$pattern.'$/i', $value))
|
||||||
|
{
|
||||||
|
return preg_replace($pattern, $irregular, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally we'll spin through the array of regular expressions and
|
||||||
|
// and look for matches for the word. If we find a match we will
|
||||||
|
// cache and return the inflected value for quick look up.
|
||||||
|
foreach ($source as $pattern => $inflected)
|
||||||
|
{
|
||||||
|
if (preg_match($pattern, $value))
|
||||||
|
{
|
||||||
|
return preg_replace($pattern, $inflected, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,6 +2,13 @@
|
||||||
|
|
||||||
class Str {
|
class Str {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The pluralizer instance.
|
||||||
|
*
|
||||||
|
* @var Pluralizer
|
||||||
|
*/
|
||||||
|
public static $pluralizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the default string encoding for the application.
|
* Get the default string encoding for the application.
|
||||||
*
|
*
|
||||||
|
@ -154,25 +161,17 @@ public static function words($value, $words = 100, $end = '...')
|
||||||
/**
|
/**
|
||||||
* Get the singular form of the given word.
|
* Get the singular form of the given word.
|
||||||
*
|
*
|
||||||
* The word should be defined in the "strings" configuration file.
|
|
||||||
*
|
|
||||||
* @param string $value
|
* @param string $value
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function singular($value)
|
public static function singular($value)
|
||||||
{
|
{
|
||||||
$inflection = Config::get('strings.inflection');
|
return static::pluralizer()->singular($value);
|
||||||
|
|
||||||
$singular = array_get(array_flip($inflection), strtolower($value), $value);
|
|
||||||
|
|
||||||
return (ctype_upper($value[0])) ? static::title($singular) : $singular;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the plural form of the given word.
|
* Get the plural form of the given word.
|
||||||
*
|
*
|
||||||
* The word should be defined in the "strings" configuration file.
|
|
||||||
*
|
|
||||||
* <code>
|
* <code>
|
||||||
* // Returns the plural form of "child"
|
* // Returns the plural form of "child"
|
||||||
* $plural = Str::plural('child', 10);
|
* $plural = Str::plural('child', 10);
|
||||||
|
@ -187,11 +186,19 @@ public static function singular($value)
|
||||||
*/
|
*/
|
||||||
public static function plural($value, $count = 2)
|
public static function plural($value, $count = 2)
|
||||||
{
|
{
|
||||||
if ((int) $count == 1) return $value;
|
return static::pluralizer()->plural($value, $count);
|
||||||
|
}
|
||||||
|
|
||||||
$plural = array_get(Config::get('strings.inflection'), strtolower($value), $value);
|
/**
|
||||||
|
* Get the pluralizer instance.
|
||||||
|
*
|
||||||
|
* @return Pluralizer
|
||||||
|
*/
|
||||||
|
protected static function pluralizer()
|
||||||
|
{
|
||||||
|
$config = Config::get('strings');
|
||||||
|
|
||||||
return (ctype_upper($value[0])) ? static::title($plural) : $plural;
|
return static::$pluralizer ?: static::$pluralizer = new Pluralizer($config);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue