1

I want to create an Eloquent Model from an Array() fetched from database which is already toArray() of some model stored in database. I am able to do that using this code:

$model = Admin::hydrate($notification->data);

$notification->data = [
  "name" => "abcd"
  "email" => "[email protected]"
  "verified" => 0
  "shopowner_id" => 1
  "id" => 86
  "shopowner" => [
    "id" => 1
    "name" => "Owner1"
    "email" => "[email protected]"
  ]
];

But i can't access the $model->shopowner->name I have to use $model->shopowner['name']

I want to use the same class of notification without any specific change to access the data.

2
  • Is there a reason you'd need to use a model for this instead of a stdClass object? Commented Nov 2, 2018 at 12:47
  • @Devon - YES, as i mentioned i want to use same Notification::toEmail method which i use to send the initial notification this is the case when i re-notify and shoot the same email content. but this time the data is fetched from the notification database. Commented Nov 2, 2018 at 12:49

5 Answers 5

4

If you want to access shopowner as a relationship, you have to hydrate it manually:

$data = $notification->data;
$model = Notification::hydrate([$data])[0];
$model->setRelation('shopowner', ShopOwner::hydrate([$data['shopowner']])[0]);
Sign up to request clarification or add additional context in comments.

1 Comment

Hi, Thanks for your answer. it's gives me the same error. but i took the [0] pattern from your code and mix it with @Devon's answer. and found the solution.
3

Solution:

Thanks to @Devon & @Junas. by combining their code I landed to this solution

$data = $notification->data;                
$data['shopowner'] = (object) $data['shopowner'];
$model = Admin::hydrate([$data])[0];

Comments

1

I see this as an invalid use of an ORM model. While you could mutate the array to fit your needs:

$notification->data['shopowner'] = (object) $notification->data['shopowner'];
$model = Admin::hydrate($notification->data);

Your model won't be functional because 'shopowner' will live as an attribute instead of a relationship, so when you try to use this model for anything other than retrieving data, it will cause an exception.

3 Comments

You are close, but it gives error Illegal string offset 'shopowner'
Yeah, I wasn't thinking correctly, map wouldn't be useful here in PHP. You could just mutate the array as updated. I'd still recommend not hydrating models like this as it will cause issues in your application in the long term. Just fetch a new model from the database or return a model from the Notification class.
As your answer get me the clue how to do it, I modified your code as we can't mutate the $notification->data. $data = $notification->data; $data['shopowner'] = (object) $data['shopowner']; $model = Admin::hydrate([$data])[0]; which worked.
0

You cannot access array data as object, what you can do is override the attribute and create an instance of the object in your model, so then you can use it like that. For example:

public function getShopownerAttribute($value)
{
   return new Notification($value); // or whatever object here
}

class Notification {

   public function __construct($data)
   {
      // here get the values from your array and make them as properties of the object
   }
}

6 Comments

thanks but didn't really understood how to use this. any code example?
this is a code example. So you should put this in the model that has that column as an array
sorry for being so dumb. all above is completely confusing flow for me. let me come to the point. the getShopownerAttribute($value) if I write in my Admin model. then when and how to call it and what $value should i pass? also, the Notification class is already there in working condition. but the issue is it is all working good when i call it for the first email passing actual model to it. but now this time i am fetching the data from database and first converting it to the model and passing it to the same notification class. there it's issue accessing the $model->shopowner->name.
This is what I am refering to: laravel.com/docs/master/… This means that you have a shopowner column in your DB table, and after that whenever you call $model->shopowner that will be cast to the Notification or whatever object you create with that data. You are not dumb, I just hope I am giving you a path on what you are trying to achieve here.
in that case, it's not useful for me, because i don't want to add a column in database for this small task. the shopowner_id is there which is a foretgn key and the shopowner data is actually comes from the relationship while first fetching it. then i store it into database and again fetch it to generate renotification. Thanks though.
|
0

It has been a while since I used laravel but to my understanding once you use hydrate your getting a Illuminate\Database\Eloquent\Collection Object, which then holds Model classes.

These however could have attributes that are lazy loaded when nested.

Using the collections fresh method could help getting a Full database object as using load missing

2 Comments

but isn't a collection getting returned when the hydrate method is used or am I confusing something? laravel.com/api/5.7/Illuminate/Database/Eloquent/…
You're right. I was thinking hydrate was a model method, but it is a builder method. Guess that makes the OP's attempt even more problematic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.