diff --git a/laravel/database/eloquent/model.php b/laravel/database/eloquent/model.php index 46fe6c5a..5cf9f7b4 100644 --- a/laravel/database/eloquent/model.php +++ b/laravel/database/eloquent/model.php @@ -1,6 +1,7 @@ $value) { + // If the "raw" flag is set, it means that we'll just load every value from + // the array directly into the attributes, without any accessibility or + // mutators being accounted for. What you pass in is what you get. + if ($raw) + { + $this->set_attribute($key, $value); + + continue; + } + // If the "accessible" property is an array, the developer is limiting the // attributes that may be mass assigned, and we need to verify that the // current attribute is included in that list of allowed attributes. @@ -154,14 +164,29 @@ public function fill($attributes) return $this; } + /** + * Fill the model with the contents of the array. + * + * No mutators or accessibility checks will be accounted for. + * + * @param array $attributes + * @return Model + */ + public function fill_raw(array $attributes) + { + return $this->fill($attributes, true); + } + /** * Set the accessible attributes for the given model. * * @param array $attributes * @return void */ - public static function accessible($attributes) + public static function accessible($attributes = null) { + if (is_null($attributes)) return static::$accessible; + static::$accessible = $attributes; } @@ -355,6 +380,8 @@ public function save() $this->timestamp(); } + $this->fire_event('saving'); + // If the model exists, we only need to update it in the database, and the update // will be considered successful if there is one affected row returned from the // fluent query instance. We'll set the where condition automatically. @@ -382,6 +409,11 @@ public function save() // dirty and subsequent calls won't hit the database. $this->original = $this->attributes; + if ($result) + { + $this->fire_event('saved'); + } + return $result; } @@ -394,7 +426,13 @@ public function delete() { if ($this->exists) { - return $this->query()->where(static::$key, '=', $this->get_key())->delete(); + $this->fire_event('deleting'); + + $result = $this->query()->where(static::$key, '=', $this->get_key())->delete(); + + $this->fire_event('deleted'); + + return $result; } } @@ -585,6 +623,19 @@ public function to_array() return $attributes; } + /** + * Fire a given event for the model. + * + * @param string $event + * @return array + */ + protected function fire_event($event) + { + $events = array("eloquent.{$event}", "eloquent.{$event}: ".get_class($this)); + + Event::fire($events, array($this)); + } + /** * Handle the dynamic retrieval of attributes and associations. * diff --git a/laravel/database/eloquent/query.php b/laravel/database/eloquent/query.php index 0906449e..cf0797bd 100644 --- a/laravel/database/eloquent/query.php +++ b/laravel/database/eloquent/query.php @@ -1,5 +1,6 @@ $value) - { - $new->set_attribute($key, $value); - } - - $new->original = $new->attributes; + $new->fill_raw($result); $models[] = $new; } diff --git a/laravel/documentation/changes.md b/laravel/documentation/changes.md index ae7a57a3..92ea4e12 100644 --- a/laravel/documentation/changes.md +++ b/laravel/documentation/changes.md @@ -61,6 +61,7 @@ ## Laravel 3.2 - `Schema::drop` now accepts `$connection` as second parameter. - Added `Input::merge` method. - Added `Input::replace` method. +- Added `eloquent.saved`, `eloquent.saving`, `eloquent.deleting`, and `eloquent.deleted` events to Eloquent models. ## Upgrading From 3.1 diff --git a/laravel/event.php b/laravel/event.php index 7fdc1368..f5277da1 100644 --- a/laravel/event.php +++ b/laravel/event.php @@ -108,14 +108,17 @@ public static function until($event, $parameters = array()) * * // Fire the "start" event passing an array of parameters * $responses = Event::fire('start', array('Laravel', 'Framework')); + * + * // Fire multiple events with the same parameters + * $responses = Event::fire(array('start', 'loading'), $parameters); * * - * @param string $event - * @param array $parameters - * @param bool $halt + * @param string|array $event + * @param array $parameters + * @param bool $halt * @return array */ - public static function fire($event, $parameters = array(), $halt = false) + public static function fire($events, $parameters = array(), $halt = false) { $responses = array(); @@ -124,24 +127,27 @@ public static function fire($event, $parameters = array(), $halt = false) // If the event has listeners, we will simply iterate through them and call // each listener, passing in the parameters. We will add the responses to // an array of event responses and return the array. - if (static::listeners($event)) + foreach ((array) $events as $event) { - foreach (static::$events[$event] as $callback) + if (static::listeners($event)) { - $response = call_user_func_array($callback, $parameters); - - // If the event is set to halt, we will return the first response - // that is not null. This allows the developer to easily stack - // events but still get the first valid response. - if ($halt and ! is_null($response)) + foreach (static::$events[$event] as $callback) { - return $response; - } + $response = call_user_func_array($callback, $parameters); - // After the handler has been called, we'll add the response to - // an array of responses and return the array to the caller so - // all of the responses can be easily examined. - $responses[] = $response; + // If the event is set to halt, we will return the first response + // that is not null. This allows the developer to easily stack + // events but still get the first valid response. + if ($halt and ! is_null($response)) + { + return $response; + } + + // After the handler has been called, we'll add the response to + // an array of responses and return the array to the caller so + // all of the responses can be easily examined. + $responses[] = $response; + } } }