Symfony 2 Doctrine Use find with between condition - php

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.

Related

Laravel Collection returns only 11 values

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.

convert value of a collection into a key in laravel

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.

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

Mongodb like statement with array

I am trying to save some db action by compiling a looped bit of code with a single query, Before I was simply adding to the the like statements using a loop before firing off the query but i cant get the same idea going in Mongo, id appreciate any ideas....
I am basically trying to do a like, but with the value as an array
('app', replaces 'mongodb' down to my CI setup )
Here's how I was doing it pre mongofication:
foreach ($workids as $workid):
$this->ci->app->or_like('work',$workid) ;
endforeach;
$query = $this->ci->db->get("who_users");
$results = $query->result();
print_r($results);
and this is how I was hoping I could get it to work, but no joy here, that function is only designed to accept strings
$query = $this->ci->app->like('work',$workids,'.',TRUE,TRUE)->get("who_users");
print_r($query);
If anyone can think of a way any cunning methods I can get my returned array with a single call again it would be great I've not found any documentation on this sort of query, The only way i can think of is to loop over the query and push it into a new results array.... but that is really gonna hurt if my app scales up.
Are you using codeigniter-mongodb-library? Based on the existing or_like() documentation, it looks like CI wraps each match with % wildcards. The equivalent query in Mongo would be a series of regex matches in an $or clause:
db.who_users.find({
$or: [
{ work: /.*workIdA.*/ },
{ work: /.*workIdB.*/ },
...
]});
Unfortunately, this is going to be quite inefficient unless (1) the work field is indexed and (2) your regexes are anchored with some constant value (e.g. /^workId.*/). This is described in more detail in Mongo's regex documentation.
Based on your comments to the OP, it looks like you're storing multiple ID's in the work field as a comma-delimited string. To take advantage of Mongo's schema, you should model this as an array of strings. Thereafter, when you query on the work field, Mongo will consider all values in the array (documented discussed here).
db.who_users.find({
work: "workIdA"
});
This query would match a record whose work value was ["workIdA", "workIdB"]. And if we need to search for one of a set of ID's (taking this back to your OR query), we can extend this example with the $in operator:
db.who_users.find({
work: { $in: ["workIdA", "workIdB", ...] }
});
If that meets your needs, be sure to index the work field as well.

MongoCollection findOne vs find

I would like to know if there is some improvement on MongoCollection::findOne or if is just an "alias" or "shorcut" to MongoCollection::find with a limit of 1, for example.
Thank you
findOne() is an alias of find() with a limit(-1)
You can see this in the source code here. It does the equivalent to
find(...).limit(-1).getNext().
The -1 is actually relevant. Here's a snippet from the wire protocol docs:
If the number is negative, then the database will return that number
and close the cursor.
If you go to the shell and type > db.collection.findOne (no parens), you can see that the function is also just a helper in the shell.
So, "yes findOne() is just a helper".
From the mongo tutorials...
To show that the document we inserted in the previous step is there,
we can do a simple findOne() operation to get the first document in
the collection. This method returns a single document (rather than the
DBCursor that the find() operation returns), and it's useful for
things where there only is one document, or you are only interested in
the first. You don't have to deal with the cursor.
The MongoCollection::findOne method will directly return the result array and the MongoCollection::find one will return a MongoCursor instance even if it is a single valued result.
mongodb.org has an performance test report where they compared findOne and find. Based on the results it would seem that findOne is 35-45% faster.
Few data points from the report:
find_one (small, no index): 989 Ops/s
find (small, no index): 554 Ops/s
It is almost like an alias but instead of return you a list, it returns you an object.
It depends on your search query. E.g if you search by ID, since ID is unique it would not need to limit the results because only one result would be found. If more than one record is found then it would limit the results by 1. Another difference is that findOne returns an array, while find returns a mongoCursor.

Categories