Laravel: Get model attributes by key array - php

I'm attempting to access a models attributes by an array of keys. The desired functionality would work something like $model->getAttribute('name'), but accept an array instead of a string.
Let's say we had a model with attributes name of 'A', age of 2 and blood_type of 'B'.
$attributesToPull = ['name', 'age'];
$model->getAttributes($attributesToPull);
// returns ['A', 2]
I've checked through the Laravel docs and cant find anything that quite fits.
The results dont need to come straight from the model, they can be pulled into their own associative array using $model->getAttributes() and then have a native PHP array function such as array_intersect to filter the results, but even then I can't seem to find a function that will allow me to filter an associative array with an indexed array.
Does anyone know how I could go about this, ideally without using a loop or a callback? The answer can be pretty open, it can return a collection or an array and use either the associative array of the model attributes or call a function on the model itself.

The Model has a only method:
$model->only($attributesToPull);

Related

Laravel - filter collection and then ->toJson, having a minor issue

I have a Laravel controller which takes a search parameter, looks through all the records in a certain time range, uses the laravel collection ->filter method, and then on the results of that filter method, returns the json ->json
$logs = RequestLog::orderBy('created_at', 'DESC')->whereBetween('created_at', [$start, $end])->get();
$logs = $logs->filter(function($log) { /* my own logic in here */ });
return response()->json($logs->toJson());
Now this seems to work just fine. It normally returns an array of the matching records, [{"id":1},{"id":2},{"id":3}]
But if the ->filter function leaves one result, let's say the 25th record in the array, the response now comes out like this: {25: {"id": 25}}. It ruins the normal array structure and returns a JSON object with a single key.
Is this expected? What's up with this? How do I deal with this?
Note: my filter function cannot be done via sql means, it has to be done in PHP.
[edit] it's actually returning an Object JSON anytime the filter results are anything other than the first items in the original Query results.
Normally after applying methods that modifies (especially removes an item from) a collection, the indexes may not come ordered. This is why you need ->values() on the collection.
So you'd have:
return response()->json($logs->values()->toJson());
values() Resets the keys on the underlying array.

Why does Laravel store two different array syntaxes in databases and which one is correct?

I come from a Javascript and Ruby background and this is baffling me. Laravel can store two different array syntaxes in my DB depending on how I handle my array serialization. In my understanding, collect() creates a true Laravel array. Why then is it storing a serialized array? Furthermore, is the {'key':'value'}syntax still an array despite having no square brackets surrounding it? It looks to me like a standard object or a hash, but if I try to do toArray() on it, it recognizes that it's already an array and throws an error. What am I misunderstanding and what is correct here?
Given a form:
edit.blade:
<select class="form-control m-bootstrap-select m_selectpicker" name="temp">
<option value={{ json_encode(array("$key"=>"$cph"), JSON_FORCE_OBJECT) }}>
</select>
The following two controllers syntaxes yield different database insertions.
PageController.php:
$page->cph_default = collect($request->temp);
$page->save();
Laravel stores an array with the following syntax in my database: ["{\"11\":\"1100\"}"]
PageController.php
$page->cph_default = json_decode($request->temp, true);
$page->save();
Laravel stores an array with the following syntax in my database: {"19": "1900"}
A PHP array with the syntax ['key' => 'value'] is called an associative array, and acts like a hash. A JSON-encoded associative array will show up as an object in JSON syntax. Examples and more info on PHP.net
Laravel's collect() function is a convenience wrapper for creating a new Collection. A Collection is not really a "true Laravel array" so much as it is an object wrapper with some convenience methods for modifying the underlying array. Think of it like a scalar object.
In your form when generating the option value, the submitted form value ($request->temp) will be a JSON-encoded string. Literally the string '{"19": "1900"}'.
Calling collect($request->temp) does no modification to that submitted data. It's simply creating a new Collection (array), containing a single string item. If you were to call toArray() on the collection, you'd see something like this:
[
0 => '{"19": "1900"}'
]
Note that this is not an associative array, it is a numeric array with a zero-based index. This array is encoded as a JSON array, not as a hash object. Hence your first result.
Calling json_decode($request->temp) is turning the string back into an associative array (hash) before saving it via Eloquent. Eloquent then calls json_encode() again internally, turning it back into the same JSON as your form's option value.
If you were to decode the form value before creating the collection, the resulting database save would look identical. You'd just have the convenience of the Collection wrapper:
$page->cph_default = collect(json_decode($request->temp, true));
$page->save();
If you're treating the column as a JSON type, you should ensure the data passed to Eloquent is NOT already encoded, or you'll get the double encoding experienced in your first example.
No Matter What is.
First If you are stroring the array into database convert to JSON FORMAT
For eg
$variable = json_encode($request->controlname);
This is the right way to store array
Into database

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');

Create associative array from numeric array and function?

I have a numeric array with codes like this: array('123', '333', '444');
I also have a function that given a code returns a name, so myFunc('123') would return 'soap'
I'd like to generate an associative array containing codes as keys and names as values. Is there any function that would allow me to do this? I know a foreach loop would do it but I wonder if there's some made function for this. Saw some methods like array_map but they don't seem to fit my needs.
array_combine($arr, array_map('myFunc', $arr))
But two functions, not one ;-) Still oneliner though

Categories