i have a big array with a lot of subarrays. Each subarray has a few values. Every subarray is an item and values are parameters of that item. I have a searchbar with a POST
method. One of the values of the item is name of the item. So if the client is looking for item_one
, I need to echo some piece of code with parameters of item_one
.
My array looks like this:
$database = [
[
'name'=> 'item_one',
'img_src'=> 'pictures/item_one.jpg',
'preview_href'=> 'item_site.php?id='.item_preview($database).'',
'description'=> 'This product is.....' ,
],
[
'name'=> 'item_two',
'img_src'=> 'pictures/item_two.jpg',
'preview_href'=> 'item_site.php?id='.item_preview($database).'',
'description'=> 'This product is.....' ,
],
// ...
];
and this piece of code i need to use for specific subarray:
echo '<div class="item">
<a href="' . $item['preview_href'] . '" title="' . $item['name'] . '">
<img src="' . $item['img_src'] . '">
<div class="item_description"> '
. $item['name'] . ' ('
. $item['release']
. ') </div>
</a>
</div>'
I have tried loads of different things, for example:
$post = $_POST['search'];
foreach ($database as $item) {
if ($item['name'] == $post) {
echo '<div class="item">
<a href="' . $item['preview_href'] . '" title="' . $item['name'] . '">
<img src="' . $item['img_src'] . '">
<div class="item_description"> ' . $item['name'] . ' (' . $item['release'] . ') </div>
</a>
</div>'
}
}
I have been trying for a few days so I will be happy for any advice. Thanks
Your code is not very forgiving. If the user does not type the name exactly as you have it in your database, you will not get a match.
I would try a couple of things.
if you need exact match:
if( strtoupper($post) === strtoupper($item['name']))
{ // item found}
or, if you want to search for substring, try
if( stripos($item['name'], $post) !== false)
{ //item was found }
I've added two approaches to filter your array using array_filter and array_reduce, both using stripos to test for an occurance of your search keyword with the item's name.
<?php
$items = [
[
'name'=> 'foo',
'img_src'=> 'pictures/item_one.jpg',
'preview_href'=> 'item_site.php?id=1',
'description'=> 'Generic description...' ,
],
[
'name'=> 'cat food',
'img_src'=> 'pictures/item_two.jpg',
'preview_href'=> 'item_site.php?id=2',
'description'=> 'This may smell bad but your cat...' ,
],
[
'name'=> 'dog food',
'img_src'=> 'pictures/item_three.jpg',
'preview_href'=> 'item_site.php?id=2',
'description'=> 'These biscuits...' ,
]
];
$search = 'food';
$matches = array_filter($items, function($item) use ($search) {
if(stripos($item['name'], $search) !== false)
return true;
});
var_export($matches);
$matches = array_reduce($items, function($matches, $item) use ($search) {
if(stripos($item['name'], $search) !== false)
$matches[] = $item;
return $matches;
}, []);
var_export($matches);
Array filter result:
array (
1 =>
array (
'name' => 'cat food',
'img_src' => 'pictures/item_two.jpg',
'preview_href' => 'item_site.php?id=2',
'description' => 'This may smell bad but your cat...',
),
2 =>
array (
'name' => 'dog food',
'img_src' => 'pictures/item_three.jpg',
'preview_href' => 'item_site.php?id=2',
'description' => 'These biscuits...',
),
)
Array reduce result:
array (
0 =>
array (
'name' => 'cat food',
'img_src' => 'pictures/item_two.jpg',
'preview_href' => 'item_site.php?id=2',
'description' => 'This may smell bad but your cat...',
),
1 =>
array (
'name' => 'dog food',
'img_src' => 'pictures/item_three.jpg',
'preview_href' => 'item_site.php?id=2',
'description' => 'These biscuits...',
),
)
You could change your test filter to something like:
if(preg_match("/(\b)$search/i", $item['name']))
This might be useful as word boundaries are respected. A search for oo
above would not match. But a search for foo
would match all.
You might also want to look at word stemming for your search terms (there are freely available libraries for this).
And/or possibly add and search a non-public field associated with each item containing alternative names/keywords for each item.
For large datasets, you'll probably end up using a database, and can leverage queries to filter resultsets instead of filtering arrays.
You might want to filter user input before:
$search = preg_replace('/[^\sa-zA-Z0-9]/', '', $search); // Remove non word chars but not spaces.
$search = preg_replace('/[\s]+/', ' ', $search); // Replace multiple spaces with one.
Or at least escape with preg_quote before the preg_match.
(You may need to tweak those regexes patterns. I welcome feedback/edits here.)