Merge remote-tracking branch 'upstream/develop' into develop
This commit is contained in:
@@ -80,6 +80,10 @@ class Runner extends Task {
|
||||
// pointing to our temporary configuration file. This allows
|
||||
// us to flexibly run tests for any setup.
|
||||
$path = path('base').'phpunit.xml';
|
||||
|
||||
// fix the spaced directories problem when using the command line
|
||||
// strings with spaces inside should be wrapped in quotes.
|
||||
$path = escapeshellarg($path)
|
||||
|
||||
passthru('phpunit --configuration '.$path);
|
||||
|
||||
|
||||
@@ -218,9 +218,11 @@ abstract class Model {
|
||||
{
|
||||
$model = new static(array(), true);
|
||||
|
||||
if (static::$timestamps) $attributes['updated_at'] = new \DateTime;
|
||||
$model->fill($attributes);
|
||||
|
||||
return $model->query()->where($model->key(), '=', $id)->update($attributes);
|
||||
if (static::$timestamps) $model->timestamp();
|
||||
|
||||
return $model->query()->where($model->key(), '=', $id)->update($model->attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -500,7 +502,7 @@ abstract class Model {
|
||||
*/
|
||||
public function changed($attribute)
|
||||
{
|
||||
return array_get($this->attributes, $attribute) !== array_get($this->original, $attribute);
|
||||
return array_get($this->attributes, $attribute) != array_get($this->original, $attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -536,7 +538,7 @@ abstract class Model {
|
||||
|
||||
foreach ($this->attributes as $key => $value)
|
||||
{
|
||||
if ( ! isset($this->original[$key]) or $value !== $this->original[$key])
|
||||
if ( ! array_key_exists($key, $this->original) or $value !== $this->original[$key])
|
||||
{
|
||||
$dirty[$key] = $value;
|
||||
}
|
||||
@@ -725,7 +727,7 @@ abstract class Model {
|
||||
{
|
||||
foreach (array('attributes', 'relationships') as $source)
|
||||
{
|
||||
if (array_key_exists($key, $this->$source)) return true;
|
||||
if (array_key_exists($key, $this->$source)) return !is_null($this->$source[$key]);
|
||||
}
|
||||
|
||||
if (method_exists($this, $key)) return true;
|
||||
|
||||
@@ -140,7 +140,7 @@ class Query {
|
||||
*/
|
||||
public function select($columns = array('*'))
|
||||
{
|
||||
$this->selects = (array) $columns;
|
||||
$this->selects = is_array($columns) ? $columns : array($columns);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -395,7 +395,7 @@ class Query {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a nested where condition to the query.
|
||||
* Add nested constraints to the query.
|
||||
*
|
||||
* @param Closure $callback
|
||||
* @param string $connector
|
||||
@@ -403,24 +403,7 @@ class Query {
|
||||
*/
|
||||
public function where_nested($callback, $connector = 'AND')
|
||||
{
|
||||
$type = 'where_nested';
|
||||
|
||||
// To handle a nested where statement, we will actually instantiate a new
|
||||
// Query instance and run the callback over that instance, which will
|
||||
// allow the developer to have a fresh query instance
|
||||
$query = new Query($this->connection, $this->grammar, $this->from);
|
||||
|
||||
call_user_func($callback, $query);
|
||||
|
||||
// Once the callback has been run on the query, we will store the nested
|
||||
// query instance on the where clause array so that it's passed to the
|
||||
// query's query grammar instance when building.
|
||||
if ($query->wheres !== null)
|
||||
{
|
||||
$this->wheres[] = compact('type', 'query', 'connector');
|
||||
}
|
||||
|
||||
$this->bindings = array_merge($this->bindings, $query->bindings);
|
||||
call_user_func($callback, $this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ class MySQL extends Grammar {
|
||||
*/
|
||||
protected function unsigned(Table $table, Fluent $column)
|
||||
{
|
||||
if ($column->type == 'integer' && $column->unsigned)
|
||||
if ($column->type == 'integer' && ($column->unsigned || $column->increment))
|
||||
{
|
||||
return ' UNSIGNED';
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
## Laravel 3.2.4
|
||||
|
||||
- Speed up many to many eager loading mapping.
|
||||
- Tweak the Eloquent::changed() method.
|
||||
- Added support for locales in the URI.
|
||||
|
||||
<a name="upgrade-3.2.3"></a>
|
||||
## Upgrading From 3.2.3
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
- [Installation & Setup](/docs/install)
|
||||
- [Requirements](/docs/install#requirements)
|
||||
- [Installation](/docs/install#installation)
|
||||
- [Server Configuration: Why Public?](/docs/install#server-configuration)
|
||||
- [Server Configuration](/docs/install#server-configuration)
|
||||
- [Basic Configuration](/docs/install#basic-configuration)
|
||||
- [Environments](/docs/install#environments)
|
||||
- [Cleaner URLs](/docs/install#cleaner-urls)
|
||||
|
||||
@@ -318,6 +318,10 @@ However, you may often only want to insert a new record into the intermediate ta
|
||||
|
||||
$user->roles()->attach($role_id);
|
||||
|
||||
It's also possible to attach data for fields in the intermediate table (pivot table), to do this add a second array variable to the attach command containing the data you want to attach:
|
||||
|
||||
$user->roles()->attach($role_id, array('expires' => $expires));
|
||||
|
||||
<a name="sync-method"></a>
|
||||
Alternatively, you can use the `sync` method, which accepts an array of IDs to "sync" with the intermediate table. After this operation is complete, only the IDs in the array will be on the intermediate table.
|
||||
|
||||
@@ -406,6 +410,28 @@ You may even eager load nested relationships. For example, let's assume our **Au
|
||||
|
||||
$books = Book::with(array('author', 'author.contacts'))->get();
|
||||
|
||||
If you find yourself eager loading the same models often, you may want to use **$includes** in the model.
|
||||
|
||||
class Book extends Eloquent {
|
||||
|
||||
public $includes = array('author');
|
||||
|
||||
public function author()
|
||||
{
|
||||
return $this->belongs_to('Author');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
**$includes** takes the same arguments that **with** takes. The following is now eagerly loaded.
|
||||
|
||||
foreach (Book::all() as $book)
|
||||
{
|
||||
echo $book->author->name;
|
||||
}
|
||||
|
||||
> **Note:** Using **with** will override a models **$includes**.
|
||||
|
||||
<a name="constraining-eager-loads"></a>
|
||||
## Constraining Eager Loads
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
- [Requirements](#requirements)
|
||||
- [Installation](#installation)
|
||||
- [Server Configuration: Why Public?](#server-configuration)
|
||||
- [Server Configuration](#server-configuration)
|
||||
- [Basic Configuration](#basic-configuration)
|
||||
- [Environments](#environments)
|
||||
- [Cleaner URLs](#cleaner-urls)
|
||||
@@ -23,7 +23,8 @@
|
||||
1. [Download Laravel](http://laravel.com/download)
|
||||
2. Extract the Laravel archive and upload the contents to your web server.
|
||||
3. Set the value of the **key** option in the **config/application.php** file to a random, 32 character string.
|
||||
4. Navigate to your application in a web browser.
|
||||
4. Verify that the `storage/views` directory is writable.
|
||||
5. Navigate to your application in a web browser.
|
||||
|
||||
If all is well, you should see a pretty Laravel splash page. Get ready, there is lots more to learn!
|
||||
|
||||
@@ -43,9 +44,9 @@ If you are having problems installing, try the following:
|
||||
- Verify that your storage folder and the folders within are writable by your web server.
|
||||
|
||||
<a name="server-configuration"></a>
|
||||
## Server Configuration: Why Public?
|
||||
## Server Configuration
|
||||
|
||||
Like most web-development frameworks, Laravel is designed to protect your application code, bundles, and local storage by placing only files that are necessarily public in the web server's DocumentRoot. This prevents some types of server misconfiguration from making your code (including database passwords and other configuration data) accessible through the web server. It's best to be safe.
|
||||
Like most web-development frameworks, Laravel is designed to protect your application code, bundles, and local storage by placing only files that are necessarily public in the web server's DocumentRoot. This prevents some types of server misconfiguration from making your code (including database passwords and other configuration data) accessible through the web server. It's best to be safe.
|
||||
|
||||
In this example let's imagine that we installed Laravel to the directory **/Users/JonSnow/Sites/MySite**.
|
||||
|
||||
@@ -53,15 +54,12 @@ A very basic example of an Apache VirtualHost configuration for MySite might loo
|
||||
|
||||
<VirtualHost *:80>
|
||||
DocumentRoot /Users/JonSnow/Sites/MySite/public
|
||||
ServerName mysite.local
|
||||
ServerName mysite.dev
|
||||
</VirtualHost>
|
||||
|
||||
Notice that while we installed to **/Users/JonSnow/Sites/MySite** our DocumentRoot points to **/Users/JonSnow/Sites/MySite/public**.
|
||||
|
||||
Pointing the DocumentRoot to the public folder is a commonly used best-practice. However, you may need to use Laravel on a host that does not allow you to update your DocumentRoot. This is possible, but before resigning to this option it's best to contact your host and verify that you are unable to change your DocumentRoot to increase the security of your application.
|
||||
|
||||
More information about how to use the public folder can be found on the [Laravel Forums](http://forums.laravel.com/viewtopic.php?pid=10023#p10023).
|
||||
|
||||
While pointing the DocumentRoot to the public folder is a commonly used best-practice, it's possible that you may need to use Laravel on a host that does not allow you to update your DocumentRoot. A collection of algorithms to circumvent this need can be found [on the Laravel forums.](http://forums.laravel.com/viewtopic.php?id=1258)
|
||||
|
||||
<a name="basic-configuration"></a>
|
||||
## Basic Configuration
|
||||
|
||||
@@ -33,7 +33,7 @@ Next, you should create a corresponding **marketing.php** file within the **appl
|
||||
|
||||
Nice! Now you know how to get started setting up your language files and directories. Let's keep localizing!
|
||||
|
||||
<a name="basics"></a>
|
||||
<a name="get"></a>
|
||||
## Retrieving A Language Line
|
||||
|
||||
#### Retrieving a language line:
|
||||
|
||||
@@ -152,6 +152,15 @@ Sometimes you may want to attach a filter to all requests that begin with a give
|
||||
|
||||
Route::filter('pattern: admin/*', 'auth');
|
||||
|
||||
Optionally you can register filters directly when attaching filters to a given URI by supplying an array with the name of the filter and a callback.
|
||||
|
||||
#### Defining a filter and URI pattern based filter in one:
|
||||
|
||||
Route::filter('pattern: admin/*', array('name' => 'auth', function()
|
||||
{
|
||||
//
|
||||
}));
|
||||
|
||||
<a name="global-filters"></a>
|
||||
## Global Filters
|
||||
|
||||
|
||||
@@ -63,6 +63,9 @@ Now you are familiar with the basic usage of the Validator class. You're ready t
|
||||
|
||||
'name' => 'required'
|
||||
|
||||
#### Validate that an attribute is present, when another attribute is present:
|
||||
'last_name' => 'required_with:first_name'
|
||||
|
||||
<a name="rule-alpha"></a>
|
||||
### Alpha, Alpha Numeric, & Alpha Dash
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ class Input {
|
||||
*/
|
||||
public static function has_file($key)
|
||||
{
|
||||
return ! is_null(static::file("{$key}.tmp_name"));
|
||||
return strlen(static::file("{$key}.tmp_name", "")) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -107,6 +107,46 @@ Routing\Router::register('*', '(:all)', function()
|
||||
return Event::first('404');
|
||||
});
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Gather The URI And Locales
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When routing, we'll need to grab the URI and the supported locales for
|
||||
| the route so we can properly set the language and route the request
|
||||
| to the proper end-point in the application.
|
||||
|
|
||||
*/
|
||||
|
||||
$uri = URI::current();
|
||||
|
||||
$locales = Config::get('application.languages', array());
|
||||
|
||||
$locales[] = Config::get('application.language');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Set The Locale Based On Route
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If the URI starts with one of the supported languages, we will set
|
||||
| the default language to match that URI segment and shorten the
|
||||
| URI we'll pass to the router to not include the lang segment.
|
||||
|
|
||||
*/
|
||||
|
||||
foreach ($locales as $locale)
|
||||
{
|
||||
if (starts_with($uri, $locale))
|
||||
{
|
||||
Config::set('application.language', $locale);
|
||||
|
||||
$uri = trim(substr($uri, strlen($locale)), '/'); break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($uri === '') $uri = '/';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Route The Incoming Request
|
||||
@@ -118,8 +158,6 @@ Routing\Router::register('*', '(:all)', function()
|
||||
|
|
||||
*/
|
||||
|
||||
$uri = URI::current();
|
||||
|
||||
Request::$route = Routing\Router::route(Request::method(), $uri);
|
||||
|
||||
$response = Request::$route->call();
|
||||
|
||||
@@ -93,7 +93,7 @@ class Response {
|
||||
*/
|
||||
public static function json($data, $status = 200, $headers = array())
|
||||
{
|
||||
$headers['Content-Type'] = 'application/json';
|
||||
$headers['Content-Type'] = 'application/json; charset=utf-8';
|
||||
|
||||
return new static(json_encode($data), $status, $headers);
|
||||
}
|
||||
@@ -113,7 +113,7 @@ class Response {
|
||||
*/
|
||||
public static function eloquent($data, $status = 200, $headers = array())
|
||||
{
|
||||
$headers['Content-Type'] = 'application/json';
|
||||
$headers['Content-Type'] = 'application/json; charset=utf-8';
|
||||
|
||||
return new static(eloquent_to_json($data), $status, $headers);
|
||||
}
|
||||
|
||||
@@ -213,6 +213,15 @@ class Route {
|
||||
{
|
||||
if (Str::is($pattern, $this->uri))
|
||||
{
|
||||
// If the filter provided is an array then we need to register
|
||||
// the filter before we can assign it to the route.
|
||||
if (is_array($filter))
|
||||
{
|
||||
list($filter, $callback) = array_values($filter);
|
||||
|
||||
Filter::register($filter, $callback);
|
||||
}
|
||||
|
||||
$filters[] = $filter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,14 @@ class URL {
|
||||
|
||||
$root = static::base().'/'.Config::get('application.index');
|
||||
|
||||
// If multiple languages are being supported via URIs, we will append current
|
||||
// language to the URI so all redirects and URLs generated include the
|
||||
// current language so it is not lost on further requests.
|
||||
if (count(Config::get('application.languages')) > 0)
|
||||
{
|
||||
$root .= '/'.Config::get('application.language');
|
||||
}
|
||||
|
||||
// Since SSL is not often used while developing the application, we allow the
|
||||
// developer to disable SSL on all framework generated links to make it more
|
||||
// convenient to work with the site while developing locally.
|
||||
@@ -242,6 +250,11 @@ class URL {
|
||||
$url = str_replace($index.'/', '', $url);
|
||||
}
|
||||
|
||||
if (count(Config::get('application.languages')) > 0)
|
||||
{
|
||||
$url = str_replace(Config::get('application.language').'/', '', $url);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
|
||||
@@ -214,7 +214,7 @@ class Validator {
|
||||
*/
|
||||
protected function implicit($rule)
|
||||
{
|
||||
return $rule == 'required' or $rule == 'accepted';
|
||||
return $rule == 'required' or $rule == 'accepted' or $rule == 'required_with';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,6 +257,27 @@ class Validator {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that an attribute exists in the attributes array, if another
|
||||
* attribute exists in the attributes array.
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param mixed $value
|
||||
* @param array $parameters
|
||||
* @return bool
|
||||
*/
|
||||
protected function validate_required_with($attribute, $value, $parameters)
|
||||
{
|
||||
$other = $parameters[0];
|
||||
|
||||
if ($this->validate_required($other, $this->attributes[$other]))
|
||||
{
|
||||
return $this->validate_required($attribute, $value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that an attribute has a matching confirmation attribute.
|
||||
*
|
||||
|
||||
@@ -551,4 +551,20 @@ class View implements ArrayAccess {
|
||||
return $this->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic Method for handling dynamic functions.
|
||||
*
|
||||
* This method handles calls to dynamic with helpers.
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
if (strpos($method, 'with_') === 0)
|
||||
{
|
||||
$key = substr($method, 5);
|
||||
return $this->with($key, $parameters[0]);
|
||||
}
|
||||
|
||||
throw new \Exception("Method [$method] is not defined on the View class.");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user