Skip to content

Instantly share code, notes, and snippets.

@barryvdh
Created September 27, 2016 08:14
Show Gist options
  • Save barryvdh/f963f5c67d5cfc23357f1a81b3aad56a to your computer and use it in GitHub Desktop.
Save barryvdh/f963f5c67d5cfc23357f1a81b3aad56a to your computer and use it in GitHub Desktop.
PushAll example
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Collection;
trait PushAll {
public function pushAll()
{
// Convert attributes to relations
foreach ($this->attributes as $key => $value) {
if (method_exists($this, $key) && $this->$key() instanceof Relation) {
$this->setRelation($key, $value);
unset($this->attributes[$key]);
}
}
// Split the relations in BelongsTo and other
$belongsToRelations = [];
$otherRelations = [];
foreach ($this->relations as $name => $model) {
if ($this->$name() instanceof BelongsTo) {
$belongsToRelations[$name] = $model;
} else {
$otherRelations[$name] = $model;
}
}
/**
* Check the inverse relations first, to set the correct key
*/
foreach ($belongsToRelations as $name => $model) {
/** @var BelongsTo $rel */
$relation = $this->$name();
$model = $this->convertDataToModel($relation, $model);
if (! $this->pushAllModel($model)) {
return false;
}
$relation->associate($model);
}
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 ($otherRelations as $name => $models) {
$models = $models instanceof Collection ? $models->all() : [$models];
foreach (array_filter($models) as $model) {
/** @var Relation $rel */
$relation = $this->$name();
$model = $this->convertDataToModel($relation, $model);
// Save related model
$relation->save($model);
if (! $this->pushAllModel($model)) {
return false;
}
}
}
return true;
}
protected function pushAllModel($model)
{
$pushMethod = method_exists($model, 'pushAll') ? 'pushAll' : 'push';
return $model->$pushMethod();
}
protected function convertDataToModel(Relation $relation, $data)
{
if ($data instanceof Model) {
return $data;
}
return $relation->getRelated()->fill($data);
}
}
<?php
Route::get('push', function(){
$user = new User;
$user->name = 'Barry';
$user->email = str_random();
$user->password = str_random();
$post = new Post;
$post->title = 'Test 1';
$post->body = 'Lorem ipsum';
$user->posts[] = $post;
$user->posts[] = [
'title' => 'Test 2',
'body' => 'from array',
];
$user->pushAll();
$user = $user->fresh('posts');
$user->posts->first()->title = 'Test 1a';
$user->posts[] = [
'title' => 'test 3',
'body' => 'lala',
];
$user->pushAll();
dump($user->fresh('posts'));
return 'ok';
});
Route::get('push2', function(){
$post = new Post;
$post->title = 'Test A';
$post->body = 'Lorem ipsum';
$post->user = [
'name' => 'Barry',
'email' => str_random(),
'password' => str_random(),
];
/*
$user = new User;
$user->name = 'Barry';
$user->email = str_random();
$user->password = str_random();
$post->user = $user;*/
$post->pushAll();
dump($post->fresh('user'));
return 'ok';
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment