What is the difference between attributesToArray() and toArray() in Laravel? - laravel

Can someone explain the difference between $model->attributesToArray() and $model->toArray() on a model?
I have an issue where a seeder is throwing an error about getCreatedAtAttribute method is not defined and it's complaining due to a toArray() method call. This is what prompted me to try and find out the difference between the two.
After switching to attributesToArray() the seeder runs fine.

attributesToArray will only fetch the attributes for the current model.
toArray calls the attributesToArray function, but also adds loaded relations to the array.

Related

Livewire, Laravel - can I call a controller 'store' method from a Livewire component?

I have a Laravel controller with a 'store' method. i.e. store(Request $request).
For the view I want to embed a livewire component and then utilize the existing controller 'store' method (behind the scenes) from a livewire component method. Is this possible? Currently, I'm running into the problem that there is no Request object since I'm no longer making the call from the existing route/view (i.e. POST /orders).
public function oms_order()
// this method provides the POST /orders leveraging
// Controllers\OrderController#store
{
$this->refId = app('App\Http\Controllers\OrderController')->store($this->jsonOrder);
}
Argument 1 passed to App\Http\Controllers\OrderController::store() must be an instance of Illuminate\Http\Request, null given, called in D:\xampp\htdocs\jade\livewire_hpp\app\Http\Livewire\Oms.php on line 26
I can remove the 'Request $request' from the store method but then that breaks the standard Laravel POST /orders route.
I was hoping to use the existing laravel app as the backend/API and add the livewire bit for a demo. Any advice is welcome.
I don't think it is a best practice to call a controller function from another class. If you want reusability, I suggest refactoring code by creating a separate class with a store method which accepts only required attributes and saves a record.
Then you can use this method in multiple places. It is easier to test also.
It is difficult to give an exact answer before seeing your store method.

STI ::find() fails in controller but succeeds in tinker

I'm using MannikJ/laravel-sti but the following code has a different behaviour in tinker and in a controller (assuming the definitions in larevel-sti's documentation, with classes Root, Sub1 and Sub2):
Root::find(1234)
In tinker, it correctly returns an instance of Sub1. But in a controller, it returns null.
I get the correct instance in the controller if I replace the code with:
Sub1::find(1234)
Thanks to the maintainer (cf. issue #1), we found that the problem is that we use constructors in our objects but laravel-sti's trait also does. Constructors are a known issue in PHP with traits…

Laravel: Use the method updateOrCreate on polymorphic relation

I am trying to use the method updateOrCreate on my polymorphic relation, which is called Taggable. This is the method I use to create a new tag.
public function attachTag($attributes)
{
return $this->tags()->create($attributes);
}
If I change the create method to the update, it also works fine when it comes to updating the model. But I want to use updateOrCreate method, which is problem because I don't pass the ID in the $attributes and therefore it just doesn't know, if there's some record in the DB or not.
I made some googling and found very little about this particular case, only something like I should pass second parameter. But I'm confused which parameter should I pass as second to make it working.
Thanks in advance for any help.
2 possible solutions
1- https://laracasts.com/discuss/channels/eloquent/updateorcreate-on-polymorph-relation
in this link, you should detect which one you want by selecting the second parameter.
2- Laravel: UpdateOrCreate on Relation?
I think it is also addressing your problem.
I used to use solution #1.
Hope it helps

Laravel eloquent skip() limit() use

Content::find($tag[0]->content_list)->take(5)
Where $tag[0]->content_list =[1,7,9,11,16,23,35,56,77,87,93]
This works properly
But I want to use something like this
Content::find($tag[0]->content_list)->take(5)->skip(5)
This throws error
By calling find() you actually execute the query and get a collection back. Now the Illuminate\Support\Collection class has a take method, but no skip method. That's what's happening here.
Instead you should call take() and skip() before you use find():
Content::take(5)->skip(5)->find($tag[0]->content_list);

How to keep helper methods when using Repository pattern in Laravel 5?

When working with repository pattern we have interface and some repository classes which implement this interface. If I'm not mistaken, one of the SOLID principles says that those repository classes should return the same type of data for each interface method so that if we switch implementation of the interface nothing breaks down.
If I have an eloquent repository class, which returns an array of eloquent classes of all users, like return User::all(), I have not a simple array but an array of Eloquent models. So instead I might want to use toArray() to return simple array, so that if I switch my implementation of the interface to some other ORM (for example UserDoctrineRepository or I don't know...) everything will still work.
If I understand correctly, inside UserEloquentRepository we use an eloquent model class to help us get data using Eloquent. However, inside my model (User class) I might have some helper methods, like getFullName(). If I simple use toArray() inside UserEloquentRepository I won't get this helper method in my controller, and, eventually in my view.
In other articles I've read they keep it like return User::all(), however, it means that I'm still coupled to Eloquent as I don't get a simple array, but an eloquent objects array
What you get from User::all() or basically every Eloquent query is a Illuminate\Database\Eloquent\Collection. The problem is that when you call toArray() on the collection it will convert all the items of the collection into an array too and you loose all the methods of your model. Instead you can call all() on the collection to get to the array of model objects:
$collection = User::all();
return $collection->all();
Yes that still means you will have Eloquent specific models in your resultset however if you don't use Eloquent features like attribute accessors you will have an easy time replacing it with another type of model.

Resources