1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572 |
- <?php namespace Illuminate\Database\Eloquent;
- use Closure;
- use DateTime;
- use Carbon\Carbon;
- use ArrayAccess;
- use Illuminate\Events\Dispatcher;
- use Illuminate\Database\Connection;
- use Illuminate\Database\Eloquent\Collection;
- use Illuminate\Database\Eloquent\Relations\HasOne;
- use Illuminate\Database\Eloquent\Relations\HasMany;
- use Illuminate\Support\Contracts\JsonableInterface;
- use Illuminate\Support\Contracts\ArrayableInterface;
- use Illuminate\Database\Eloquent\Relations\MorphOne;
- use Illuminate\Database\Eloquent\Relations\MorphMany;
- use Illuminate\Database\Eloquent\Relations\BelongsTo;
- use Illuminate\Database\Query\Builder as QueryBuilder;
- use Illuminate\Database\Eloquent\Relations\BelongsToMany;
- use Illuminate\Database\ConnectionResolverInterface as Resolver;
- abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterface {
- /**
- * The connection name for the model.
- *
- * @var string
- */
- protected $connection;
- /**
- * The table associated with the model.
- *
- * @var string
- */
- protected $table;
- /**
- * The primary key for the model.
- *
- * @var string
- */
- protected $primaryKey = 'id';
- /**
- * The number of models to return for pagination.
- *
- * @var int
- */
- protected $perPage = 15;
- /**
- * Indicates if the IDs are auto-incrementing.
- *
- * @var bool
- */
- public $incrementing = true;
- /**
- * Indicates if the model should be timestamped.
- *
- * @var bool
- */
- public $timestamps = true;
- /**
- * The model's attributes.
- *
- * @var array
- */
- protected $attributes = array();
- /**
- * The model attribute's original state.
- *
- * @var array
- */
- protected $original = array();
- /**
- * The loaded relationships for the model.
- *
- * @var array
- */
- protected $relations = array();
- /**
- * The attributes that should be hidden for arrays.
- *
- * @var array
- */
- protected $hidden = array();
- /**
- * The attributes that should be visible in arrays.
- *
- * @var array
- */
- protected $visible = array();
- /**
- * The accessors to append to the model's array form.
- *
- * @var array
- */
- protected $appends = array();
- /**
- * The attributes that are mass assignable.
- *
- * @var array
- */
- protected $fillable = array();
- /**
- * The attributes that aren't mass assignable.
- *
- * @var array
- */
- protected $guarded = array('*');
- /**
- * The relationships that should be touched on save.
- *
- * @var array
- */
- protected $touches = array();
- /**
- * The relations to eager load on every query.
- *
- * @var array
- */
- protected $with = array();
- /**
- * Indicates if the model exists.
- *
- * @var bool
- */
- public $exists = false;
- /**
- * Indicates if the model should soft delete.
- *
- * @var bool
- */
- protected $softDelete = false;
- /**
- * Indicates whether attributes are snake cased on arrays.
- *
- * @var bool
- */
- public static $snakeAttributes = true;
- /**
- * The connection resolver instance.
- *
- * @var \Illuminate\Database\ConnectionResolverInterface
- */
- protected static $resolver;
- /**
- * The event dispatcher instance.
- *
- * @var \Illuminate\Events\Dispatcher
- */
- protected static $dispatcher;
- /**
- * The array of booted models.
- *
- * @var array
- */
- protected static $booted = array();
- /**
- * Indicates if all mass assignment is enabled.
- *
- * @var bool
- */
- protected static $unguarded = false;
- /**
- * The cache of the mutated attributes for each class.
- *
- * @var array
- */
- protected static $mutatorCache = array();
- /**
- * The name of the "created at" column.
- *
- * @var string
- */
- const CREATED_AT = 'created_at';
- /**
- * The name of the "updated at" column.
- *
- * @var string
- */
- const UPDATED_AT = 'updated_at';
- /**
- * The name of the "deleted at" column.
- *
- * @var string
- */
- const DELETED_AT = 'deleted_at';
- /**
- * Create a new Eloquent model instance.
- *
- * @param array $attributes
- * @return void
- */
- public function __construct(array $attributes = array())
- {
- if ( ! isset(static::$booted[get_class($this)]))
- {
- static::boot();
- static::$booted[get_class($this)] = true;
- }
- $this->fill($attributes);
- }
- /**
- * The "booting" method of the model.
- *
- * @return void
- */
- protected static function boot()
- {
- $class = get_called_class();
- static::$mutatorCache[$class] = array();
- // Here we will extract all of the mutated attributes so that we can quickly
- // spin through them after we export models to their array form, which we
- // need to be fast. This will let us always know the attributes mutate.
- foreach (get_class_methods($class) as $method)
- {
- if (preg_match('/^get(.+)Attribute$/', $method, $matches))
- {
- if (static::$snakeAttributes) $matches[1] = snake_case($matches[1]);
- static::$mutatorCache[$class][] = lcfirst($matches[1]);
- }
- }
- }
- /**
- * Register an observer with the Model.
- *
- * @param object $class
- * @return void
- */
- public static function observe($class)
- {
- $instance = new static;
- $className = get_class($class);
- // When registering a model observer, we will spin through the possible events
- // and determine if this observer has that method. If it does, we will hook
- // it into the model's event system, making it convenient to watch these.
- foreach ($instance->getObservableEvents() as $event)
- {
- if (method_exists($class, $event))
- {
- static::registerModelEvent($event, $className.'@'.$event);
- }
- }
- }
- /**
- * Fill the model with an array of attributes.
- *
- * @param array $attributes
- * @return \Illuminate\Database\Eloquent\Model|static
- */
- public function fill(array $attributes)
- {
- foreach ($attributes as $key => $value)
- {
- $key = $this->removeTableFromKey($key);
- // The developers may choose to place some attributes in the "fillable"
- // array, which means only those attributes may be set through mass
- // assignment to the model, and all others will just be ignored.
- if ($this->isFillable($key))
- {
- $this->setAttribute($key, $value);
- }
- elseif ($this->totallyGuarded())
- {
- throw new MassAssignmentException($key);
- }
- }
- return $this;
- }
- /**
- * Create a new instance of the given model.
- *
- * @param array $attributes
- * @param bool $exists
- * @return \Illuminate\Database\Eloquent\Model|static
- */
- public function newInstance($attributes = array(), $exists = false)
- {
- // This method just provides a convenient way for us to generate fresh model
- // instances of this current model. It is particularly useful during the
- // hydration of new objects via the Eloquent query builder instances.
- $model = new static((array) $attributes);
- $model->exists = $exists;
- return $model;
- }
- /**
- * Create a new model instance that is existing.
- *
- * @param array $attributes
- * @return \Illuminate\Database\Eloquent\Model|static
- */
- public function newFromBuilder($attributes = array())
- {
- $instance = $this->newInstance(array(), true);
- $instance->setRawAttributes((array) $attributes, true);
- return $instance;
- }
- /**
- * Save a new model and return the instance.
- *
- * @param array $attributes
- * @return \Illuminate\Database\Eloquent\Model|static
- */
- public static function create(array $attributes)
- {
- $model = new static($attributes);
- $model->save();
- return $model;
- }
- /**
- * Begin querying the model.
- *
- * @return \Illuminate\Database\Eloquent\Builder|static
- */
- public static function query()
- {
- return with(new static)->newQuery();
- }
- /**
- * Begin querying the model on a given connection.
- *
- * @param string $connection
- * @return \Illuminate\Database\Eloquent\Builder|static
- */
- public static function on($connection = null)
- {
- // First we will just create a fresh instance of this model, and then we can
- // set the connection on the model so that it is be used for the queries
- // we execute, as well as being set on each relationship we retrieve.
- $instance = new static;
- $instance->setConnection($connection);
- return $instance->newQuery();
- }
- /**
- * Get all of the models from the database.
- *
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Collection|static[]
- */
- public static function all($columns = array('*'))
- {
- $instance = new static;
- return $instance->newQuery()->get($columns);
- }
- /**
- * Find a model by its primary key.
- *
- * @param mixed $id
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Model|Collection|static
- */
- public static function find($id, $columns = array('*'))
- {
- $instance = new static;
- if (is_array($id))
- {
- return $instance->newQuery()->whereIn($instance->getKeyName(), $id)->get($columns);
- }
- return $instance->newQuery()->find($id, $columns);
- }
- /**
- * Find a model by its primary key or throw an exception.
- *
- * @param mixed $id
- * @param array $columns
- * @return \Illuminate\Database\Eloquent\Model|Collection|static
- */
- public static function findOrFail($id, $columns = array('*'))
- {
- if ( ! is_null($model = static::find($id, $columns))) return $model;
- throw new ModelNotFoundException;
- }
- /**
- * Eager load relations on the model.
- *
- * @param array|string $relations
- * @return void
- */
- public function load($relations)
- {
- if (is_string($relations)) $relations = func_get_args();
- $query = $this->newQuery()->with($relations);
- $query->eagerLoadRelations(array($this));
- }
- /**
- * Being querying a model with eager loading.
- *
- * @param array|string $relations
- * @return \Illuminate\Database\Eloquent\Builder|static
- */
- public static function with($relations)
- {
- if (is_string($relations)) $relations = func_get_args();
- $instance = new static;
- return $instance->newQuery()->with($relations);
- }
- /**
- * Define a one-to-one relationship.
- *
- * @param string $related
- * @param string $foreignKey
- * @return \Illuminate\Database\Eloquent\Relations\HasOne
- */
- public function hasOne($related, $foreignKey = null)
- {
- $foreignKey = $foreignKey ?: $this->getForeignKey();
- $instance = new $related;
- return new HasOne($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey);
- }
- /**
- * Define a polymorphic one-to-one relationship.
- *
- * @param string $related
- * @param string $name
- * @param string $type
- * @param string $id
- * @return \Illuminate\Database\Eloquent\Relations\MorphOne
- */
- public function morphOne($related, $name, $type = null, $id = null)
- {
- $instance = new $related;
- list($type, $id) = $this->getMorphs($name, $type, $id);
- $table = $instance->getTable();
- return new MorphOne($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id);
- }
- /**
- * Define an inverse one-to-one or many relationship.
- *
- * @param string $related
- * @param string $foreignKey
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function belongsTo($related, $foreignKey = null)
- {
- list(, $caller) = debug_backtrace(false);
- // If no foreign key was supplied, we can use a backtrace to guess the proper
- // foreign key name by using the name of the relationship function, which
- // when combined with an "_id" should conventionally match the columns.
- $relation = $caller['function'];
- if (is_null($foreignKey))
- {
- $foreignKey = snake_case($relation).'_id';
- }
- // Once we have the foreign key names, we'll just create a new Eloquent query
- // for the related models and returns the relationship instance which will
- // actually be responsible for retrieving and hydrating every relations.
- $instance = new $related;
- $query = $instance->newQuery();
- return new BelongsTo($query, $this, $foreignKey, $relation);
- }
- /**
- * Define an polymorphic, inverse one-to-one or many relationship.
- *
- * @param string $name
- * @param string $type
- * @param string $id
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function morphTo($name = null, $type = null, $id = null)
- {
- // If no name is provided, we will use the backtrace to get the function name
- // since that is most likely the name of the polymorphic interface. We can
- // use that to get both the class and foreign key that will be utilized.
- if (is_null($name))
- {
- list(, $caller) = debug_backtrace(false);
- $name = snake_case($caller['function']);
- }
- // Next we will guess the type and ID if necessary. The type and IDs may also
- // be passed into the function so that the developers may manually specify
- // them on the relations. Otherwise, we will just make a great estimate.
- list($type, $id) = $this->getMorphs($name, $type, $id);
- $class = $this->$type;
- return $this->belongsTo($class, $id);
- }
- /**
- * Define a one-to-many relationship.
- *
- * @param string $related
- * @param string $foreignKey
- * @return \Illuminate\Database\Eloquent\Relations\HasMany
- */
- public function hasMany($related, $foreignKey = null)
- {
- $foreignKey = $foreignKey ?: $this->getForeignKey();
- $instance = new $related;
- return new HasMany($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey);
- }
- /**
- * Define a polymorphic one-to-many relationship.
- *
- * @param string $related
- * @param string $name
- * @param string $type
- * @param string $id
- * @return \Illuminate\Database\Eloquent\Relations\MorphMany
- */
- public function morphMany($related, $name, $type = null, $id = null)
- {
- $instance = new $related;
- list($type, $id) = $this->getMorphs($name, $type, $id);
- $table = $instance->getTable();
- return new MorphMany($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id);
- }
- /**
- * Define a many-to-many relationship.
- *
- * @param string $related
- * @param string $table
- * @param string $foreignKey
- * @param string $otherKey
- * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
- */
- public function belongsToMany($related, $table = null, $foreignKey = null, $otherKey = null)
- {
- $caller = $this->getBelongsToManyCaller();
- // First, we'll need to determine the foreign key and "other key" for the
- // relationship. Once we have determined the keys we'll make the query
- // instances as well as the relationship instances we need for this.
- $foreignKey = $foreignKey ?: $this->getForeignKey();
- $instance = new $related;
- $otherKey = $otherKey ?: $instance->getForeignKey();
- // If no table name was provided, we can guess it by concatenating the two
- // models using underscores in alphabetical order. The two model names
- // are transformed to snake case from their default CamelCase also.
- if (is_null($table))
- {
- $table = $this->joiningTable($related);
- }
- // Now we're ready to create a new query builder for the related model and
- // the relationship instances for the relation. The relations will set
- // appropriate query constraint and entirely manages the hydrations.
- $query = $instance->newQuery();
- return new BelongsToMany($query, $this, $table, $foreignKey, $otherKey, $caller['function']);
- }
- /**
- * Get the relationship name of the belongs to many.
- *
- * @return string
- */
- protected function getBelongsToManyCaller()
- {
- $self = __FUNCTION__;
- return array_first(debug_backtrace(false), function($trace) use ($self)
- {
- $caller = $trace['function'];
- return $caller != 'belongsToMany' and $caller != $self;
- });
- }
- /**
- * Get the joining table name for a many-to-many relation.
- *
- * @param string $related
- * @return string
- */
- public function joiningTable($related)
- {
- // The joining table name, by convention, is simply the snake cased models
- // sorted alphabetically and concatenated with an underscore, so we can
- // just sort the models and join them together to get the table name.
- $base = snake_case(class_basename($this));
- $related = snake_case(class_basename($related));
- $models = array($related, $base);
- // Now that we have the model names in an array we can just sort them and
- // use the implode function to join them together with an underscores,
- // which is typically used by convention within the database system.
- sort($models);
- return strtolower(implode('_', $models));
- }
- /**
- * Destroy the models for the given IDs.
- *
- * @param array|int $ids
- * @return void
- */
- public static function destroy($ids)
- {
- $ids = is_array($ids) ? $ids : func_get_args();
- $instance = new static;
- // We will actually pull the models from the database table and call delete on
- // each of them individually so that their events get fired properly with a
- // correct set of attributes in case the developers wants to check these.
- $key = $instance->getKeyName();
- foreach ($instance->whereIn($key, $ids)->get() as $model)
- {
- $model->delete();
- }
- }
- /**
- * Delete the model from the database.
- *
- * @return bool|null
- */
- public function delete()
- {
- if ($this->exists)
- {
- if ($this->fireModelEvent('deleting') === false) return false;
- // Here, we'll touch the owning models, verifying these timestamps get updated
- // for the models. This will allow any caching to get broken on the parents
- // by the timestamp. Then we will go ahead and delete the model instance.
- $this->touchOwners();
- $this->performDeleteOnModel();
- $this->exists = false;
- // Once the model has been deleted, we will fire off the deleted event so that
- // the developers may hook into post-delete operations. We will then return
- // a boolean true as the delete is presumably successful on the database.
- $this->fireModelEvent('deleted', false);
- return true;
- }
- }
- /**
- * Force a hard delete on a soft deleted model.
- *
- * @return void
- */
- public function forceDelete()
- {
- $softDelete = $this->softDelete;
- // We will temporarily disable false delete to allow us to perform the real
- // delete operation against the model. We will then restore the deleting
- // state to what this was prior to this given hard deleting operation.
- $this->softDelete = false;
- $this->delete();
- $this->softDelete = $softDelete;
- }
- /**
- * Perform the actual delete query on this model instance.
- *
- * @return void
- */
- protected function performDeleteOnModel()
- {
- $query = $this->newQuery()->where($this->getKeyName(), $this->getKey());
- if ($this->softDelete)
- {
- $this->{static::DELETED_AT} = $time = $this->freshTimestamp();
- $query->update(array(static::DELETED_AT => $this->fromDateTime($time)));
- }
- else
- {
- $query->delete();
- }
- }
- /**
- * Restore a soft-deleted model instance.
- *
- * @return bool|null
- */
- public function restore()
- {
- if ($this->softDelete)
- {
- // If the restoring event does not return false, we will proceed with this
- // restore operation. Otherwise, we bail out so the developer will stop
- // the restore totally. We will clear the deleted timestamp and save.
- if ($this->fireModelEvent('restoring') === false)
- {
- return false;
- }
- $this->{static::DELETED_AT} = null;
- // Once we have saved the model, we will fire the "restored" event so this
- // developer will do anything they need to after a restore operation is
- // totally finished. Then we will return the result of the save call.
- $result = $this->save();
- $this->fireModelEvent('restored', false);
- return $result;
- }
- }
- /**
- * Register a saving model event with the dispatcher.
- *
- * @param \Closure|string $callback
- * @return void
- */
- public static function saving($callback)
- {
- static::registerModelEvent('saving', $callback);
- }
- /**
- * Register a saved model event with the dispatcher.
- *
- * @param \Closure|string $callback
- * @return void
- */
- public static function saved($callback)
- {
- static::registerModelEvent('saved', $callback);
- }
- /**
- * Register an updating model event with the dispatcher.
- *
- * @param \Closure|string $callback
- * @return void
- */
- public static function updating($callback)
- {
- static::registerModelEvent('updating', $callback);
- }
- /**
- * Register an updated model event with the dispatcher.
- *
- * @param \Closure|string $callback
- * @return void
- */
- public static function updated($callback)
- {
- static::registerModelEvent('updated', $callback);
- }
- /**
- * Register a creating model event with the dispatcher.
- *
- * @param \Closure|string $callback
- * @return void
- */
- public static function creating($callback)
- {
- static::registerModelEvent('creating', $callback);
- }
- /**
- * Register a created model event with the dispatcher.
- *
- * @param \Closure|string $callback
- * @return void
- */
- public static function created($callback)
- {
- static::registerModelEvent('created', $callback);
- }
- /**
- * Register a deleting model event with the dispatcher.
- *
- * @param \Closure|string $callback
- * @return void
- */
- public static function deleting($callback)
- {
- static::registerModelEvent('deleting', $callback);
- }
- /**
- * Register a deleted model event with the dispatcher.
- *
- * @param \Closure|string $callback
- * @return void
- */
- public static function deleted($callback)
- {
- static::registerModelEvent('deleted', $callback);
- }
- /**
- * Register a restoring model event with the dispatcher.
- *
- * @param \Closure|string $callback
- * @return void
- */
- public static function restoring($callback)
- {
- static::registerModelEvent('restoring', $callback);
- }
- /**
- * Register a restored model event with the dispatcher.
- *
- * @param \Closure|string $callback
- * @return void
- */
- public static function restored($callback)
- {
- static::registerModelEvent('restored', $callback);
- }
- /**
- * Remove all of the event listeners for the model.
- *
- * @return void
- */
- public static function flushEventListeners()
- {
- if ( ! isset(static::$dispatcher)) return;
- $instance = new static;
- foreach ($instance->getObservableEvents() as $event)
- {
- static::$dispatcher->forget("eloquent.{$event}: ".get_called_class());
- }
- }
- /**
- * Register a model event with the dispatcher.
- *
- * @param string $event
- * @param \Closure|string $callback
- * @return void
- */
- protected static function registerModelEvent($event, $callback)
- {
- if (isset(static::$dispatcher))
- {
- $name = get_called_class();
- static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback);
- }
- }
- /**
- * Get the observable event names.
- *
- * @return array
- */
- public function getObservableEvents()
- {
- return array(
- 'creating', 'created', 'updating', 'updated',
- 'deleting', 'deleted', 'saving', 'saved',
- 'restoring', 'restored',
- );
- }
- /**
- * Increment a column's value by a given amount.
- *
- * @param string $column
- * @param int $amount
- * @return int
- */
- protected function increment($column, $amount = 1)
- {
- return $this->incrementOrDecrement($column, $amount, 'increment');
- }
- /**
- * Decrement a column's value by a given amount.
- *
- * @param string $column
- * @param int $amount
- * @return int
- */
- protected function decrement($column, $amount = 1)
- {
- return $this->incrementOrDecrement($column, $amount, 'decrement');
- }
- /**
- * Run the increment or decrement method on the model.
- *
- * @param string $column
- * @param int $amount
- * @param string $method
- * @return int
- */
- protected function incrementOrDecrement($column, $amount, $method)
- {
- $query = $this->newQuery();
- if ( ! $this->exists)
- {
- return $query->{$method}($column, $amount);
- }
- return $query->where($this->getKeyName(), $this->getKey())->{$method}($column, $amount);
- }
- /**
- * Update the model in the database.
- *
- * @param array $attributes
- * @return mixed
- */
- public function update(array $attributes = array())
- {
- if ( ! $this->exists)
- {
- return $this->newQuery()->update($attributes);
- }
- return $this->fill($attributes)->save();
- }
- /**
- * Save the model and all of its relationships.
- *
- * @return bool
- */
- public function push()
- {
- if ( ! $this->save()) return false;
- // To sync all of the relationships to the database, we will simply spin through
- // the relationships and save each model via this "push" method, which allows
- // us to recurse into all of these nested relations for the model instance.
- foreach ($this->relations as $models)
- {
- foreach (Collection::make($models) as $model)
- {
- if ( ! $model->push()) return false;
- }
- }
- return true;
- }
- /**
- * Save the model to the database.
- *
- * @param array $options
- * @return bool
- */
- public function save(array $options = array())
- {
- $query = $this->newQueryWithDeleted();
- // If the "saving" event returns false we'll bail out of the save and return
- // false, indicating that the save failed. This gives an opportunities to
- // listeners to cancel save operations if validations fail or whatever.
- if ($this->fireModelEvent('saving') === false)
- {
- return false;
- }
- // If the model already exists in the database we can just update our record
- // that is already in this database using the current IDs in this "where"
- // clause to only update this model. Otherwise, we'll just insert them.
- if ($this->exists)
- {
- $saved = $this->performUpdate($query);
- }
- // If the model is brand new, we'll insert it into our database and set the
- // ID attribute on the model to the value of the newly inserted row's ID
- // which is typically an auto-increment value managed by the database.
- else
- {
- $saved = $this->performInsert($query);
- }
- if ($saved) $this->finishSave($options);
- return $saved;
- }
- /**
- * Finish processing on a successful save operation.
- *
- * @return void
- */
- protected function finishSave(array $options)
- {
- $this->syncOriginal();
- $this->fireModelEvent('saved', false);
- if (array_get($options, 'touch', true)) $this->touchOwners();
- }
- /**
- * Perform a model update operation.
- *
- * @param \Illuminate\Database\Eloquent\Builder
- * @return bool
- */
- protected function performUpdate($query)
- {
- $dirty = $this->getDirty();
- if (count($dirty) > 0)
- {
- // If the updating event returns false, we will cancel the update operation so
- // developers can hook Validation systems into their models and cancel this
- // operation if the model does not pass validation. Otherwise, we update.
- if ($this->fireModelEvent('updating') === false)
- {
- return false;
- }
- // First we need to create a fresh query instance and touch the creation and
- // update timestamp on the model which are maintained by us for developer
- // convenience. Then we will just continue saving the model instances.
- if ($this->timestamps)
- {
- $this->updateTimestamps();
- $dirty = $this->getDirty();
- }
- // Once we have run the update operation, we will fire the "updated" event for
- // this model instance. This will allow developers to hook into these after
- // models are updated, giving them a chance to do any special processing.
- $this->setKeysForSaveQuery($query)->update($dirty);
- $this->fireModelEvent('updated', false);
- }
- return true;
- }
- /**
- * Perform a model insert operation.
- *
- * @param \Illuminate\Database\Eloquent\Builder
- * @return bool
- */
- protected function performInsert($query)
- {
- if ($this->fireModelEvent('creating') === false) return false;
- // First we'll need to create a fresh query instance and touch the creation and
- // update timestamps on this model, which are maintained by us for developer
- // convenience. After, we will just continue saving these model instances.
- if ($this->timestamps)
- {
- $this->updateTimestamps();
- }
- // If the model has an incrementing key, we can use the "insertGetId" method on
- // the query builder, which will give us back the final inserted ID for this
- // table from the database. Not all tables have to be incrementing though.
- $attributes = $this->attributes;
- if ($this->incrementing)
- {
- $this->insertAndSetId($query, $attributes);
- }
- // If the table is not incrementing we'll simply insert this attributes as they
- // are, as this attributes arrays must contain an "id" column already placed
- // there by the developer as the manually determined key for these models.
- else
- {
- $query->insert($attributes);
- }
- // We will go ahead and set the exists property to true, so that it is set when
- // the created event is fired, just in case the developer tries to update it
- // during the event. This will allow them to do so and run an update here.
- $this->exists = true;
- $this->fireModelEvent('created', false);
- return true;
- }
- /**
- * Insert the given attributes and set the ID on the model.
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @param array $attributes
- * @return void
- */
- protected function insertAndSetId($query, $attributes)
- {
- $id = $query->insertGetId($attributes, $keyName = $this->getKeyName());
- $this->setAttribute($keyName, $id);
- }
- /**
- * Touch the owning relations of the model.
- *
- * @return void
- */
- public function touchOwners()
- {
- foreach ($this->touches as $relation)
- {
- $this->$relation()->touch();
- }
- }
- /**
- * Determine if the model touches a given relation.
- *
- * @param string $relation
- * @return bool
- */
- public function touches($relation)
- {
- return in_array($relation, $this->touches);
- }
- /**
- * Fire the given event for the model.
- *
- * @param string $event
- * @param bool $halt
- * @return mixed
- */
- protected function fireModelEvent($event, $halt = true)
- {
- if ( ! isset(static::$dispatcher)) return true;
- // We will append the names of the class to the event to distinguish it from
- // other model events that are fired, allowing us to listen on each model
- // event set individually instead of catching event for all the models.
- $event = "eloquent.{$event}: ".get_class($this);
- $method = $halt ? 'until' : 'fire';
- return static::$dispatcher->$method($event, $this);
- }
- /**
- * Set the keys for a save update query.
- *
- * @param \Illuminate\Database\Eloquent\Builder
- * @return \Illuminate\Database\Eloquent\Builder
- */
- protected function setKeysForSaveQuery($query)
- {
- $query->where($this->getKeyName(), '=', $this->getKey());
- return $query;
- }
- /**
- * Update the model's update timestamp.
- *
- * @return bool
- */
- public function touch()
- {
- $this->updateTimestamps();
- return $this->save();
- }
- /**
- * Update the creation and update timestamps.
- *
- * @return void
- */
- protected function updateTimestamps()
- {
- $time = $this->freshTimestamp();
- if ( ! $this->isDirty(static::UPDATED_AT))
- {
- $this->setUpdatedAt($time);
- }
- if ( ! $this->exists and ! $this->isDirty(static::CREATED_AT))
- {
- $this->setCreatedAt($time);
- }
- }
- /**
- * Set the value of the "created at" attribute.
- *
- * @param mixed $value
- * @return void
- */
- public function setCreatedAt($value)
- {
- $this->{static::CREATED_AT} = $value;
- }
- /**
- * Set the value of the "updated at" attribute.
- *
- * @param mixed $value
- * @return void
- */
- public function setUpdatedAt($value)
- {
- $this->{static::UPDATED_AT} = $value;
- }
- /**
- * Get the name of the "created at" column.
- *
- * @return string
- */
- public function getCreatedAtColumn()
- {
- return static::CREATED_AT;
- }
- /**
- * Get the name of the "updated at" column.
- *
- * @return string
- */
- public function getUpdatedAtColumn()
- {
- return static::UPDATED_AT;
- }
- /**
- * Get the name of the "deleted at" column.
- *
- * @return string
- */
- public function getDeletedAtColumn()
- {
- return static::DELETED_AT;
- }
- /**
- * Get the fully qualified "deleted at" column.
- *
- * @return string
- */
- public function getQualifiedDeletedAtColumn()
- {
- return $this->getTable().'.'.$this->getDeletedAtColumn();
- }
- /**
- * Get a fresh timestamp for the model.
- *
- * @return DateTime
- */
- public function freshTimestamp()
- {
- return new DateTime;
- }
- /**
- * Get a fresh timestamp for the model.
- *
- * @return DateTime
- */
- public function freshTimestampString()
- {
- return $this->fromDateTime($this->freshTimestamp());
- }
- /**
- * Get a new query builder for the model's table.
- *
- * @param bool $excludeDeleted
- * @return \Illuminate\Database\Eloquent\Builder|static
- */
- public function newQuery($excludeDeleted = true)
- {
- $builder = new Builder($this->newBaseQueryBuilder());
- // Once we have the query builders, we will set the model instances so the
- // builder can easily access any information it may need from the model
- // while it is constructing and executing various queries against it.
- $builder->setModel($this)->with($this->with);
- if ($excludeDeleted and $this->softDelete)
- {
- $builder->whereNull($this->getQualifiedDeletedAtColumn());
- }
- return $builder;
- }
- /**
- * Get a new query builder that includes soft deletes.
- *
- * @return \Illuminate\Database\Eloquent\Builder|static
- */
- public function newQueryWithDeleted()
- {
- return $this->newQuery(false);
- }
- /**
- * Determine if the model instance has been soft-deleted.
- *
- * @return bool
- */
- public function trashed()
- {
- return $this->softDelete and ! is_null($this->{static::DELETED_AT});
- }
- /**
- * Get a new query builder that includes soft deletes.
- *
- * @return \Illuminate\Database\Eloquent\Builder|static
- */
- public static function withTrashed()
- {
- return with(new static)->newQueryWithDeleted();
- }
- /**
- * Get a new query builder that only includes soft deletes.
- *
- * @return \Illuminate\Database\Eloquent\Builder|static
- */
- public static function onlyTrashed()
- {
- $instance = new static;
- $column = $instance->getQualifiedDeletedAtColumn();
- return $instance->newQueryWithDeleted()->whereNotNull($column);
- }
- /**
- * Get a new query builder instance for the connection.
- *
- * @return \Illuminate\Database\Query\Builder
- */
- protected function newBaseQueryBuilder()
- {
- $conn = $this->getConnection();
- $grammar = $conn->getQueryGrammar();
- return new QueryBuilder($conn, $grammar, $conn->getPostProcessor());
- }
- /**
- * Create a new Eloquent Collection instance.
- *
- * @param array $models
- * @return \Illuminate\Database\Eloquent\Collection
- */
- public function newCollection(array $models = array())
- {
- return new Collection($models);
- }
- /**
- * Get the table associated with the model.
- *
- * @return string
- */
- public function getTable()
- {
- if (isset($this->table)) return $this->table;
- return str_replace('\\', '', snake_case(str_plural(class_basename($this))));
- }
- /**
- * Set the table associated with the model.
- *
- * @param string $table
- * @return void
- */
- public function setTable($table)
- {
- $this->table = $table;
- }
- /**
- * Get the value of the model's primary key.
- *
- * @return mixed
- */
- public function getKey()
- {
- return $this->getAttribute($this->getKeyName());
- }
- /**
- * Get the primary key for the model.
- *
- * @return string
- */
- public function getKeyName()
- {
- return $this->primaryKey;
- }
- /**
- * Get the table qualified key name.
- *
- * @return string
- */
- public function getQualifiedKeyName()
- {
- return $this->getTable().'.'.$this->getKeyName();
- }
- /**
- * Determine if the model uses timestamps.
- *
- * @return bool
- */
- public function usesTimestamps()
- {
- return $this->timestamps;
- }
- /**
- * Determine if the model instance uses soft deletes.
- *
- * @return bool
- */
- public function isSoftDeleting()
- {
- return $this->softDelete;
- }
- /**
- * Set the soft deleting property on the model.
- *
- * @param bool $enabled
- * @return void
- */
- public function setSoftDeleting($enabled)
- {
- $this->softDelete = $enabled;
- }
- /**
- * Get the polymorphic relationship columns.
- *
- * @param string $name
- * @param string $type
- * @param string $id
- * @return array
- */
- protected function getMorphs($name, $type, $id)
- {
- $type = $type ?: $name.'_type';
- $id = $id ?: $name.'_id';
- return array($type, $id);
- }
- /**
- * Get the number of models to return per page.
- *
- * @return int
- */
- public function getPerPage()
- {
- return $this->perPage;
- }
- /**
- * Set the number of models ot return per page.
- *
- * @param int $perPage
- * @return void
- */
- public function setPerPage($perPage)
- {
- $this->perPage = $perPage;
- }
- /**
- * Get the default foreign key name for the model.
- *
- * @return string
- */
- public function getForeignKey()
- {
- return snake_case(class_basename($this)).'_id';
- }
- /**
- * Get the hidden attributes for the model.
- *
- * @return array
- */
- public function getHidden()
- {
- return $this->hidden;
- }
- /**
- * Set the hidden attributes for the model.
- *
- * @param array $hidden
- * @return void
- */
- public function setHidden(array $hidden)
- {
- $this->hidden = $hidden;
- }
- /**
- * Set the visible attributes for the model.
- *
- * @param array $visible
- * @return void
- */
- public function setVisible(array $visible)
- {
- $this->visible = $visible;
- }
- /**
- * Set the accessors to append to model arrays.
- *
- * @param array $appends
- * @return void
- */
- public function setAppends(array $appends)
- {
- $this->appends = $appends;
- }
- /**
- * Get the fillable attributes for the model.
- *
- * @return array
- */
- public function getFillable()
- {
- return $this->fillable;
- }
- /**
- * Set the fillable attributes for the model.
- *
- * @param array $fillable
- * @return \Illuminate\Database\Eloquent\Model
- */
- public function fillable(array $fillable)
- {
- $this->fillable = $fillable;
- return $this;
- }
- /**
- * Set the guarded attributes for the model.
- *
- * @param array $guarded
- * @return \Illuminate\Database\Eloquent\Model
- */
- public function guard(array $guarded)
- {
- $this->guarded = $guarded;
- return $this;
- }
- /**
- * Disable all mass assignable restrictions.
- *
- * @return void
- */
- public static function unguard()
- {
- static::$unguarded = true;
- }
- /**
- * Enable the mass assignment restrictions.
- *
- * @return void
- */
- public static function reguard()
- {
- static::$unguarded = false;
- }
- /**
- * Set "unguard" to a given state.
- *
- * @param bool $state
- * @return void
- */
- public static function setUnguardState($state)
- {
- static::$unguarded = $state;
- }
- /**
- * Determine if the given attribute may be mass assigned.
- *
- * @param string $key
- * @return bool
- */
- public function isFillable($key)
- {
- if (static::$unguarded) return true;
- // If the key is in the "fillable" array, we can of course assume tha it is
- // a fillable attribute. Otherwise, we will check the guarded array when
- // we need to determine if the attribute is black-listed on the model.
- if (in_array($key, $this->fillable)) return true;
- if ($this->isGuarded($key)) return false;
- return empty($this->fillable) and ! starts_with($key, '_');
- }
- /**
- * Determine if the given key is guarded.
- *
- * @param string $key
- * @return bool
- */
- public function isGuarded($key)
- {
- return in_array($key, $this->guarded) or $this->guarded == array('*');
- }
- /**
- * Determine if the model is totally guarded.
- *
- * @return bool
- */
- public function totallyGuarded()
- {
- return count($this->fillable) == 0 and $this->guarded == array('*');
- }
- /**
- * Remove the table name from a given key.
- *
- * @param string $key
- * @return string
- */
- protected function removeTableFromKey($key)
- {
- if ( ! str_contains($key, '.')) return $key;
- return last(explode('.', $key));
- }
- /**
- * Get the relationships that are touched on save.
- *
- * @return array
- */
- public function getTouchedRelations()
- {
- return $this->touches;
- }
- /**
- * Set the relationships that are touched on save.
- *
- * @param array $touches
- * @return void
- */
- public function setTouchedRelations(array $touches)
- {
- $this->touches = $touches;
- }
- /**
- * Get the value indicating whether the IDs are incrementing.
- *
- * @return bool
- */
- public function getIncrementing()
- {
- return $this->incrementing;
- }
- /**
- * Set whether IDs are incrementing.
- *
- * @param bool $value
- * @return void
- */
- public function setIncrementing($value)
- {
- $this->incrementing = $value;
- }
- /**
- * Convert the model instance to JSON.
- *
- * @param int $options
- * @return string
- */
- public function toJson($options = 0)
- {
- return json_encode($this->toArray(), $options);
- }
- /**
- * Convert the model instance to an array.
- *
- * @return array
- */
- public function toArray()
- {
- $attributes = $this->attributesToArray();
- return array_merge($attributes, $this->relationsToArray());
- }
- /**
- * Convert the model's attributes to an array.
- *
- * @return array
- */
- public function attributesToArray()
- {
- $attributes = $this->getArrayableAttributes();
- // We want to spin through all the mutated attributes for this model and call
- // the mutator for the attribute. We cache off every mutated attributes so
- // we don't have to constantly check on attributes that actually change.
- foreach ($this->getMutatedAttributes() as $key)
- {
- if ( ! array_key_exists($key, $attributes)) continue;
- $attributes[$key] = $this->mutateAttribute(
- $key, $attributes[$key]
- );
- }
- // Here we will grab all of the appended, calculated attributes to this model
- // as these attributes are not really in the attributes array, but are run
- // when we need to array or JSON the model for convenience to the coder.
- foreach ($this->appends as $key)
- {
- $attributes[$key] = $this->mutateAttribute($key, null);
- }
- return $attributes;
- }
- /**
- * Get an attribute array of all arrayable attributes.
- *
- * @return array
- */
- protected function getArrayableAttributes()
- {
- return $this->getArrayableItems($this->attributes);
- }
- /**
- * Get the model's relationships in array form.
- *
- * @return array
- */
- public function relationsToArray()
- {
- $attributes = array();
- foreach ($this->getArrayableRelations() as $key => $value)
- {
- if (in_array($key, $this->hidden)) continue;
- // If the values implements the Arrayable interface we can just call this
- // toArray method on the instances which will convert both models and
- // collections to their proper array form and we'll set the values.
- if ($value instanceof ArrayableInterface)
- {
- $relation = $value->toArray();
- }
- // If the value is null, we'll still go ahead and set it in this list of
- // attributes since null is used to represent empty relationships if
- // if it a has one or belongs to type relationships on the models.
- elseif (is_null($value))
- {
- $relation = $value;
- }
- // If the relationships snake-casing is enabled, we will snake case this
- // key so that the relation attribute is snake cased in this returned
- // array to the developer, making this consisntent with attributes.
- if (static::$snakeAttributes)
- {
- $key = snake_case($key);
- }
- // If the relation value has been set, we will set it on this attributes
- // list for returning. If it was not arrayable or null, we'll not set
- // the value on the array because it is some type of invalid value.
- if (isset($relation) or is_null($value))
- {
- $attributes[$key] = $relation;
- }
- }
- return $attributes;
- }
- /**
- * Get an attribute array of all arrayable relations.
- *
- * @return array
- */
- protected function getArrayableRelations()
- {
- return $this->getArrayableItems($this->relations);
- }
- /**
- * Get an attribute array of all arrayable values.
- *
- * @param array $values
- * @return array
- */
- protected function getArrayableItems(array $values)
- {
- if (count($this->visible) > 0)
- {
- return array_intersect_key($values, array_flip($this->visible));
- }
- return array_diff_key($values, array_flip($this->hidden));
- }
- /**
- * Get an attribute from the model.
- *
- * @param string $key
- * @return mixed
- */
- public function getAttribute($key)
- {
- $inAttributes = array_key_exists($key, $this->attributes);
- // If the key references an attribute, we can just go ahead and return the
- // plain attribute value from the model. This allows every attribute to
- // be dynamically accessed through the _get method without accessors.
- if ($inAttributes or $this->hasGetMutator($key))
- {
- return $this->getAttributeValue($key);
- }
- // If the key already exists in the relationships array, it just means the
- // relationship has already been loaded, so we'll just return it out of
- // here because there is no need to query within the relations twice.
- if (array_key_exists($key, $this->relations))
- {
- return $this->relations[$key];
- }
- // If the "attribute" exists as a method on the model, we will just assume
- // it is a relationship and will load and return results from the query
- // and hydrate the relationship's value on the "relationships" array.
- $camelKey = camel_case($key);
- if (method_exists($this, $camelKey))
- {
- $relations = $this->$camelKey()->getResults();
- return $this->relations[$key] = $relations;
- }
- }
- /**
- * Get a plain attribute (not a relationship).
- *
- * @param string $key
- * @return mixed
- */
- protected function getAttributeValue($key)
- {
- $value = $this->getAttributeFromArray($key);
- // If the attribute has a get mutator, we will call that then return what
- // it returns as the value, which is useful for transforming values on
- // retrieval from the model to a form that is more useful for usage.
- if ($this->hasGetMutator($key))
- {
- return $this->mutateAttribute($key, $value);
- }
- // If the attribute is listed as a date, we will convert it to a DateTime
- // instance on retrieval, which makes it quite convenient to work with
- // date fields without having to create a mutator for each property.
- elseif (in_array($key, $this->getDates()))
- {
- if ($value) return $this->asDateTime($value);
- }
- return $value;
- }
- /**
- * Get an attribute from the $attributes array.
- *
- * @param string $key
- * @return mixed
- */
- protected function getAttributeFromArray($key)
- {
- if (array_key_exists($key, $this->attributes))
- {
- return $this->attributes[$key];
- }
- }
- /**
- * Determine if a get mutator exists for an attribute.
- *
- * @param string $key
- * @return bool
- */
- public function hasGetMutator($key)
- {
- return method_exists($this, 'get'.studly_case($key).'Attribute');
- }
- /**
- * Get the value of an attribute using its mutator.
- *
- * @param string $key
- * @param mixed $value
- * @return mixed
- */
- protected function mutateAttribute($key, $value)
- {
- return $this->{'get'.studly_case($key).'Attribute'}($value);
- }
- /**
- * Set a given attribute on the model.
- *
- * @param string $key
- * @param mixed $value
- * @return void
- */
- public function setAttribute($key, $value)
- {
- // First we will check for the presence of a mutator for the set operation
- // which simply lets the developers tweak the attribute as it is set on
- // the model, such as "json_encoding" an listing of data for storage.
- if ($this->hasSetMutator($key))
- {
- $method = 'set'.studly_case($key).'Attribute';
- return $this->{$method}($value);
- }
- // If an attribute is listed as a "date", we'll convert it from a DateTime
- // instance into a form proper for storage on the database tables using
- // the connection grammar's date format. We will auto set the values.
- elseif (in_array($key, $this->getDates()))
- {
- if ($value)
- {
- $value = $this->fromDateTime($value);
- }
- }
- $this->attributes[$key] = $value;
- }
- /**
- * Determine if a set mutator exists for an attribute.
- *
- * @param string $key
- * @return bool
- */
- public function hasSetMutator($key)
- {
- return method_exists($this, 'set'.studly_case($key).'Attribute');
- }
- /**
- * Get the attributes that should be converted to dates.
- *
- * @return array
- */
- public function getDates()
- {
- return array(static::CREATED_AT, static::UPDATED_AT, static::DELETED_AT);
- }
- /**
- * Convert a DateTime to a storable string.
- *
- * @param DateTime|int $value
- * @return string
- */
- public function fromDateTime($value)
- {
- $format = $this->getDateFormat();
- // If the value is already a DateTime instance, we will just skip the rest of
- // these checks since they will be a waste of time, and hinder performance
- // when checking the field. We will just return the DateTime right away.
- if ($value instanceof DateTime)
- {
- //
- }
- // If the value is totally numeric, we will assume it is a UNIX timestamp and
- // format the date as such. Once we have the date in DateTime form we will
- // format it according to the proper format for the database connection.
- elseif (is_numeric($value))
- {
- $value = Carbon::createFromTimestamp($value);
- }
- // If the value is in simple year, month, day format, we will format it using
- // that setup. This is for simple "date" fields which do not have hours on
- // the field. This conveniently picks up those dates and format correct.
- elseif (preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $value))
- {
- $value = Carbon::createFromFormat('Y-m-d', $value);
- }
- // If this value is some other type of string, we'll create the DateTime with
- // the format used by the database connection. Once we get the instance we
- // can return back the finally formatted DateTime instances to the devs.
- elseif ( ! $value instanceof DateTime)
- {
- $value = Carbon::createFromFormat($format, $value);
- }
- return $value->format($format);
- }
- /**
- * Return a timestamp as DateTime object.
- *
- * @param mixed $value
- * @return DateTime
- */
- protected function asDateTime($value)
- {
- // If this value is an integer, we will assume it is a UNIX timestamp's value
- // and format a Carbon object from this timestamp. This allows flexibility
- // when defining your date fields as they might be UNIX timestamps here.
- if (is_numeric($value))
- {
- return Carbon::createFromTimestamp($value);
- }
- // If the value is in simply year, month, day format, we will instantiate the
- // Carbon instances from that fomrat. Again, this provides for simple date
- // fields on the database, while still supporting Carbonized conversion.
- elseif (preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $value))
- {
- return Carbon::createFromFormat('Y-m-d', $value);
- }
- // Finally, we will just assume this date is in the format used by default on
- // the database connection and use that format to create the Carbon object
- // that is returned back out to the developers after we convert it here.
- elseif ( ! $value instanceof DateTime)
- {
- $format = $this->getDateFormat();
- return Carbon::createFromFormat($format, $value);
- }
- return Carbon::instance($value);
- }
- /**
- * Get the format for database stored dates.
- *
- * @return string
- */
- protected function getDateFormat()
- {
- return $this->getConnection()->getQueryGrammar()->getDateFormat();
- }
- /**
- * Clone the model into a new, non-existing instance.
- *
- * @return \Illuminate\Database\Eloquent\Model
- */
- public function replicate()
- {
- $attributes = array_except($this->attributes, array($this->getKeyName()));
- with($instance = new static)->setRawAttributes($attributes);
- return $instance->setRelations($this->relations);
- }
- /**
- * Get all of the current attributes on the model.
- *
- * @return array
- */
- public function getAttributes()
- {
- return $this->attributes;
- }
- /**
- * Set the array of model attributes. No checking is done.
- *
- * @param array $attributes
- * @param bool $sync
- * @return void
- */
- public function setRawAttributes(array $attributes, $sync = false)
- {
- $this->attributes = $attributes;
- if ($sync) $this->syncOriginal();
- }
- /**
- * Get the model's original attribute values.
- *
- * @param string $key
- * @param mixed $default
- * @return array
- */
- public function getOriginal($key = null, $default = null)
- {
- return array_get($this->original, $key, $default);
- }
- /**
- * Sync the original attributes with the current.
- *
- * @return \Illuminate\Database\Eloquent\Model
- */
- public function syncOriginal()
- {
- $this->original = $this->attributes;
- return $this;
- }
- /**
- * Determine if a given attribute is dirty.
- *
- * @param string $attribute
- * @return bool
- */
- public function isDirty($attribute)
- {
- return array_key_exists($attribute, $this->getDirty());
- }
- /**
- * Get the attributes that have been changed since last sync.
- *
- * @return array
- */
- public function getDirty()
- {
- $dirty = array();
- foreach ($this->attributes as $key => $value)
- {
- if ( ! array_key_exists($key, $this->original) or $value !== $this->original[$key])
- {
- $dirty[$key] = $value;
- }
- }
- return $dirty;
- }
- /**
- * Get all the loaded relations for the instance.
- *
- * @return array
- */
- public function getRelations()
- {
- return $this->relations;
- }
- /**
- * Get a specified relationship.
- *
- * @param string $relation
- * @return mixed
- */
- public function getRelation($relation)
- {
- return $this->relations[$relation];
- }
- /**
- * Set the specific relationship in the model.
- *
- * @param string $relation
- * @param mixed $value
- * @return \Illuminate\Database\Eloquent\Model
- */
- public function setRelation($relation, $value)
- {
- $this->relations[$relation] = $value;
- return $this;
- }
- /**
- * Set the entire relations array on the model.
- *
- * @param array $relations
- * @return \Illuminate\Database\Eloquent\Model
- */
- public function setRelations(array $relations)
- {
- $this->relations = $relations;
- return $this;
- }
- /**
- * Get the database connection for the model.
- *
- * @return \Illuminate\Database\Connection
- */
- public function getConnection()
- {
- return static::resolveConnection($this->connection);
- }
- /**
- * Get the current connection name for the model.
- *
- * @return string
- */
- public function getConnectionName()
- {
- return $this->connection;
- }
- /**
- * Set the connection associated with the model.
- *
- * @param string $name
- * @return \Illuminate\Database\Eloquent\Model
- */
- public function setConnection($name)
- {
- $this->connection = $name;
- return $this;
- }
- /**
- * Resolve a connection instance.
- *
- * @param string $connection
- * @return \Illuminate\Database\Connection
- */
- public static function resolveConnection($connection = null)
- {
- return static::$resolver->connection($connection);
- }
- /**
- * Get the connection resolver instance.
- *
- * @return \Illuminate\Database\ConnectionResolverInterface
- */
- public static function getConnectionResolver()
- {
- return static::$resolver;
- }
- /**
- * Set the connection resolver instance.
- *
- * @param \Illuminate\Database\ConnectionResolverInterface $resolver
- * @return void
- */
- public static function setConnectionResolver(Resolver $resolver)
- {
- static::$resolver = $resolver;
- }
- /**
- * Get the event dispatcher instance.
- *
- * @return \Illuminate\Events\Dispatcher
- */
- public static function getEventDispatcher()
- {
- return static::$dispatcher;
- }
- /**
- * Set the event dispatcher instance.
- *
- * @param \Illuminate\Events\Dispatcher $dispatcher
- * @return void
- */
- public static function setEventDispatcher(Dispatcher $dispatcher)
- {
- static::$dispatcher = $dispatcher;
- }
- /**
- * Unset the event dispatcher for models.
- *
- * @return void
- */
- public static function unsetEventDispatcher()
- {
- static::$dispatcher = null;
- }
- /**
- * Get the mutated attributes for a given instance.
- *
- * @return array
- */
- public function getMutatedAttributes()
- {
- $class = get_class($this);
- if (isset(static::$mutatorCache[$class]))
- {
- return static::$mutatorCache[get_class($this)];
- }
- return array();
- }
- /**
- * Dynamically retrieve attributes on the model.
- *
- * @param string $key
- * @return mixed
- */
- public function __get($key)
- {
- return $this->getAttribute($key);
- }
- /**
- * Dynamically set attributes on the model.
- *
- * @param string $key
- * @param mixed $value
- * @return void
- */
- public function __set($key, $value)
- {
- $this->setAttribute($key, $value);
- }
- /**
- * Determine if the given attribute exists.
- *
- * @param mixed $offset
- * @return bool
- */
- public function offsetExists($offset)
- {
- return isset($this->$offset);
- }
- /**
- * Get the value for a given offset.
- *
- * @param mixed $offset
- * @return mixed
- */
- public function offsetGet($offset)
- {
- return $this->$offset;
- }
- /**
- * Set the value for a given offset.
- *
- * @param mixed $offset
- * @param mixed $value
- * @return void
- */
- public function offsetSet($offset, $value)
- {
- $this->$offset = $value;
- }
- /**
- * Unset the value for a given offset.
- *
- * @param mixed $offset
- * @return void
- */
- public function offsetUnset($offset)
- {
- unset($this->$offset);
- }
- /**
- * Determine if an attribute exists on the model.
- *
- * @param string $key
- * @return void
- */
- public function __isset($key)
- {
- return isset($this->attributes[$key]) or isset($this->relations[$key]);
- }
- /**
- * Unset an attribute on the model.
- *
- * @param string $key
- * @return void
- */
- public function __unset($key)
- {
- unset($this->attributes[$key]);
- unset($this->relations[$key]);
- }
- /**
- * Handle dynamic method calls into the method.
- *
- * @param string $method
- * @param array $parameters
- * @return mixed
- */
- public function __call($method, $parameters)
- {
- if (in_array($method, array('increment', 'decrement')))
- {
- return call_user_func_array(array($this, $method), $parameters);
- }
- $query = $this->newQuery();
- return call_user_func_array(array($query, $method), $parameters);
- }
- /**
- * Handle dynamic static method calls into the method.
- *
- * @param string $method
- * @param array $parameters
- * @return mixed
- */
- public static function __callStatic($method, $parameters)
- {
- $instance = new static;
- return call_user_func_array(array($instance, $method), $parameters);
- }
- /**
- * Convert the model to its string representation.
- *
- * @return string
- */
- public function __toString()
- {
- return $this->toJson();
- }
- }
|