I have the following code:
public function ajax()
{
// Contains results
$data = array();
if( isset($this->request->get['keyword']) ) {
// Parse all keywords to lowercase
$keywords = strtolower( $this->request->get['keyword'] );
// Perform search only if we have some keywords
if( strlen($keywords) >= 3 ) {
$parts = explode( ' ', $keywords );
$add = '';
// Generating search
foreach( $parts as $part ) {
$add .= ' AND (LOWER(pd.name) LIKE "%' . $this->db->escape($part) . '%"';
$add .= ' OR LOWER(p.model) LIKE "%' . $this->db->escape($part) . '%")';
}
$add = substr( $add, 4 );
$sql = 'SELECT pd.product_id, pd.name, p.model FROM ' . DB_PREFIX . 'product_description AS pd ';
$sql .= 'LEFT JOIN ' . DB_PREFIX . 'product AS p ON p.product_id = pd.product_id ';
$sql .= 'LEFT JOIN ' . DB_PREFIX . 'product_to_store AS p2s ON p2s.product_id = pd.product_id ';
$sql .= 'WHERE ' . $add . ' AND p.status = 1 ';
$sql .= ' AND p2s.store_id = ' . (int)$this->config->get('config_store_id');
$sql .= ' ORDER BY LOWER(pd.name) ASC, LOWER(p.model) ASC';
$sql .= ' LIMIT 15';
$res = $this->db->query( $sql );
if( $res ) {
$data = ( isset($res->rows) ) ? $res->rows : $res->row;
// For the seo url stuff
$basehref = 'product/product&keyword=' . $this->request->get['keyword'] . '&product_id=';
foreach( $data as $key => $values ) {
$data[$key] = array(
'name' => htmlspecialchars_decode($values['name'] . ' (' . $values['model'] . ')', ENT_QUOTES),
'href' => $this->url->link($basehref . $values['product_id'])
);
}
}
}
}
echo json_encode( $data );
}
So, the array generates a list of products, like for e.g.:
Apple MacBook (Product Model 10)
Apple МакБук (Product Model 10)
The problem is that those two products is actually one and the same product (same product_id) but in different languages, and both have the same URL.
So, what I want to check is, while making the array, the code to check if there is already a product with that product_id in the array, and if there is, not to add another one with the same product_id.
Practically, I don't want the array to generate two or more products with the same product_id.
EDIT: With Marc's code and ghbarratt suggestion work like a charm. A million thanks to you guys, and to all of you here.
P.S. How can I add ASC or DESC for ORDER BY pd.language_id:
$sql .= ' ORDER BY pd.language_id = ' . (int)$this->config->get('config_language_id');
$sql .= ' , LOWER(pd.name) ASC, LOWER(p.model) ASC';
$data = array();
foreach ($res->rows as $values) {
$data[$values['product_id']] = array(
'name' => ...,
'href' => ...
);
}
Guarantees unique product ids only.
The easiest way should be to add another array to track already written ids and check with http://php.net/manual/en/function.in-array.php:
$basehref = 'product/product&keyword=' . $this->request->get['keyword'] . '&product_id=';
$writtenIds = array();
foreach( $data as $key => $values ) {
if(in_array($values['product_id'], $writtenIds))
{
unset($data[$key]);
continue;
}
$data[$key] = array(
'name' => htmlspecialchars_decode($values['name'] . ' (' . $values['model'] . ')', ENT_QUOTES),
'href' => $this->url->link($basehref . $values['product_id'])
);
$writtenIds[] = $values['product_id'];
}
This answer is similar to Marc's except it will preserve the other names in an additional element on the data array for the product_id and it will make sure to remove the sub-arrays that have the same product_id as the first encountered one, which I believe is an important part of what you wanted to do.
$product_ids_added = array();
foreach( $data as $key => $values ) {
$original_key = array_search($values['product_id'], $product_ids_added);
if($original_key===false) {
$data[$key] = array(
'name' => htmlspecialchars_decode($values['name'] . ' (' . $values['model'] . ')', ENT_QUOTES),
'href' => $this->url->link($basehref . $values['product_id'])
);
$product_ids_added[] = $values['product_id'];
}
else {
unset($data[$key]);
if(!isset($data[$original_key]['additional_names'])) $data[$original_key]['additional_names'] = array();
$data[$original_key]['additional_names'][] = htmlspecialchars_decode($values['name'] . ' (' . $values['model'] . ')', ENT_QUOTES);
}
}
Related
does not work with a nested element
the elements of the first level are output, and the nested array with data is not read, as it is possible to get values - id, title and location?
<?php
function removeBomUtf8($s){
if(substr($s,0,3)==chr(hexdec('EF')).chr(hexdec('BB')).chr(hexdec('BF'))){
return substr($s,3);
}else{
return $s;
}
}
$url = "https://denden000qwerty.000webhostapp.com/opportunities.json";
$content = file_get_contents($url);
$clean_content = removeBomUtf8($content);
$decoded = json_decode($clean_content);
while ($el_name = current($decoded)) {
// echo 'total = ' . $el_name->total_items . 'current = ' . $el_name->current_page . 'total = ' . $el_name->total_pages . '<br>' ;
echo ' id = ' . $el_name->data[0]->id . ' title = ' . $el_name->data.title . ' location = ' . $el_name->data.location . '<br>' ;
next($decoded);
}
?>
$el_name->data[0]->id is correct
$el_name->data.title is not
you see the difference?
and $decoded is the root (no need to iterate over it) - you want to iterate over the data children
<?php
foreach($decoded->data as $data)
{
$id = (string)$data->id;
$title = (string)$data->title;
$location = (string)$data->location;
echo sprintf('id = %s, title = %s, location = %s<br />', $id, $title, $location);
}
I want to extract query and separated to array like this
My problem is i need [from => account_admin] and have [join => ['LEFT JOIN account_admin_role_relation ON account_admin.id = account_admin_role_relation.admin_id', 'LEFT JOIN account_admin_role ON account_admin_role_relation.admin_role_id = account_admin_role.id']]
This is my progress :
$query = '
SELECT account_admin.id, account_admin.name, email, account_admin_role.name AS role FROM account_admin
LEFT JOIN account_admin_role_relation ON account_admin.id = account_admin_role_relation.admin_id
LEFT JOIN account_admin_role ON account_admin_role_relation.admin_role_id = account_admin_role.id
WHERE status = 1
GROUP BY account_admin.id
';
$matches = null;
$regex_value = '(?:\w++|`[^`]*+`|"(?:[^"\\\\]++|\\\\.)*+"|\'(?:[^\'\\\\]++|\\\\.)*+\'|\s++|[^`"\'\w\s])*?';
preg_match('/^\s*(?:\bSELECT\b\s*(' . $regex_value . '))?(?:\bFROM\b\s*(' . $regex_value . '))?(?:\bWHERE\b\s*(' . $regex_value . '))?(?:\bGROUP\s+BY\b\s*(' . $regex_value . '))?(?:\bORDER\s+BY\b\s*(' . $regex_value . '))?(?:\bLIMIT\b\s*(' . $regex_value . '))?(?:;|$)/si', $query, $matches);
$parts = array_combine(['query', 'select', 'from', 'where', 'group', 'order', 'limit'], $matches + array_fill(0, 7, ''));
if (preg_match_all('/(LEFT|INNER|OUTER|RIGHT)?\sJOIN((?:(?!\sJOIN).)+)/i', 'FROM ' . $parts['from'], $matches)) {
$parts['join'] = $matches[0];
}
if (preg_match('/FROM\s+(.+)/i', 'FROM ' . $parts['from'], $matches)) {
$parts['from'] = $matches[1];
}
print_r($parts);
Edit : I just looking for simple array as output because i just working with simple query select .. from .. join .. where .. group .. order .. limit
I wrote some code to update a mySQL table via php/PDO.
But it is not working and I just can't figure out where my mistake is.
The execute() returns true, but the changes never actually show up in the table.
My code looks pretty much like this:
$columnObject = array(
"emailAddress"=>"aaa#aaa.com",
"passwordHash"=>"56bj5g63j4g57g567g5k75jh7gk4g74j5hg67",
"name"=>"qweqweqwe",
"lastActivity"=>4128649814
);
$knownColumnName = "emailAddress";
$knownColumnData = "aaa#aaa.com";
foreach ($columnObject as $columnName => $columnData) {
$pdoUpdateString .= $columnName . "=:" . $columnName . ",";
$pdoExecuteObject[$columnName] = $columnData;
}
$pdoUpdateString = rtrim($pdoUpdateString, ",");
$pdoExecuteObject['knownColumn'] = $knownColumnData;
$q = $this->hCon->prepare('UPDATE ' . $this->name . ' SET ' . $pdoUpdateString . ' WHERE ' . $knownColumnName . '=:knownColumn');
$q->execute($pdoExecuteObject);
I am trying to add wheres to my query depending on what's coming in from GET:
public function index($type_id) {
$Product = new Product;
$Product->where('type_id', $type_id);
if(array_key_exists('ages', Input::get())) {
$Product->where('age_id', $_GET['ages']);
}
$products = $Product->get();
$productsPaginated = $Product->where('type_id', $type_id)->paginate(2);
return View::make('products.products', array(
'products' => $products,
'productsList' => $productsPaginated
)
);
}
But all it's doing is bringing back every record.
What am I doing wrong?
This is how I'm rendering my filters:
$brands = $prices = $ages = $brandsUsed = $agesUsed = array();
$out = '';
foreach ($productsList as $product) {
$brands[$product->brands->id] = $product->brands->brand;
$brandsUsed[] = $product->brands->id;
$prices[] = $product->price;
$ages[$product->ages->id] = $product->ages->age;
$agesUsed[] = $product->ages->id;
}
$brandsUsed = array_count_values($brandsUsed);
$brands = array_unique($brands);
$params = Input::get();
$lastParams = http_build_query($params);
unset($params['brand']);
$params = http_build_query($params);
if (count($brands) > 0) {
$out .= '<h5>Brands</h5>';
foreach ($brands as $brandId => $brandName) {
if (stristr($lastParams, '&brand=' . $brandId) || stristr($lastParams, 'brand=' . $brandId)) {
$out .= '<a class="filter-link" href="' . Request::path() . '?' . $params . '">';
} else {
$out .= '<a class="filter-link" href="' . Request::path() . '?' . $params . '&brand=' . $brandId . '">';
}
$out .= '<span class="cbox">';
if (stristr($lastParams, '&brand=' . $brandId) || stristr($lastParams, 'brand=' . $brandId)) {
$out .= '<span class="cbox-checked"></span>';
}
$out .= '</span>';
$out .= $brandName;
$out .= ' (' . $brandsUsed[$brandId] . ')';
$out .= '</a>';
}
}
You cannot create queries on object, you should do it this way:
public function index($type_id) {
$product = Product::where('type_id', $type_id);
if(array_key_exists('ages', Input::get())) {
$product->where('age_id', $_GET['ages']);
}
$productsAll = $product->get();
$productsPaginated = $product->where('type_id', $type_id)->paginate(2);
return View::make('products.products', array(
'products' => $productsAll,
'productsList' => $productsPaginated
)
);
}
You should also consider if it makes any sense to get all products and also paginated products. If you have many products in your database it will take long time to get all your products.
I'm also not sure what exactly you want to get for $productsPaginated. I think you will need here building new query:
$productsPaginated = Product::where('type_id', $type_id)->paginate(2);
EDIT
As you want to get count of products with only one filter, you should use here:
public function index($type_id) {
$product = Product::where('type_id', $type_id);
$productCount = $product->count();
if(array_key_exists('ages', Input::get())) {
$product->where('age_id', $_GET['ages']);
}
$productsPaginated = $product->paginate(2);
return View::make('products.products', array(
'productsCount' => $productCount,
'productsList' => $productsPaginated
)
);
}
I am trying to sort the array $result by 'address' below. I have tried usort() but it does not work.
Thanks for all help
foreach ($results as $result) {
$this->data['addresses'][] = array(
'address_id' => $result['address_id'],
'address' => $result['firstname'] . ' ' . $result['lastname'] . ', ' . $result['address_1'] . ', ' . $result['city'] . ', ' . (($result['zone']) ? $result['zone'] . ', ' : FALSE) . (($result['postcode']) ? $r$
'href' => HTTPS_SERVER . 'index.php?route=account/address/' . $type . '&address_id=' . $result['address_id']
);
}
//The following does not work
usort($result, 'address');
To make usort work, you need to define a custom function:
usort($result, function($a, $b){
// ^ anonymous function
return strcmp($a['address'], $b['address']);
});
usort needs a function as second parameter to sort your data, 'address' doesn't seem to be a function
You try to sort $result but you fill $this->data['addresses'] with data
I would fill $this->data['addresses'] with data and use the thing you want to use as key and then use ksort to sort it, example:
foreach ($results as $result) {
$this->data['addresses'][$result['address_id']] = array(
'address_id' => $result['address_id'],
'address' => $result['firstname'] . ' ' . $result['lastname'] . ', ' . $result['address_1'] . ', ' . $result['city'] . ', ' . (($result['zone']) ? $result['zone'] . ', ' : FALSE) . (($result['postcode']) ? $r$
'href' => HTTPS_SERVER . 'index.php?route=account/address/' . $type . '&address_id=' . $result['address_id']
);
}
ksort($this->data['addresses']);