From caebda4bd476dbe785257a0b2e00caa998dd03ba Mon Sep 17 00:00:00 2001 From: Pieter De Moor Date: Sun, 14 Dec 2014 15:41:05 +0100 Subject: [PATCH] Addition of creation and initiation methods Addition of findOrNew, firstOrNew, firstOrCreate, updateOrCreate to BelongsToMany, HasOneOrMany and MorphOneOrMany. --- .../Eloquent/Relations/BelongsToMany.php | 74 ++++++++++++++++ .../Eloquent/Relations/HasOneOrMany.php | 76 +++++++++++++++++ .../Eloquent/Relations/MorphOneOrMany.php | 85 +++++++++++++++++++ 3 files changed, 235 insertions(+) diff --git a/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php b/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php index 58d8be931cae..341bfe44a954 100755 --- a/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php +++ b/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php @@ -513,6 +513,80 @@ public function saveMany(array $models, array $joinings = array()) return $models; } + /** + * Find a related model by its primary key or return new instance of the related model. + * + * @param mixed $id + * @param array $columns + * @return \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model + */ + public function findOrNew($id, $columns = array('*')) + { + if(is_null($instance = $this->find($id, $columns))) + { + $instance = $this->related->newInstance(); + } + + return $instance; + } + + /** + * Get the first related record matching the attributes or create it. + * + * @param array $attributes + * @return \Illuminate\Database\Eloquent\Model + */ + public function firstOrCreate(array $attributes, array $joining = array(), $touch = true) + { + if (is_null($instance = $this->where($attributes)->first())) + { + $instance = $this->create($attributes, $joining, $touch); + } + + return $instance; + } + + /** + * Get the first related model record matching the attributes or instantiate it. + * + * @param array $attributes + * @return \Illuminate\Database\Eloquent\Model + */ + public function firstOrNew(array $attributes) + { + if (is_null($instance = $this->where($attributes)->first())) + { + $instance = $this->related->newInstance(); + } + + return $instance; + } + + /** + * Create or update a related record matching the attributes, and fill it with values. + * + * @param array $attributes + * @param array $values + * @return \Illuminate\Database\Eloquent\Model + */ + public function updateOrCreate(array $attributes, array $values = array(), array $joining = array(), $touch = true) + { + if (is_null($instance = $this->where($attributes)->first())) + { + $instance = $this->related->newInstance(); + + $new = true; + } + + $instance->fill($values); + + $instance->save(array('touch' => false)); + + if ($new) $this->attach($instance->getKey(), $joining, $touch); + + return $instance; + } + /** * Create a new instance of the related model. * diff --git a/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php b/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php index 83bc7eee2d58..19bd2b2e83c3 100755 --- a/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php +++ b/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php @@ -182,6 +182,82 @@ public function saveMany(array $models) return $models; } + /** + * Find a model by its primary key or return new instance of the related model. + * + * @param mixed $id + * @param array $columns + * @return \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model + */ + public function findOrNew($id, $columns = array('*')) + { + if(is_null($instance = $this->find($id, $columns))) + { + $instance = $this->related->newInstance(); + } + + if( ! $instance instanceof Collection) + { + $instance->setAttribute($this->getPlainForeignKey(), $this->getParentKey()); + } + + return $instance; + } + + /** + * Get the first related record matching the attributes or create it. + * + * @param array $attributes + * @return \Illuminate\Database\Eloquent\Model + */ + public function firstOrCreate(array $attributes) + { + if (is_null($instance = $this->where($attributes)->first())) + { + $instance = $this->create($attributes); + } + + return $instance; + } + + /** + * Get the first related model record matching the attributes or instantiate it. + * + * @param array $attributes + * @return \Illuminate\Database\Eloquent\Model + */ + public function firstOrNew(array $attributes) + { + if (is_null($instance = $this->where($attributes)->first())) + { + $instance = $this->related->newInstance(); + + $instance->setAttribute($this->getPlainForeignKey(), $this->getParentKey()); + } + + return $instance; + } + + /** + * Create or update a related record matching the attributes, and fill it with values. + * + * @param array $attributes + * @param array $values + * @return \Illuminate\Database\Eloquent\Model + */ + public function updateOrCreate(array $attributes, array $values = array()) + { + $instance = $this->firstOrNew($attributes); + + $instance->fill($values); + + $instance->setAttribute($this->getPlainForeignKey(), $this->getParentKey()); + + $instance->save(); + + return $instance; + } + /** * Create a new instance of the related model. * diff --git a/src/Illuminate/Database/Eloquent/Relations/MorphOneOrMany.php b/src/Illuminate/Database/Eloquent/Relations/MorphOneOrMany.php index 4a20351edce6..78c3156b3ac9 100755 --- a/src/Illuminate/Database/Eloquent/Relations/MorphOneOrMany.php +++ b/src/Illuminate/Database/Eloquent/Relations/MorphOneOrMany.php @@ -93,6 +93,91 @@ public function save(Model $model) return parent::save($model); } + /** + * Find a related model by its primary key or return new instance of the related model. + * + * @param mixed $id + * @param array $columns + * @return \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model + */ + public function findOrNew($id, $columns = array('*')) + { + if(is_null($instance = $this->find($id, $columns))) + { + $instance = $this->related->newInstance(); + } + + if( ! $instance instanceof Collection) + { + // When saving a polymorphic relationship, we need to set not only the foreign + // key, but also the foreign key type, which is typically the class name of + // the parent model. This makes the polymorphic item unique in the table. + $this->setForeignAttributesForCreate($instance); + } + + return $instance; + } + + /** + * Get the first related record matching the attributes or create it. + * + * @param array $attributes + * @return \Illuminate\Database\Eloquent\Model + */ + public function firstOrCreate(array $attributes) + { + if (is_null($instance = $this->where($attributes)->first())) + { + $instance = $this->create($attributes); + } + + return $instance; + } + + /** + * Get the first related model record matching the attributes or instantiate it. + * + * @param array $attributes + * @return \Illuminate\Database\Eloquent\Model + */ + public function firstOrNew(array $attributes) + { + if (is_null($instance = $this->where($attributes)->first())) + { + $instance = $this->related->newInstance(); + + // When saving a polymorphic relationship, we need to set not only the foreign + // key, but also the foreign key type, which is typically the class name of + // the parent model. This makes the polymorphic item unique in the table. + $this->setForeignAttributesForCreate($instance); + } + + return $instance; + } + + /** + * Create or update a related record matching the attributes, and fill it with values. + * + * @param array $attributes + * @param array $values + * @return \Illuminate\Database\Eloquent\Model + */ + public function updateOrCreate(array $attributes, array $values = array()) + { + $instance = $this->firstOrNew($attributes); + + $instance->fill($values); + + // When saving a polymorphic relationship, we need to set not only the foreign + // key, but also the foreign key type, which is typically the class name of + // the parent model. This makes the polymorphic item unique in the table. + $this->setForeignAttributesForCreate($instance); + + $instance->save(); + + return $instance; + } + /** * Create a new instance of the related model. *