I am having an array that I make a collection out of it with CakePHP 3 then I use match to extract a new collection containing only the elements that id=2.
What I am unable to understand is after I use match if I use each to iterate with my original collection i see the element with id=2. \
Shouldn't it be removed from the original collection ?
How can I iterate my new collection cause each, compile, foreach are not working, and when I use debug all I get is
\src\Controller\ComlibsController.php (line 51)
object(Cake\Collection\Collection) {
'count' => (int) 0
}
The collection code id :
//get the current answer and remove it from the query array
$mycollection = new Collection($query[0]['answers']);
$answer = $mycollection->match(['answers.id' => $theid]);
Cookbook is not as simple as they claimed.
Any sort of help would be appreciated.
Performing a match on a collection returns a new collection with the elements that match, but it doesn't alter the original collection in any way.
When you're creating your collection, you're specifying the ['answers'] key, which means that won't be part of the path any more for elements in the collection. You will therefore simply want to do ->match(['id' => $theid]) to find the matches.
Related
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);
I'm building timeline for my app and got this issue, that my collection returns me only 11 values.
I have tried to change merged data and it always returns me 11 values that makes me very confused, bc their is no limits in my code.
public function timeline($company_id)
{
// USER COMPANY
$company = auth()->user()->companies()->findOrFail($company_id);
//GETTING DATA TO MERGE COLLECTION
$equities = Share::where('company_id', $company_id)->get();
$equityGrants = EquityGrant::whereIn('share_id', $equities->pluck('id')->toArray())->get();
$warrants = Warrant::where('company_id', $company_id)->orderBy('created_at', 'DESC')->get();
$warrantGtrants = WarrantGrant::whereIn('warrant_id', $warrants->pluck('id')->toArray())->get();
$convertibles = Convertible::where('company_id', $company_id)->get();
// CREATING COLLECTION
$operations = $equities->merge($equityGrants)->merge($warrants)->merge($warrantGtrants)->merge($convertibles);
$operations = $operations->sortByDesc('created_at');
// RETURNS ME ONLY 11 VALUES
return $operations->values()->all();
}
I tried to merge() less instances, like $operations = $equities->merge($equityGrants)->merge($warrants)->merge($warrantGtrants) but always maximum 11 values. I need to return all data for my timeline.
HELP ME Please! :)
Cheers, love :)
SOLUTION:
function concat() instead of merge() fixed the problem.
Using merge() on collections in Laravel will cause overiding all elements with the same ids comming from Eloquent query.
I believe that is why you are getting only 11 elements because this is the count off all elements having distinct ids.
According to the documentation of merge, when a key matches, it will be overwritten by the last item with that key (the collection you are merging in).
A solution to your problem would be the keyBy method (documentation). If you use keyBy('created_at'), it will give you an array where the keys are the created_at timestamps.
Although it sounds like they would be unique, there is a great change that some of the linked resources (like warrant and warrentGrants) are created at the exact same moment. If that is the case, you should try to find another key or something that is unique across all resources.
SOLUTION: function concat() instead of merge() fixed the problem.
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
I need to define Doctrine Criteria and filter ArrayCollection in the way that every collection's element could be defined with specific field's value as simple scalar or array of scalars (integers). Criteria should define accepted field's value (scalar) and it should be matched if scalar=scalar OR if scalar is in array of scalars.
I have collection of scenarios, like:
$scenarios = new ArrayCollection([
['code' => 1],
['code' => [2, 3]]
]);
And Criteria like:
$criteria = new Criteria();
$criteria->where($criteria->expr()->contains('code', 1));
$matching = $scenarios->matching($criteria);
But it's not working for arrays since Comparison::CONTAINS only checks if value is part of a field with strpos. Comparison::IN works the other way I need - it checks if collection element field's value is in array specified in criteria's expression.
Is it possible to achieve what I need? Do I need to create custom class which implements Doctrine\Common\Collections\Expr\Expression? How to do it?
PS. Yes, I know I could normalize collection and make everywhere arrays, but it only simplifies handling of a condition. It does not solve the problem since Doctrine's built-in comparisions does not support matching arrays in "my way".
There is new comparison MEMBER_OF in master branch which should be released soon according to Guilherme Blanco's comment. It works exactly as needed, so just use dev-master or wait for v1.4.
I am working with migration and I am migrating taxonomy terms that the document has been tagged with. The terms are in the document are separated by commas. so far I have managed to separate each term and place it into an array like so:
public function prepareRow($row) {
$terms = explode(",", $row->np_tax_terms);
foreach ($terms as $key => $value) {
$terms[$key] = trim($value);
}
var_dump($terms);
exit;
}
This gives me the following result when I dump it in the terminal:
array(2) {
[0]=>
string(7) "Smoking"
[1]=>
string(23) "Not Smoking"
}
Now I have two fields field_one and field_two and I want to place the value 0 of the array into field_one and value 1 into field_two
e.g
field_one=[0]$terms;
I know this isn't correct and I'm not sure how to do this part. Any suggestions on how to do this please?
If you are only looking to store the string value of the taxonomy term into a different field of a node, then the following code should do the trick:
$node->field_one['und'][0]['value'] = $terms[0];
$node->field_two['und'][0]['value'] = $terms[1];
node_save($node);
Note you will need to load the node first, if you need help with that, comment here and will update my answer.
You are asking specifically about ArrayList and HashMap, but I think to fully understand what is going on you have to understand the Collections framework. So an ArrayList implements the List interface and a HashMap implements the Map interface.
List:
An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted. The user can access elements by their integer index (position in the list), and search for elements in the list.
Map:
An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
So as other answers have discussed, the list interface (ArrayList) is an ordered collection of objects that you access using an index, much like an array (well in the case of ArrayList, as the name suggests, it is just an array in the background, but a lot of the details of dealing with the array are handled for you). You would use an ArrayList when you want to keep things in sorted order (the order they are added, or indeed the position within the list that you specify when you add the object).
A Map on the other hand takes one object and uses that as a key (index) to another object (the value). So lets say you have objects which have unique IDs, and you know you are going to want to access these objects by ID at some point, the Map will make this very easy on you (and quicker/more efficient). The HashMap implementation uses the hash value of the key object to locate where it is stored, so there is no guarentee of the order of the values anymore.
You might like to try:
list($field_one, $field_two) = prepareRow($row);
The list function maps entries in an array (in order) to the variables passed by reference.
This is a little fragile, but should work so long as you know you'll have at least two items in your prepareRow result.