I am trying to implement search in Laravel. I want to search on models.
Since there can be many records in the database, I am trying the chunk function.
public function searchLeads($param)
{
$results = array();
// get all leads
Lead::chunk(100, function($leads) use ($results, $param) {
// search in name
$results = array_merge($results, $this->repository->searchInName($leads, $param));
// search in email
$results = array_merge($results, $this->repository->searchInEmail($leads, $param));
// and so on ...
}
// eliminate duplicates
$collection = collect($results);
$collection = $collection->unique();
$results = $collection->all();
dd($results);
// return $results;
}
Note: The searchIn... functions return array of results and are working as expected.
When I try the above code, I get an empty array. So I changed the following line (added a reference & to $results).
Lead::chunk(100, function($leads) use (&$results, $param) {
Now I get the expected output.
My question is, have I stumbled upon the right solution, or am I missing something that might introduce bugs in the code?
Note:
I know using where clause is a better and efficient way; but I cannot use where for this.
I got the solution after reading a bit about php closures. My real worry was that I am not using the $results array correctly.
But after reading php docs, I know I am doing it correctly.
Please note that I am aware of where clause and it's usage would be much more efficient here. But that's not what I was trying to ask.
to use the search, you could do something like:
$results = Lead::where('mail','like', $param)->orWhere('name','like', $param)->get();
then mysql does the search, which i believe is the fastes way of doing it.
depending on how the search should be done:
...where('mail','like', %$param%)...
https://laravel.com/docs/5.1/queries#where-clauses
else try to describe what the end goal of your search is?
Related
I have a function that takes a string and does a (very broad) match for it against multiple fields (aka. almost all of my DB fields in the table). This seems somewhat kludgy, but it works; however, this is not my primary concern at the moment.
Is it possible to: show which 'orwhere' returned the record into collection? I would like to show (on the results view) what part of the record the string matched.
$apps = Application::all();
$apps->where('bill_company_name', 'like', '%'.$request->filter.'%');
$apps->orwhere('bill_address', 'like', '%'.$request->filter.'%');
$apps->orwhere('bill_city', 'like', '%'.$request->filter.'%');
...
$apps = $apps->paginate();
$apps->withPath('custom/url');
return $apps;
I know I could probably do this on the view (via some more code grepping the filter against the record again), but this option sounds even more laborious.
Thank you!
You could do:
$records = Model::query();
$records = $records->where(‘field’, ‘value’);
…
$records_where = $records->orWhere(‘field’, ‘value’)->get();
if($records_where->isNotEmpty()){
// save into array this one that matched
}
$records = Model::query();
And then on view iterate over the ones that matched, but this process may take quiet a bit if you have too many fields…
In your model,
public function getMatch($str) {
if (strpos($this->bill_address, $str) !== false) {
return "bill_address";
} elseif (...) { ... }
}
Not really answers the question, so might be slightly off-topic, but might help you in the future: as you already noticed that what you are doing becomes a bit messy this way, i recommend solving the problem with a different technology. For example the lucene search engine (used by Solr and elastic-search) offers a debug functionality that can be used to show in detail how the score of a returned record was composed, so you can see what part of the query hit.
And its much faster :)
https://lucene.apache.org/solr/guide/6_6/common-query-parameters.html#CommonQueryParameters-ThedebugParameter
Can you try
orwhere -> orWhere
https://laravel.com/docs/5.5/queries#where-clauses
I know how to remove something from an array but in this case its a bit different. My code seems to generate this annoying item in the array called "*items", I'm not sure how to remove it.
I need it removing because my application visually displays all the data in the array and right now there's just a blank space because of this item.
My code
Basically in my code I have converted an object to an array like this
$accounts = Account::where('archive', false)->select('id', 'display_name')->get();
$accounts = (array) $accounts;
I'm 100% sure its to do with this. is there a way to remove the "*items" item from the array?
I've tried
array_pop($array);
this didn't work for me it just removed the last item before "*item"
unset($array['*item']);
This also didn't work, it just didn't unset anything at all.
Picture
EDIT
I'm working on someone else's code here and there is a lot of random features and functions, writing and explaining the whole script would take a silly amount of time so I tried to include what I thought would be necessary.
Casting your object with (array) may have a weird behavior here. You could try toArray:
$accounts = Account::where('archive', false)
->select('id', 'display_name')
->get()
->toArray();
Then you could check the result with dd:
dd($accounts);
Awkwardly i found an answer to this immediately after posting it..
Instead of using the following feats of code...
$accounts = Account::where('archive', false)->select('id', 'display_name')->get();
$accounts = (array) $accounts;
I used
foreach($account in $accounts){
$test = new \stdClass();
$test = (array) $test;
$test[$index]['Revenue'] = (double) $account->revenue;
$test[$index]['Expense'] = (double) $account->expense;
$test[$index]['Profit'] = $account->sum;
$test[$index]['ID'] = $id;
$test[$index]['Account Name'] = $display_name;
}
this still is confusing however because ive tried making a new array and then adding the values through that but it wouldnt work..?
EDIT
i fully understand this is a highly ineffecient way of doing things but im working with a deadline and this is working, if you have anything to add please do! ill review the criticism when i have time and hopefully i can improve the code with your help!
I'm struggling a bit with resetting a pointer. I want to do this because I'm going to use the same query twice in the same script. As far as I can work out I can do this with resetting the pointer after I've looped trough the fetched array. If there is a better way to do this, I'd love to hear it.
Anyway, this is what I got.
$getEvent = $connection->prepare("SELECT * BLABLA FROM BLABLA");
$getEvent->bind_param("i", $eventID);
$getEvent->execute();
$getEvent->bind_result($eventMember, $eventStaff, $eventMemberID, $eventMemberSuper);
while($getEvent->fetch())
{
// Do stuff
}
// Then bunch of code, before finally another
//$getEvent->execute(); //Script doesn't work without this and next line
//$getEvent->bind_result($eventMember, $eventStaff, $eventMemberID, $eventMemberSuper);
while($getEvent->fetch())
{
// Do other stuff
}
I've tried with $getEvent->data_seek(0); but no luck. The script only works if I redeclare $getEvent->bind_result. Thanks in advance for any replies.
This places unnecessary extra strain on the database server. Rather than rewind and reuse the result set, store the whole thing in an array to begin with. You may then use it as many times and different ways as you like in the PHP application code.
Update Fixed code so it should work with MySQLi rather than PDO. Also, made the results into an associative array.
$results = array();
while($getEvent->fetch())
{
$results[] = array('eventMember'=>$eventMember, 'eventStaff'=>$eventStaff, 'eventMemberID'=>$eventMemberID, 'eventMemberSuper'=>$eventMemberSuper);
}
// Now use $results however you need to.
I have code in php such as the following:
while($r = mysql_fetch_array($q))
{
// Do some stuff
}
where $q is a query retrieving a set of group members. However, certain groups have there members saved in memcached and that memcached value is stored in an array as $mem_entry. To run through that, I'd normally do the following
foreach($mem_entry as $k => $r)
{
// Do some stuff
}
Here's the problem. I don't want to have two blocks of identical code (the //do some stuff section) nested in two different loops just because in one case I have to use mysql for the loop and the other memcached. Is there some way to toggle starting off the loop with the while or foreach? In other words, if $mem_entry has a non-blank value, the first line of the loop will be foreach($mem_entry as $k => $r), or if it's empty, the first line of the loop will be while($r = mysql_fetch_array($q))
Edit
Well, pretty much a few seconds after I wrote this I ended up coming with the solution. Figure I'd leave this up for anyone else that might come upon this problem. I first set the value of $members to the memcached value. If that's blank, I run the mysql query and use a while loop to transfer all the records to an array called $members. I then initiate the loop using foreach($members as as $k => $r). Basically, I'm using a foreach loop everytime, but the value of $members is set differently based on whether or not a value for it exists in memcached.
Why not just refactor out doSomeStuff() as a function which gets called from within each loop. Yes, you'll need to see if this results in a performance hit, but unless that's significant, this is a simple approach to avoiding code repetition.
If there's a way to toggle as you suggest, I don't know of it.
Not the ideal solution but i will give you my 2 cents. The ideal would have been to call a function but if you dont want to do that then, you can try something like this:
if(!isset($mem_entry)){
$mem_entry = array();
while($r = mysql_fetch_array($q))
{
$mem_entry[] = $r;
}
}
The idea is to just use the foreach loop to do the actual work, if there is nothing in memcache then fill your mem_entry array with stuff from mysql and then feed it to your foreach loop.
the following code produces the error in the title. I've tried to google it, but all I got were pages who got the same error (and not an explanation thereof). This isn't really a problem since it's actually working and cancelling the error out with the # works out just fine. Though I'm still wondering why I haven't been able to execute array_multisort just once without getting this error.
public function getMostRelevant(){
list($occurrences, $keywords) = $this->occurr_keyw_array;
array_multisort($occurrences, SORT_DESC, SORT_NUMERIC,
$keywords);
$return_array = array(
array($occurrences[0], $keywords[0]),
array($occurrences[1], $keywords[1]),
array($occurrences[2], $keywords[2])
);
return $return_array;
}
You can apply a check before the function to check if it's an array. For example:
if(is_array($occurrences)){
array_multisort($occurrences, SORT_DESC, SORT_NUMERIC,$keywords);
}
I think this would help you.
Make sure that $this->occurr_keyw_array and then $occurrences contain what you expect them to contain.
You could try to declare the arrays you use beforehand:
$occurrences = array();
It doesn't make sense for me particularly, but it worked here. I suppose it's One More PHP Quirk.