Filtering search engine data - php

I have a problem with filtering information using a form,
Here is my code
$cooperation = Cooperation::with('user')->get();
$search_results = [];
$search = Input::get('q');
$category = Input::get('c');
$land = Input::get('l');
if(!empty($search || $category || $land)){
$search_results = $cooperation;
if (!empty($search)){
$search_results = $search_results->where('title', 'like', '%'. $search .'%');
}
if (!empty($category)){
$search_results = $search_results->where('category', $category);
}
if (!empty($land)){
$search_results = $search_results->where('land', $land);
}
$exist_s = true;
$not_s = false;
return view('cooperation.index', compact('cooperation', 'search_results', 'exist_s', 'not_s'));
}
else{
$not_s = true;
$exist_s = false;
return view('cooperation.index', compact('cooperation', 'search_results', 'exist_s', 'not_s'));
}
After retrieving data from the form I am trying to filter through the array in sequence by each variable but nothing happens, the only thing that works is filtering in $ category but I do not know why the rest does not work.
I'm looking for a solution as to how to filter data efficiently, I could do it if () after if () but with more variables it would be a very inefficient solution.
If anyone has any idea in advance thank you.

If you want to have an efficient search according to your requirements you can have following input variables:
$columns, $searchColumns, $search_operator, $search_input
$columns can be the columns through which you can order, searchColumns can be the columns through which you want to have search and search_operator as in like, <, <=, in, >, >= etc, you can even improvise with the direction as asc or dsc in values, so you can have something like this:
return $query
->orderBy($request->column, $request->direction)
->where(function($query) use ($request, $searchColumns) {
if($request->has('search_input')) {
for($x = 0, $l = count($searchColumns); $x < $l; $x++) {
if($request->search_operator == 'in') {
$query->whereIn($searchColumns[$x], explode(',', $request->search_input));
} else if($request->search_operator == 'like') {
$query->orWhere($searchColumns[$x], 'LIKE', '%'.$request->search_input.'%');
}
else {
$query->orWhere($searchColumns[$x], $this->operators[$request->search_operator], $request->search_input);
}
}
}
})
->paginate(100);

I don't know why your request is not working. However, if you are looking for a generic way of filtering your results I believe a simple foreach loop with an array of your filters variables would do the trick :
$filters = []; //your variables such as category and land go in there
foreach ($filters as $column => $value){
$search_results = $search_results->where($column, $value);
}

Related

Argument 1 passed to Illuminate\Database\Grammar::parameterize() must be of the type array, string given

It clear shown that $file_ids is array type but still getting this error, and I used different function to know the data type of variable like gettype() it also return array.please help me to get rid from this headache.
Thanks in advance.
public function getFilesForLink(Request $request)
{
$file_ids = array();
$ids = $request->input('selected_file');
if (count($ids) > 0) {
foreach ($ids as $id => $value) {
$file_ids[] = base64_decode($value);
}
}
$link_id = $this->makeDownloadLink($file_ids, $_POST['password']);
if ($_POST['via'] == 'Email') {
$files = File::find($file_ids);
foreach ($files as $name) {
$files_name[] = $name->name;
}
$this->sendEmail($files_name, $link_id, $_POST['recipient'],
$_POST['subject'], $_POST['body']);
}
In one place you are using $file_ids and in others $files_ids so make sure you are using same variable.
In addition are you sure you have valid values in $file_ids array?
Looking at the comment the problem is:
$downloadLink->file_ids = $file_ids;
inside makeDownloadLink method.
You are doing something like this:
if (count($file_ids) > 1) {
$downloadLink->file_ids = implode(',', $file_ids);
}
$downloadLink->file_ids = $file_ids;
and this will fail when $file_ids is array. You should probably add else here like so:
if (count($file_ids) > 1) {
$downloadLink->file_ids = implode(',', $file_ids);
}
else {
$downloadLink->file_ids = $file_ids;
}
check this pieces of code
$files = File::get($file_ids);
replace get() with find()
$files = File::find($file_ids);

Optimise search in JSON with strings in ascending order

I have this JSON here
At the root, there is a command(property) as wp which has 39 sub-commands(sub-properties) as cache, cap, checksum...etc, where each has its own subcommands and this goes up to 4 levels
The better part is that all subcommands are arranged in ascending order, i.e.; strings are arranged in ascending order.
I want to traverse and search whether a command like wp site create or wp term delete exists in the JSON tree. I don't want to iterate using a for loop due to huge time complexity. It's been too long since I've completed my engineering and if my memory serves correctly, a tree structure would greatly improvise the search time.
Can anyone point me to the right direction on achieving this? I'm using PHP as my language.
here's a binary search solution, you'll need to put your json into a file...
NOTE: because wp isn't in a subcommands array you can't search for it
<?php
function binarySearch(&$myArray, $search, $start, $end)
{
$middle = ($start + $end) >> 1; // divide by 2
if ($middle >= $start) {
if ($search > $myArray[$middle]['name']) { // $search must be in top half of array
$result = binarySearch($myArray, $search, $middle + 1, $end);
} elseif ($search < $myArray[$middle]['name']) { // $search must be in bottom half of array
$result = binarySearch($myArray, $search, $start, $middle - 1);
} else { // $search is here
$result = $middle;
}
} else {
$result = false; // $search not found
}
return $result;
}
function findCommand($arrFound, $strFind)
{
$arrFind = explode(' ', $strFind);
while ($arrFound !== false and list($key, $strCommand) = each($arrFind)) {
$arrSearch = $arrFound['subcommands'];
if (($key = binarySearch($arrSearch, $strCommand, 0, count($arrSearch) - 1)) === false) {
$arrFound = false;
} else {
$arrFound = $arrSearch[$key];
}
}
return $arrFound;
}
// get json from file and convert it to an array
$arrJson = json_decode(file_get_contents('items.json'), true);
$arrCommand = findCommand($arrJson, 'site create');
var_dump($arrCommand);
$arrCommand = findCommand($arrJson, 'term delete');
var_dump($arrCommand);
though using native functions array_search() and array_column() will probably be quicker
<?php
function findCommand($arrFound, $strFind)
{
$arrFind = explode(' ', $strFind);
while ($arrFound !== false and list($key, $strCommand) = each($arrFind)) {
$arrSearch = $arrFound['subcommands'];
if (($key = array_search($strCommand, array_column($arrSearch, 'name'))) === false) {
$arrFound = false;
} else {
$arrFound = $arrSearch[$key];
}
}
return $arrFound;
}
// get json from file and convert it to an array
$arrJson = json_decode(file_get_contents('items.json'), true);
$arrCommand = findCommand($arrJson, 'site create');
var_dump($arrCommand);
$arrCommand = findCommand($arrJson, 'term delete');
var_dump($arrCommand);

How can I exclude certain records from an XML parse?

I'm pulling data from an XML file using the following code:
<?php
$url = 'http://www.inveroak.com/readerimages/livepanel/91221.xml';
$xml = simplexml_load_file($url);
$items = array();
$exclude = array('4419','4373');
$items = array_diff($items, $exclude);
foreach($xml as $Reader) {
$items[] = $Reader;
}
usort ($items, function($a, $b) {
return strcmp($a->Status,$b->Status);
});
foreach($items as $Reader) {
if($Reader->Status != 'Logged Off' && $Reader->Picture != 'None')
{
include '/extras/reader-single.php';
}
}
?>
The two lines showing $exclude and $items I've added afer seeing another post excluding values from a foreach loop about excluding from XML, but when i load the page.. the two records that have the PINs specified, are still showing.
Is this the correct way to exclude pulling certain records from an XML file?
Any help is greatly appreciated!
EDIT: The four digit numbers entered are a PIN number found at Reader->PIN
After thinking, could it be that it's not making the link between the number and the Reader->PIN on the xml file?
There is a much simpler way to specifically query for attributes - or to exclude them.
$url = 'http://www.inveroak.com/readerimages/livepanel/91221.xml';
$xml = simplexml_load_file($url);
$matches = $xml->xpath( "//Reader[Pin!=4419 and Pin!=4373]" );
This will give you the entire structure, minus the two items # 4419 and # 4373.
As I told in comments, get the pin of each record, compare it to the exclude array, if it is part of the exclude array then just continue the loop. Like this:
$url = 'http://www.inveroak.com/readerimages/livepanel/91221.xml';
$xml = simplexml_load_file($url);
$items = array();
$exclude = array('4419','4373');
$items = array_diff($items, $exclude);
foreach($xml as $Reader) {
$items[] = $Reader;
}
usort ($items, function($a, $b) {
return strcmp($a->Status,$b->Status);
});
foreach($xml as $Reader) {
if($Reader->Status != 'Logged Off'
&& $Reader->Picture != 'None'
// check if the Pin is in exclude array
&& !in_array($Reader->Pin, $exclude)
) {
include '/extras/reader-single.php';
}
}
Alternatively you may use array_filter():
$url = 'http://www.inveroak.com/readerimages/livepanel/91221.xml';
$xml = simplexml_load_file($url);
$items = array();
$exclude = array('4419','4373');
$items = array_diff($items, $exclude);
foreach($xml as $Reader) {
$items[] = $Reader;
}
$items= array_filter($items, function($Reader) use ($exclude) {
if($Reader->Status == 'Logged Off'
|| $Reader->Picture == 'None'
|| in_array($Reader->Pin, $exclude)
) {
return false;
}
return true;
});
usort ($items, function($a, $b) {
return strcmp($a->Status,$b->Status);
});
foreach($items as $Reader) {
include '/extras/reader-single.php';
}
Another way would be filter them out in the first foreach loop:
foreach($xml as $Reader) {
if (array_search($Reader->Pin, $exclude) === FALSE) {
$items[] = $Reader;
}
}
In either case, you do not need:
$items = array_diff($items, $exclude);
array_diff() returns the values from the first array ($items) that do not exist in the second array ($exclude). Because in your case the first array is an empty array, it has no values, so array_diff() will also always return an empty array.
Perhaps someone will come along with an XPath solution - that would be another approach. (EDIT - Ah, I see #pp19dd has supplied this.)

Closures in programmatically generated Eloquent OR queries

I am trying to parse a query string into Eloquent that involves 'OR' statements.
This is part of a much larger function that has other filters etc being applied, but I want to make an or_where group.
My confusion comes with the closure.. and how to make sure the right values are passed through. If I do as code below, it says the closure has the wrong arguments, but otherwise I cannot give it access to the $or_list variable.
($thing_query is the query that's being built over the course of this and other functions.)
elseif (strstr($column, 'or|')){
//in format or|=tablename-id=240,tablename-id=8
$or_list = explode(',', $value);
var_dump(explode(',', $value));
$thing_query->where(function($q, $or_list)
{
$count = 0;
foreach ($or_list as $or) {
$arr = explode('=', $or);
$col = $arr[0];
$val = $arr[1];
$col = str_replace('-', '.', $col);
if($count == 0){
$q->where($col, '=', $val);
} else {
$q->or_where($col, '=', $val);
}
$count++;
}
});
}
Try this:
$thing_query->where(function($q) use($or_list)
{
...
http://blog.dubbelboer.com/2012/04/07/php-use-keyword.html

Sorting search results array by number of matches?

I'm building a basic search function for my site. Realising that the most useful search displays the page with the most counts of the terms given, I coded the following:
function search()
{
$this->page = preg_replace('/[^\w \"\']/i', '', trim($this->page));
preg_match_all('/"(.[^"]+)"|([\w]+)/i', $this->page, $terms);
$terms=array_unique($terms[0]); // scrub duplicate search terms
$tsql="SELECT reviewSummary, reviewFullText, game.gameName FROM review LEFT JOIN game ON review.gameID = game.gameID ";
$constraint="WHERE";
foreach ($terms as $term)
{
$term=str_replace('"','',$term);
$tsql.=" $constraint (reviewSummary LIKE '%".$term."%' OR reviewFullText LIKE '%".$term."%' OR game.gameName LIKE '%".$term."%')";
$constraint="AND";
}
$tsql .= "AND game.isPublished = 'y'";
$result = $this->sql->db_query($tsql);
if (mysql_num_rows($result)!=0)
{
while($row = mysql_fetch_array($result))
{
$gameName = stripslashes($row['gameName']);
$content = strip_tags($row['reviewFullText']) . ' ' . $row['reviewSummary'];
$counter = 0;
foreach($terms as $term)
{
$term=str_replace('"','',$term);
preg_match_all("/($term)/i", $content, $matches);
foreach($matches[0] as $m)
{
$counter++;
}
}
$found["Games"][$gameName]=$counter;
}
}
print_r($found);
}
Works great. What it doesn't do is order the results in according to which has the most matches. I'm not sure how to sort the resulting array to achieve this, can anyone help?
Take a look at at uasort() which can sort an associative array using a user-defined comparison function. Something like this should do it...
function cmp($a, $b) {
if ($a == $b) {
return 0;
}
return ($a < $b) ? 1 : -1;
}
uasort($found["Games"], 'cmp');

Categories