Eloquent Return Non Associative Array? - laravel

I am trying to get an array list of IDs to pass onto another model query.
$companies = $user->companies->pluck('id');
But it keeps returning an associative array as such:
[ 0 => 2, 1 => 9]
So when I pass it to the find method on my Company model, like this
$company = Company::find($companies);
I get the following error:
Trying to get property of non-object
I need to be able to pass a non-associative array to the call like such:
Company::find([2,9]);

Try that:
$companies = $user->companies->pluck('id')->toArray();
Just did a test in tinker and the result is a flat array, the "find" will work for sure!

As you can see in Laravels source code
src/Illuminate/Database/Eloquent/Builder.php
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);
}
find() will internally call findMany() if the first parameter is an array. But $user->companies->pluck('id') returns a Collection and the Builder creates a wrong query. So your options are:
Use findMany():
$company = Company::findMany($companies);
Convert the Collection to an array:
$company = Company::find($companies->toArray());
Use whereIn():
$company = Company::whereIn('id', $companies)->get();
But actually that all doesn't seem to make any sense, because $user->companies probably already contains the collection you want to fetch from DB. So you could also write:
$company = $user->companies;
However - the fact that you are using singular naming (company) for a set of companies, let me think that you are trying to achieve something completely different.

You can try with the whereIn method
Company::whereIn('id', $companies)->get();

Related

How to get a value from database on Laravel Controller?

I have this code where I want to select certain values from the table. Counter is my Model.
$today = '2022-03-16';
$tanggal = Counter::select('tanggal')->where('api', 'Agenda')->where('tanggal', $today)->get();
But if i dd($tanggal->tanggal), it returns with an error Property [tanggal] does not exist on this collection instance.
How to get a value from 'tanggal' attribute?
You are using get() method. it will return collection. You can not access any field directly from collection.
You have to need use freach loop to access single property.
$today = '2022-03-16';
$tanggals = Counter::select('tanggal')
->where('api', 'Agenda')->where('tanggal', $today)->get();
forech( $tanggals as $tanggal)
{
dump($tanggal->tanggal);
}
You are trying to access a model property from a Collection, this can be fixed like so:
$tanggal = Counter::where(['api' => 'Agenda', 'tanggal' => $today])->first(['tanggal']);
get() returns a Collection, first() returns a Model.
You can use the collection but then use its .each() method and give it a lambda instead to process each value.
$collection = Counter::select('tanggal')->where('api', 'Agenda')->where('tanggal', $today)->get();
$collection->each(function ($item, $key) {
//write now your code here can do $item->tanggal
});

How to compare two objects and get different columns in Laravel

I have two objects of the same record which I am getting from the database. One is before the update, and the other is after the update. I want to know the column values which are changed during this update query.
$before_update = DeliveryRun::find($id);
$before_update->name = $request->input('name');
$before_update->save();
$after_update = DeliveryRun::find($id);
compare($before_update, $after_update)
I would define a method on your DeliveryRun model which can be used to compare objects of the same type.
Lets say we want to be able to do something like $deliveryRun->compareTo($otherDeliveryRun). That seems like a nice fluid syntax and reads well in my opinion.
What we want to do is get the attributes and their values for the DeliveryRun we're calling compareTo on and then compare them against the attributes and values for the DeliveryRun we provide as an arguement to the compareTo method.
class DeliveryRun extends Model
{
public function compareTo(DeliveryRun $other)
{
$attributes = collect($this->getAttributes())
->map(function ($attribute, $key) use ($other) {
if ($attribute != $other->$key) {
return $key = $attribute;
}
})->reject(function ($attribute, $key) {
return !$attribute || in_array($key, ['id', 'created_at', 'updated_at']);
});
return $attributes;
}
}
The above gets the attributes for the current ($this) DeliveryRun, converts the array returned from getAttributes() to a collection so we can use the map() function and then loops over each attribute on the DeliveryRun model comparing the key and value of each against the $other DeliveryRun model provided.
The reject() call is used to remove attributes which are the same and some attribute keys which you might not be interested in leaving you just the attributes that have changed.
Update
I am saving object in other variable before update $before_update = $delivery_run; but after update $before_update variable I also gets updated
If I am understanding you correctly, you're still comparing the same object to itself. Try something like the following.
$before = clone $delivery_run; // use clone to force a copy
$delivery_run->name = 'something';
$delivery_run->save();
$difference = $before->compareTo($delivery_run);
I would consider using getChanges() as suggested by #Clément Baconnier if all you're doing is looking to get the changes of an object straight after the object has been saved/updated.

how to display name from database in laravel

i want to display data from my database
controller
public function generatePDF(Request $request)
{
$id = Auth::user()->id;
$name = User::select("NAME")->where("id", $id)->get();
$pdf = PDF::loadView('generatePDF', ['name'=>$name]);
return $pdf->stream('generatePDF.pdf');
}
blade
<h2>{{name}}</h2>
result
[{"NAME":"name_from_database"}]
can i display without [{"name":}], so just the value of data (name_from_database) ?
Simple use find like this
$name = User::find($id)->name;
Or direct from auth
$name = \Auth::user()->name;
To get logged in user id you can use \Auth::id()
you can use:
$user_id = User::findOrFail($id)->first();
$name=$user_id->name;
test the laravel log file:
\Log::info($name);
Use first() instead of get(), because get() will return an array and first() will return the object.
DRY Code line no.1 and no.2. simple use:
$name = auth()->user()->name;
to get the name of the currently authenticated user.
Send $name to you view is fine
$pdf = PDF::loadView('generatePDF', ['name' => $name]);
Correct your code in blade file
{{ name }} -> {{ $name }}
I hope this might help you. :)
Hello Aldi Rostiawan,
$nameGet = User::select("NAME")->where("id", $id)->get();
$nameFirst = User::select("NAME")->where("id", $id)->first();
Here in both line of code the difference is only Get and First.
Get method returns an Array of objects. So for example if the query apply on many records then the code will give you many objects in an array. Or if query will be true for only one record then also it will return an array with one object.
If you know that id is primary key of he table then only one record will be fetched then you can use First function instead if Get method.
First function always return an Object. In case if query apply on many records then also first method will return you only first record as an Object.
And it seems that you have required an Object only.
You should try this:
Controller
public function generatePDF(Request $request)
{
$id = Auth::user()->id;
$rsltUser = User::where("id", $id)->first();
$pdf = PDF::loadView('generatePDF', ['rsltUser'=>$rsltUser]);
return $pdf->stream('generatePDF.pdf');
}
blade
<h2>{{$rsltUser->name}}</h2>
use VALUE() to display name only.
in your case:
<h2>{{$rsltUser->value('name')}}</h2>
your name variable is an array containing a single object with a NAME attribute .. so to diplay that value, you should change your script to
<h2>{{name[0]['NAME']}}</h2>

Laravel Eloquent query with optional parameters

I am trying to learn whether or not there is a simple way to pass a variable number of parameters to a query in Eloquent, hopefully using an array.
From what I can find, there doesn't seem to be a way to do this without looping through the Input to see what was set in the request.
Examples here: Laravel Eloquent search two optional fields
This would work, but feels non-Laravel to me in its complexity/inelegance.
Here is where I am, and this may not be possible, just hoping someone else has solved a similar issue:
$where = array("user_id" => 123, "status" => 0, "something else" => "some value");
$orders = Order::where($where)->get()->toArray();
return Response::json(array(
'orders' => $orders
),
200
);
That returns an error of course strtolower() expects parameter 1 to be string, array given.
Is this possible?
Order::where actually returns an instance of query builder, so this is probably easier than you thought. If you just want to grab that instance of query builder and "build" your query one where() at a time you can get it like this:
$qb = (new Order)->newQuery();
foreach ($searchParams as $k => $v) {
$qb->where($k, $v);
}
return $qb->get(); // <-- fetch your results
If you ever want to see what query builder is doing you can also execute that get() and shortly after:
dd(\DB::getQueryLog());
That will show you what the resulting query looks like; this can be very useful when playing with Eloquent.
You can try this:
Method 1:
If you have one optional search parameter received in input
$orders = Order::select('order_id','order_value',...other columns);
if($request->has(user_id)) {
$orders->where('orders.user_id','=',$request->user_id);
}
//considering something_else as a substring that needs to be searched in orders table
if($request->has('something_else')) {
$orders->where('orders.column_name', 'LIKE', '%'.$request->something_else.'%');
}
$orders->paginate(10);
Method 2:
If you have multiple optional parameters in input
$orders = Order::select('columns');
foreach($input_parameters as $key => $value) {
//this will return results for column_name=value
$orders->where($key, $value);//key should be same as the column_name
//if you need to make some comparison
$orders->where($key, '>=', $value);//key should be same as the column_name
}
return $orders->paginate(15);

Laravel 4 - Get Array of Attributes from Collection

I have a collection of objects. Let's say the objects are tags:
$tags = Tag::all();
I want to retrieve a certain attribute for each tag, say its name. Of course I can do
foreach ($tags as $tag) {
$tag_names[] = $tag->name;
}
But is there a more laravelish solution to this problem?
Something like $tags->name?
Collections have a lists method similar to the method for tables described by #Gadoma. It returns an array containing the value of a given attribute for each item in the collection.
To retrieve the desired array of names from my collection of tags I can simply use:
$tags->lists('name');
Update: As of laravel 5.2 lists is replaced by pluck.
$tags->pluck('name');
More specifically, the laravel 5.2 upgrade guide states that "[t]he lists method on the Collection, query builder and Eloquent query builder objects has been renamed to pluck. The method signature remains the same."
Yep, you can do it nice and easily. As the Laravel 4 Documentation states, you can do
Retrieving All Rows From A Table
$users = DB::table('users')->get();
foreach ($users as $user)
{
var_dump($user->name);
}
Retrieving A Single Row From A Table
$user = DB::table('users')->where('name', 'John')->first();
var_dump($user->name);
Retrieving A Single Column From A Row
$name = DB::table('users')->where('name', 'John')->pluck('name');
Retrieving A List Of Column Values
$roles = DB::table('roles')->lists('title');
This method will return an array of role titles.
You may also specify a custom key column for the returned array:
$roles = DB::table('roles')->lists('title', 'name');
Specifying A Select Clause
$users = DB::table('users')->select('name', 'email')->get();
$users = DB::table('users')->distinct()->get();
$users = DB::table('users')->select('name as user_name')->get();
EDIT:
The above examples show how to access data with the help of Laravel's fluent query builder. If you are using models you can access the data with Laravel's Eloquent ORM
Because Eloquent is internaly using the query builder, you can without any problem do the following things:
$tag_names = $tags->lists('tag_name_label', 'tag_name_column')->get();
which could be also done with:
$tag_names = DB::table('tags')->lists('tag_name_label', 'tag_name_column')->get();
Here are a few snippets from my own experimentation on the matter this morning. I only wish (and maybe someone else knows the solution) that the Collection had a $collection->distinct() method, so I could easily generate a list of column values based on an already filtered collection.
Thoughts?
I hope these snippets help clarify some alternative options for generating a list of unique values from a Table, Collection, and Eloquent Model.
Using a Collection (Happy)
/**
* Method A
* Store Collection to reduce queries when building multiple lists
*/
$people = Person::get();
$cities = array_unique( $people->lists('city') );
$states = array_unique( $people->lists('state') );
// etc...
Using an Eloquent Model (Happier)
/**
* Method B
* Utilize the Eloquent model's methods
* One query per list
*/
// This will return an array of unique cities present in the list
$cities = Person::distinct()->lists('city');
$states = Person::distinct()->lists('state');
Using an Eloquent Model PLUS Caching (Happiest)
/**
* Method C
* Utilize the Eloquent model's methods PLUS the built in Caching
* Queries only run once expiry is reached
*/
$expiry = 60; // One Hour
$cities = Person::remember($expiry)->distinct()->lists('city');
$states = Person::remember($expiry)->distinct()->lists('state');
I would love to hear some alternatives to this if you guys have one!
#ErikOnTheWeb
You could use array_column for this (it's a PHP 5.5 function but Laravel has a helper function that replicates the behavior, for the most part).
Something like this should suffice.
$tag_names = array_column($tags->toArray(), 'name');

Resources