convert value of a collection into a key in laravel - php

this my mysql query:
$tmp=almacen::select('nombre_empresa','oferta')->join('users','users.id','=','almacen.emp_id')->where('almacen.event_id','5')->get();
this returns several objects like these:
...
App\almacen {#1948
nombre_empresa: "Aux1",
oferta: "Serv_1234",
},
App\almacen {#1947
nombre_empresa: "Aux2",
oferta: "Serv 12345678",
},
...
i need to convert "nombre_empresa" in a key, for example
$tmp['Aux2']
this return:
"Serv 12345678"
Is it possible to do this in Laravel? or should I do it in another way?

Sure Laravel can handle that, check out the available collections methods. mapWithKeys is probably what you're looking for:
$mapped = $results->mapWithKeys(function ($item) {
return [$item['nombre_empresa'] => $item['oferta']];
});
Edit: mapWithKeys rather than map
https://laravel.com/docs/5.5/collections#method-mapwithkeys

You can use keyBy:
$tmp->keyBy('nombre_empresa');
You can chain it directly at the end of your query, after the get method.
But on this case you are only getting 2 fields from the database you can use pluck directly on the query builder:
$tmp=almacen::select('nombre_empresa','oferta')
->join('users','users.id','=','almacen.emp_id')
->where('almacen.event_id','5')
->pluck('oferta','nombre_empresa');
The second argument of pluck will be use for the key.
If none is given it will just use numeric keys: 0, 1,...

Of course, all solutions are valid, but the way I would do it which I think is also considered to be best practice in Laravel is by using pluck()
Documentation
Example:
$tmp=almacen::select('nombre_empresa','oferta')
->join('users','users.id','=','almacen.emp_id')
->where('almacen.event_id','5')
->get()
->pluck('oferta', 'nombre_empresa')
->toArray();
Do notice that pluck() is a new method introduced in version 5.2 to replace the before used lists()
Notice that I would transform toArray() but it is not a must, I would consider it since with such a simple collection I might not need the extra functionality making this variable take up less space.

Related

Removing rows from a collection changing types of the collection

I have a two collections. First one is a big collection. Another one is remove list. For example:
$data= List::where('status', true)->get();
$list= List::where('begin_at', '<', Carbon::now())->pluck('id');
$result = $data->whereNotIn('id', $list);
This is just a simple example. I have a dynamic data. My question is:
When i return $data, it returns [{}, {}, ...] format
But when i return $result, it returns {}, {}, ...
I tried to $result->toArray(), $result->toCollapse() but none of them is worked.
Why after the get(), using where condition changing the type of the collection? Why array symbols gone? What is the best practices in here to solution? Thanks in advance.
Use all() on the collection to get it as an array with the Eloquent models intact. If you use toArray() instead, it will convert everything to an plain PHP array.
$data->whereNotIn('id', $list)->all();
See docs here
Calling get() on a model will create a collection, and the collection upon creation will call all() on itself. So after modifying the collection you will need to call all() yourself to the the same "format" as from get().

Select, where JSON Array contains

So in Laravel 5 there's the handy thing called JSON Where Clauses using MySQL's new ability to store and fetch JSON stored in a column:
User::where('meta->colors', 'red')->get()
would return all rows, where colors in the column meta would be set to red.
Now let's say colors is not a string, but an array containing multiple colors (colors => ['red', 'blue', 'green']).
What would be an efficient way to retrieve all rows, where colors contains e.g. the value red?
JSON_CONTAINS() does exactly what you're looking for:
JSON_CONTAINS(target, candidate[, path])
Indicates by returning 1 or 0 whether a given candidate JSON document is contained within a target JSON document, or—if a path argument was supplied—whether the candidate is found at a specific path within the target. — 12.16.3 Functions That Search JSON Values
Currently, Laravel's query builder does not provide a corresponding API. There's an open internals proposal for it though.
In the meantime, you can execute a raw query:
\DB::table('users')->whereRaw(
'JSON_CONTAINS(meta->"$.colors", \'["red"]\')'
)->get();
Which would return all users that have "red" in their meta->colors JSON field. Note that the -> operator requires MySQL 5.7.9+.
You can also call the whereRaw() directly on an Eloquent model.
Laravel 5.6
As of the 5.6 release, Laravel's query builder contains a new whereJsonContains method.
I think a way would be using the like operator:
User::where('meta->colors', 'like', '%"red"%')
However, this would only work if the values never contain the character " and the delimiters wouldn't change.
An update for this answer, according to MySQL or MariaDb, the correct syntax must be JSON_CONTAINS(#json, 'red', '$.colors'), and is necessary to use JSON_EXTRACT.
So them, the code inside Laravel (for version 5.5 or less).
Like say #Elwin, meta column must contains the following JSON: { "colors": ["red", "blue", "green"] }
User::whereRaw("JSON_CONTAINS(JSON_EXTRACT(meta, '$.colors'), '\"{$color}\"')")
Remember to use double quotes in value sentence.
JSON_CONTAINS(JSON_EXTRACT(meta, '$.colors'), '"red"')
The whereIn method verifies that a given column's value is contained within the given array.
Try this:
$colorArray = ['red', 'blue', 'green'];
$user = User::whereIn($meta->color, $colorArray)->get();
More about Laravel's whereIn.

Append a Laravel collection with another collection

I am trying to append an Eloquent collection with another Eloquent collection in Laravel 5.3.
This is what I've done so far:
$entries = Entry::all();
$posts = Post::all();
$entries->merge($posts);
I tried to use merge() as shown in the code above, but it seems that I'm stuck with this kind of problem (since some of them have the same id with the same value):
Collection merge eating up some rows
Any ideas?
For versions < 5.4 you can merge the two eloquent collections by resetting keys with toBase like this:
$mergedCollection = $entries->toBase()->merge($posts);
For versions >= 5.4 you can use concat as suggested by Jason.
I believe you may be looking for concat(). This will append one container to the end of another container, regardless of the keys of either.
$mergedCollection = $entries->concat($posts);
Here's the link: laravel7.X
$collection = collect(['Desk', 'Chair']);
$merged = $collection->merge(['Bookcase', 'Door']);
$merged->all();
if you need to merge big_products and small_products:
$products = $bigProducts->values()->merge($smallProducts->values());
The merge method merges the given array or collection with the original collection. If a string key in the given items matches a string key in the original collection, the given items's value will overwrite the value in the original collection.
But
If the given items's keys are numeric, the values will be appended to the end of the collection:
Thus, all you need is to get rid of keys and you can do it with ->values() function.
Tested on Laravel-6
The merge() method receives an array, so you have to do something like
$entries->merge($posts->toArray());
Laravel Collections: merge() method

how to get collection results as array with ids

it should be simple but I am missing something,
lets say this simple eloquent:
Post::select('id')->take(5)->get();
I want to get simple array with the results id's so it will look like this:
[1,2,3,4,5]
but i am getting something like this:
[{"id":"1"},{"id":"2"},{"id":"3"},{"id":"4"},{"id":"5"}]
flatten() not working and I am getting the same results:
Post::select('id')->take(5)->get()->flatten();
http://laravel.com/docs/master/collections#method-flatten
The flatten
method flattens a multi-dimensional collection into a single
dimension:
what i am missing? I remember there is a short line laravel way of getting this results without iterate through the array and create a new one
just got it, its the lists() that do the magic so the answer is:
Post::select('id')->take(5)->lists('id');
Update:
as of laravel 5.2 lists() become deprecated
The lists method on the Collection, query builder and Eloquent query
builder objects has been renamed to pluck. The method signature
remains the same.
the new method name is pluck which work the same:
Post::select('id')->take(5)->pluck('id');

Symfony 2 Doctrine Use find with between condition

I have to find one record with between condition, and when I tried like this:
$paramHoraire = $em->getRepository('FrxintranetBundle:ParamPaye')->createQueryBuilder('a')
->where(':nbrDepots BETWEEN a.parampayeBornebas AND a.parampayeBornehaut')
->setParameter('nbrDepots', $nbrDep)
->getQuery()
->getResult();
It returns an array and if I want to use a get method I have to do $paramHoraire[0]->getParampayePourcentage()
I want to know if they are a method like find to return just one line and not an array.
Thanks.
Since there can be more then just one match you will always get an array. It is also used this way in the docs of doctrine as you can see here. There are functions such as getSingleScalarResult() if you used COUNT() in your DQL.

Categories