Browse Source

Add some events to Eloquent models.

Taylor Otwell 12 years ago
parent
commit
ca06582369

+ 56 - 5
laravel/database/eloquent/model.php

@@ -1,6 +1,7 @@
 <?php namespace Laravel\Database\Eloquent;
 
 use Laravel\Str;
+use Laravel\Event;
 use Laravel\Database;
 use Laravel\Database\Eloquent\Relationships\Has_Many_And_Belongs_To;
 
@@ -115,14 +116,23 @@ abstract class Model {
 	 * Hydrate the model with an array of attributes.
 	 *
 	 * @param  array  $attributes
+	 * @param  bool   $raw
 	 * @return Model
 	 */
-	public function fill($attributes)
+	public function fill(array $attributes, $raw = false)
 	{
-		$attributes = (array) $attributes;
-
 		foreach ($attributes as $key => $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 @@ abstract class Model {
 		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 @@ abstract class Model {
 			$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 @@ abstract class Model {
 		// 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 @@ abstract class Model {
 	{
 		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 @@ abstract class Model {
 		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.
 	 *

+ 2 - 6
laravel/database/eloquent/query.php

@@ -1,5 +1,6 @@
 <?php namespace Laravel\Database\Eloquent;
 
+use Laravel\Event;
 use Laravel\Database;
 use Laravel\Database\Eloquent\Relationships\Has_Many_And_Belongs_To;
 
@@ -119,12 +120,7 @@ class Query {
 			// We need to set the attributes manually in case the accessible property is
 			// set on the array which will prevent the mass assignemnt of attributes if
 			// we were to pass them in using the constructor or fill methods.
-			foreach ($result as $key => $value)
-			{
-				$new->set_attribute($key, $value);
-			}
-
-			$new->original = $new->attributes;
+			$new->fill_raw($result);
 
 			$models[] = $new;
 		}

+ 1 - 0
laravel/documentation/changes.md

@@ -61,6 +61,7 @@
 - `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.
 
 <a name="upgrade-3.2"></a>
 ## Upgrading From 3.1

+ 24 - 18
laravel/event.php

@@ -108,14 +108,17 @@ class Event {
 	 *
 	 *		// 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);
 	 * </code>
 	 *
-	 * @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 @@ class Event {
 		// 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);
+
+					// 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;
 				}
-
-				// 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;
 			}
 		}