Extract MySQL Query using Regex - php

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

Related

PDO: UPDATE not working

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

Sorting array in php (OpenCart addresses)

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

Im trying to get this code to do a multiple keyword search

When I type about three keywords or more it seems to only search the last keyword i.e sydney+region+nsw it will only search nsw.
I want it to search multiple keywords or the complete search term when inputted.
This is the code:
if($_REQUEST['searchkey']!="" && $_REQUEST['searchkey']=="search_record"){
//Remove any html/javascript.
$keyword = secureValue($_REQUEST['keyword']);
$cat_id = intval($_REQUEST['cat_level_root']);
$subcat_id = intval($_REQUEST['cat_level_one']);
$sub_subcat_id = intval($_REQUEST['cat_level_two']);
$stateId = intval($_REQUEST['classi_state']);
$hometownId = intval($_REQUEST['classi_zipcode']);
$servicesId = intval($_REQUEST['classified_desc9']);
$cityId = intval($_REQUEST['classi_city']);
$priceId = intval($_REQUEST['classified_title9']);
$ad_key = intval($_REQUEST['ad_id']);
$types = array();
$types_x = explode(" ",$keyword);
$keyword = trim($_REQUEST['keyword']);
foreach($types_x as $keyword) {
$x++;
if($x==0)
$types[]=($keyword!="" && $keyword!="Enter Your Keywords..") ? " " : "";
}
$types=implode($types);
$columns = "SELECT SQL_CALC_FOUND_ROWS * ";
$sql = " FROM tbl_classified
WHERE clsd_sub_subcat_id=1395 AND CONCAT(classified_title, ' ',
classified_desc, ' ', classified_type6, ' ', classified_title2, ' ",
classified_type, ' ', classified_type2, ' ', classified_type3, ' ',
classified_desc3, ' ', classified_type5) LIKE '%$keyword%'
and classified_status='Active'
and paid_status!='Pending'
ORDER BY classified_post_date,classified_featured asc $types";
$sql = $columns.$sql;
$rs_classi=db_query($sql);
$res_classi = mysql_fetch_array(db_query("Select FOUND_ROWS() as total"));
$reccnt=$res_classi['total'];
}
You explode the keyword string with spaces. $types_x = explode(" ",$keyword);
Explode with + (eg. explode("+", $keyword)) or use urldecode before explode.

Having trouble searching a string

Okay I have a csv file that gets parsed and displayed. I want to make it searchable. So I have a form that accepts a user query and compares it to the array to find matches. Now here's what I have:
foreach( $last as $key=>$string ) {
$hits[$key] = strpos( strtolower( $string . " " . $first[$key] . " " . $middle[$key] ), $query );
}
Before this little snippet I force $query to lower also.
So basically this concatenates the full name, Last First Middle, and searches each array item for a match. Then if $hits[$key] != false I can say that there was a match there. So I go back and display that result from the main array of names. Hopefully that makes sense...
Now on the plus side, I will get many results that should show up. Like if I search jo, a list will come up with all of the Johnson last names.
The issue I'm having is results turning up that don't match the query or results not showing up when I know they are in the list of names. So I'll know smith john should return a result, but it will come back with no results.
This is the first time I've really worked on something with a search functionality so I want to do it right.
The strpos() function returns the index of matched substring, meaning it could possibly return 0:
strpos('foo', 'f'); // 0
If the substring is not found, it will return FALSE.
strpos('foo', 'z'); // FALSE
Because both 0 and FALSE are falsy values (meaning they both evaluate to boolean FALSE), you will need to use strict checking:
foreach( $last as $key=>$string ) {
$hits[$key] = strpos( strtolower( $string . " " . $first[$key] . " " . $middle[$key] ), $query ) !== FALSE;
}
Notice the strpos(...) !== FALSE instead of just strpos(...).
Edit (for #baudday):
Code:
<?php
$query = strtolower('Michael');
$last = array('Baier', 'Baker', 'Baker', 'Banfield', 'Banks', 'Barber');
$first = array('Michael', 'Michael', 'Stephanie', 'Christopher', 'Joseph', 'David');
$middle = array('Joseph', 'Daniel', 'Nicole', 'Phillip', 'Andrew', 'Daniel');
foreach ( $last as $key=>$string ) {
$haystack = $string . " " . $first[$key] . " " . $middle[$key] . " " . $first[$key] . " " . $middle[$key] . " " . $last[$key] . " " . $first[$key] . " " . $string . " " . $middle[$key];
$hits[$key] = strpos( strtolower( $haystack ), $query ) !== false;
}
foreach ($hits as $key => $matches) {
if ($matches) {
echo $last[$key] . ', ' . $first[$key] . ' ' . $middle[$key] . ' (key: ' . $key . ") matches the query.\n";
}
}
Output:
Baier, Michael Joseph (key: 0) matches the query.
Baker, Michael Daniel (key: 1) matches the query.

I need to remove duplicates from an array from a specific code

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

Categories