hretic hretic - 1 year ago 52
PHP Question

findOrNew returns an array instead of object when condition is not on id

i have 2 tables


in my
model i have

function meta() {
return $this->hasOne('App\userMeta');

in my controller when i want to save user and user meta

function store( Request $request , $id = 0 ) {
$user = User::findOrNew($id);
$user->save() ;

$meta = UserMeta::findOrNew(['user_id'=>$id]);

when im trying to save meta i get this error

Argument 1 passed to
Illuminate\Database\Eloquent\Relations\HasOneOrMany::save() must be
an instance of Illuminate\Database\Eloquent\Model,

here is the problem
returns an array instead of object ... which is weird .. while
itself returns and object .... i'm guessing it's becuz of my conditions (its the only difference between 2 query)

right now i have to do something like this

$meta = UserMeta::findOrNew(['user_id'=>$id]);
if(is_array($meta)) {
} else {

which i dont like and looks wrong !

Answer Source

The function findOrNew() is probably not what your are looking for. It is intended to be used as follows:

// the array in the second parameter specifies which columns are 
// included in the resulting model (if found)
// it is NOT used as a WHERE clause
$meta = UserMeta::findOrNew($id, ['user_id'=>$id]);

What you are looking for:

// adds where clause (returns new model if it does not exist)
$meta = UserMeta::firstOrNew(['user_id' => $id]);

// same as above but persists new model to database
$meta = UserMeta::firstOrCreate(['user_id' => $id]);

Reason why firstOrNew() returns no single model in your case:

This is the implementation of findOrNew Illuminate\Database\Eloquent\Builder.php :

public function findOrNew($id, $columns = ['*'])
    if (! is_null($model = $this->find($id, $columns))) {
        return $model;

    return $this->model->newInstance();

As you can see, the first parameter is not intended for the columns.

If you have a look at the find method in $this->find($id, $columns) you will see:

public function find($id, $columns = ['*'])
    if (is_array($id)) {
        return $this->findMany($id, $columns);

    $this->query->where($this->model->getQualifiedKeyName(), '=', $id);

    return $this->first($columns);

As your passed an array as $id the result of $this->findMany() is returned, which is a Collection.