Adding content of Array into where Condition in SQL query - php

I'm trying to make this function get() that takes tbl_name and condition which will be used in WHERE.
Here $condition is an array like:
$condition = array(
'id' => 'some id',
'anycondition' => 'any value');
public function get($tbl_name, $condition = null) {
if($condition) {
$data = "select * from '$tbl_name' WHERE '$condition'";
}
else {
$data = $tbl_name;
}
return $data;
}
I want the echo be like this
select * from $tbl_name WHERE id='some id' and anycondition='any value'

Try This:
$query ="SELECT * FROM '$tbl_name' WHERE id='".$condition['id']."' AND anycondition='".$condition['anycondition']."'";

$data="select * from '$tbl_name' WHERE
(select array_to_string($condition, 'and', '') as condition);
here (in array_to_string) :
first parameter -->array
2nd -->concatenation text
3rd -->replacement of the null value in your array

This a horrible way a approach a class, which handles the database layer of your application. If I was you I read throughly into mysqli driver http://us2.php.net/manual/en/book.mysqli.php and come up with a better solution.
But here is what I think you were trying to accomplish in your opening post.
class A
{
public function sqlSelect($dbh, $tableName, $params=array()) {
if (!empty($param)) {
foreach ($params as $field => $value) {
// http://www.php.net/manual/en/function.mysql-real-escape-string.php
$value = mysql_real_escape_string($value, $dbh);
$whereSql[] = sprintf("%s = %s", $field, $value);
}
$whereSql = implode(" AND ", $whereSql);
return sprintf("SELECT * FROM %s WHERE %s",
$tableName, $whereSql);
}
return sprintf("SELECT * FROM %s", $tableName);
}
}
$condition = array(
'id' => 1234,
'some_other_column' => 'someOtherValue'
);
echo A.sqlSelect('SomeTableName', $condition);
echo A.sqlSelect('SomeOtherTableName');
Output:
SELECT * FROM SomeTableName WHERE id = 1234 AND some_other_column = 'someOtherValue'
SELECT * FROM SomeOtherTableName

Related

Laravel - how to get the query with bind parameters?

I can get the not-bind query on with this way :
\DB::enableQueryLog();
$items = OrderItem::where('name', '=', 'test')->get();
$log = \DB::getQueryLog();
print_r($log);
Output is :
(
[0] => Array
(
[query] => select * from "order_items" where "order_items"."name" = ? and "order_items"."deleted_at" is null
[bindings] => Array
(
[0] => test
)
[time] => 0.07
)
)
But what I really need is bind query like this :
select * from "order_items" where "order_items"."name" = 'test' and "order_items"."deleted_at" is null
I know I can do this with raw PHP but is there any solution in laravel core?
Actually I've created one function within helpers.php for same. You can also use same function within your helpers.php file
if (! function_exists('ql'))
{
/**
* Get Query Log
*
* #return array of queries
*/
function ql()
{
$log = \DB::getQueryLog();
$pdo = \DB::connection()->getPdo();
foreach ($log as &$l)
{
$bindings = $l['bindings'];
if (!empty($bindings))
{
foreach ($bindings as $key => $binding)
{
// This regex matches placeholders only, not the question marks,
// nested in quotes, while we iterate through the bindings
// and substitute placeholders by suitable values.
$regex = is_numeric($key)
? "/\?(?=(?:[^'\\\']*'[^'\\\']*')*[^'\\\']*$)/"
: "/:{$key}(?=(?:[^'\\\']*'[^'\\\']*')*[^'\\\']*$)/";
$l['query'] = preg_replace($regex, $pdo->quote($binding), $l['query'], 1);
}
}
}
return $log;
}
}
if (! function_exists('qldd'))
{
/**
* Get Query Log then Dump and Die
*
* #return array of queries
*/
function qldd()
{
dd(ql());
}
}
if (! function_exists('qld'))
{
/**
* Get Query Log then Dump
*
* #return array of queries
*/
function qld()
{
dump(ql());
}
}
Simply place these three functions within your helpers.php file and you can use same as follows:
$items = OrderItem::where('name', '=', 'test')->get();
qldd(); //for dump and die
or you can use
qld(); // for dump only
Here I extended the answer of #blaz
In app\Providers\AppServiceProvider.php
Add this on boot() method
if (env('APP_DEBUG')) {
DB::listen(function($query) {
File::append(
storage_path('/logs/query.log'),
self::queryLog($query->sql, $query->bindings) . "\n\n"
);
});
}
and also added a private method
private function queryLog($sql, $binds)
{
$result = "";
$sql_chunks = explode('?', $sql);
foreach ($sql_chunks as $key => $sql_chunk) {
if (isset($binds[$key])) {
$result .= $sql_chunk . '"' . $binds[$key] . '"';
}
}
$result .= $sql_chunks[count($sql_chunks) -1];
return $result;
}
Yeah, you're right :/
This is a highly requested feature, and i have no idea why its not a part of the framework yet...
This is not the most elegant solution, but you can do something like this:
function getPureSql($sql, $binds) {
$result = "";
$sql_chunks = explode('?', $sql);
foreach ($sql_chunks as $key => $sql_chunk) {
if (isset($binds[$key])) {
$result .= $sql_chunk . '"' . $binds[$key] . '"';
}
}
return $result;
}
$query = OrderItem::where('name', '=', 'test');
$pure_sql_query = getPureSql($query->toSql(), $query->getBindings());
// Or like this:
$data = OrderItem::where('name', '=', 'test')->get();
$log = DB::getQueryLog();
$log = end($log);
$pure_sql_query = getPureSql($log['query'], $log['bindings']);
You can do that with:
OrderItem::where('name', '=', 'test')->toSql();

Does this query creator class make sense to you?

I am preparing a simple class. I want to create a query by following a different path. Class below it is a draft. I look forward to your suggestions.
The Cyclomatic Complexity number 4. PHP Mess Detector, PHPCS fixer tools, I have no problems.
My English is not good, I'm sorry.
<?php
class test
{
protected $q = array();
protected $p = array();
public function get()
{
$new = array();
foreach ($this->p as $value) {
$new = array_merge($new, $value);
}
$this->p = $new;
print_r($this->p);
$query = 'select * from table ';
foreach ($this->q as $sql) {
$query .= implode(' ', $sql) . ' ';
}
echo $query . PHP_EOL;
}
public function camelCase($value)
{
return strtolower(preg_replace('/(.)([A-Z])/', '$1 $2', $value));
}
public function __call($method, $params)
{
$clause = $this->camelCase($method);
$clause = explode(' ', $clause);
if ($key = array_search('in', $clause)) {
$clause[$key] = 'in(?)';
} elseif (isset($clause[2]) && in_array($clause[2], array(
'or',
'and'
))) {
$clause[1] = $clause[1] . ' =?';
$clause[3] = $clause[3] . ' =?';
} elseif (isset($clause[0]) && $clause[0] == 'limit') {
$clause[$key] = 'limit ? offset ?';
} elseif (isset($clause[1]) && $clause[1] != 'by') {
$clause[1] = $clause[1] . ' =?';
}
$this->q[] = $clause;
$this->p[] = $params;
return $this;
}
}
The use of the query creator class is as follows.
<?php
(new test())
->orderByIdDesc()
->limit(15)
->get();
(new test())
->whereIdOrName(6,'foo')
->get();
(new test())
->whereIdIsNotNull(10)
->get();
(new test())
->whereIdIn(9)
->get();
(new test())
->whereIdNotIn(8)
->get();
Output:
Array
(
[0] => 15
)
select * from table order by id desc limit ? offset ?
Array
(
[0] => 6
[1] => foo
)
select * from table where id =? or name =?
Array
(
[0] => 10
)
select * from table where id =? is not null
Array
(
[0] => 9
)
select * from table where id in(?)
Array
(
[0] => 8
)
select * from table where id not in(?)
If it does not make sense, you can write why it doesn't make sense.
In terms of responsibility, your class should never echo in a method.
public function get()
{
$new = array();
foreach ($this->p as $value) {
$new = array_merge($new, $value);
}
$this->p = $new;
print_r($this->p);
$query = 'select * from table ';
foreach($this->q as $sql){
$query .= implode(' ', $sql) . ' ';
}
return $query . PHP_EOL;
}
And
<?= (new test())
->orderByIdDesc()
->limit(15)
->get();
Also, you should have a look at existing libraries rather than inventing and maintaining your own (eloquent for instance).
If you're PHP 5.4+ (which I hope), you could use the short array syntax.
The class could probably be final and with private attributes.

Wordpress $wpdb. Insert Multiple Records

Is there any way to accomplish the following in Wordpress with $wpdb->insert or
$wpdb->query($wpdb->prepare)):
INSERT into TABLE (column1, column2, column3)
VALUES
('value1', 'value2', 'value3'),
('otherval1', 'otherval2', 'otherval3'),
('anotherval1', 'anotherval2', 'anotherval3')
...etc
OK, I figured it out!
Setup arrays for Actual Values, and Placeholders
$values = array();
$place_holders = array();
the initial Query:
$query = "INSERT INTO orders (order_id, product_id, quantity) VALUES ";
Then loop through the the values you're looking to add, and insert them in the appropriate arrays:
foreach ( $_POST as $key => $value ) {
array_push( $values, $value, $order_id );
$place_holders[] = "('%d', '%d')" /* In my case, i know they will always be integers */
}
Then add these bits to the initial query:
$query .= implode( ', ', $place_holders );
$wpdb->query( $wpdb->prepare( "$query ", $values ) );
You can also use this way to build the query:
$values = array();
// We're preparing each DB item on it's own. Makes the code cleaner.
foreach ( $items as $key => $value ) {
$values[] = $wpdb->prepare( "(%d,%d)", $key, $value );
}
$query = "INSERT INTO orders (order_id, product_id, quantity) VALUES ";
$query .= implode( ",\n", $values );
I have came across with this problem and decided to build a more improved function by using accepted answer too:
/**
* A method for inserting multiple rows into the specified table
*
* Usage Example:
*
* $insert_arrays = array();
* foreach($assets as $asset) {
*
* $insert_arrays[] = array(
* 'type' => "multiple_row_insert",
* 'status' => 1,
* 'name'=>$asset,
* 'added_date' => current_time( 'mysql' ),
* 'last_update' => current_time( 'mysql' ));
*
* }
*
* wp_insert_rows($insert_arrays);
*
*
* #param array $row_arrays
* #param string $wp_table_name
* #return false|int
*
* #author Ugur Mirza ZEYREK
* #source http://stackoverflow.com/a/12374838/1194797
*/
function wp_insert_rows($row_arrays = array(), $wp_table_name) {
global $wpdb;
$wp_table_name = esc_sql($wp_table_name);
// Setup arrays for Actual Values, and Placeholders
$values = array();
$place_holders = array();
$query = "";
$query_columns = "";
$query .= "INSERT INTO {$wp_table_name} (";
foreach($row_arrays as $count => $row_array)
{
foreach($row_array as $key => $value) {
if($count == 0) {
if($query_columns) {
$query_columns .= ",".$key."";
} else {
$query_columns .= "".$key."";
}
}
$values[] = $value;
if(is_numeric($value)) {
if(isset($place_holders[$count])) {
$place_holders[$count] .= ", '%d'";
} else {
$place_holders[$count] .= "( '%d'";
}
} else {
if(isset($place_holders[$count])) {
$place_holders[$count] .= ", '%s'";
} else {
$place_holders[$count] .= "( '%s'";
}
}
}
// mind closing the GAP
$place_holders[$count] .= ")";
}
$query .= " $query_columns ) VALUES ";
$query .= implode(', ', $place_holders);
if($wpdb->query($wpdb->prepare($query, $values))){
return true;
} else {
return false;
}
}
Source: https://github.com/mirzazeyrek/wp-multiple-insert
In addition to inserting multiple rows using $wpdb, if you ever need to update existing rows following snippet should be helpful.
This is updated snippet of what #philipp provided above.
$values = array();
// We're preparing each DB item on it's own. Makes the code cleaner.
foreach ( $items as $key => $value ) {
$values[] = $wpdb->prepare( "(%d,%d)", $key, $value );
}
$values = implode( ",\n", $values );
$query = "INSERT INTO orders (order_id, product_id, quantity) VALUES {$values} ON DUPLICATE KEY UPDATE `quantity` = VALUES(quantity)";
This is a bit late, but you could also do it like this.
global $wpdb;
$table_name = $wpdb->prefix . 'your_table';
foreach ($your_array as $key => $value) {
$result = $wpdb->insert(
$table_name,
array(
'colname_1' => $value[0],
'colname_2' => $value[1],
'colname_3' => $value[2],
)
);
}
if (!$result) {
print 'There was a error';
}
not very nice, but if you know what you are doing:
require_once('wp-load.php');
mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
#mysql_select_db(DB_NAME) or die();
mysql_query("INSERT into TABLE ('column1', 'column2', 'column3') VALUES
('value1', 'value2', 'value3'),
('otherval1', 'otherval2', 'otherval3'),
('anotherval1', 'anotherval2', 'anotherval3)");

Php arrays -- one title a few record

i have a problem with php in arrays.
i have a db table like that , it shows applications to job.
What i want is to order job titles with their files for example
title must be shown :
WEB Tasarım Uzmanı
noktamedya.com/CVs/zsdfsdfsdfsdfsdf.docx
noktamedya.com/CVs/zsdfsdfsdfsdfsdf.docx
İçerik Yöneticisi
noktamedya.com/CVs/abc.docx
noktamedya.com/CVs/abc.docx
i have a class which takes to important record from db
public function getAllRec()
{
$query = "SELECT * FROM applyRecords ";
$resultDb = $this->db->query ($query);
$jobs = array ();
while ( $row = $resultDb->fetchObject () ) {
$job = new Job ();
$job->title = $row->jobTitle;
$job->url = $row->file;
$jobs [] = $job;
}
return $jobs;
}
i have here to file and jobTitle.
in admin inc. i call this function like that
$jobs3 = $jobHome->getAllRec();
and try to order with their jobTitle but have error and dont understand
foreach($jobs3 as $job)
{
$groupJobs = [$job->title][$job->url] = $job;
}
what's wrong here?
I think this is what you are trying to do:
Group job applications by title of job applying to
$groupJobs = array();
foreach($job3 as $job){
if(!isset($groupJobs[$job->title])){
$groupJobs[$job->title] = array();
}
$groupJobs[$job->title][] = $job; // add job to group
}
Instead of ordering in PHP, order in SQL, and then continue.
Instead of
"SELECT * FROM applyRecords "
try
"SELECT * FROM applyRecords ORDER BY jobtitle "
Try something like this:
$groupJobs[$job->title] = array(
$job->url => $job
);
The groupJobs Array Must be defined as Array before foreach.
And remember, $job is an object.
Just sort the records at the time of database fetch
"SELECT * FROM applyRecords ORDER BY jobTitle"
$groupJobs = [$job->title][$job->url] = $job;
This is not valid php syntax. I can't even see what are you trying to do here but I make a wild guess:
$groupJobs[] = array(
"title" => $job->title,
"urls" => array($job->url1, $job->url2)
);
About the ordering: You should add a parameter for this and let sql do to ordering:
public function getAllRec($order)
{
$query = "SELECT * FROM applyRecords ";
if ($order) $query .= " ORDER BY " . $order;
$resultDb = $this->db->query ($query);
...
My final answer is below
$groupJobs = array();
foreach($jobs3 as $job)
{
$groupJobs[$job->title][] = $job;
}
foreach($groupJobs as $key => $value){
$key . "<br />";
foreach($value as $node){
$node->url;
$node->name;
}
}
Thank you all.

Mysql query generation?

I have several different filters and search functions that I need to generate mysql queries for. I am wondering if there is a class or library I can use.
For example if they input there email with a date I need to add WHERE email='email' AND date`='date' in the middle of the sql query. But if they also enter a city then I need to add that.
I was thinking put everything I need to search by in an array and then imploding it by AND ? Does anyone have any better suggestion?
I use Zend_Db for that sort of thing. Quick example, using Zend_Db_Select:
$select = $db->select()->from("users");
if($email) {
$select->where('email = ?', $email);
}
if($date) {
$select->where('date = ?', $date);
}
// etc
// show query
// will output something like SELECT * from `users` WHERE email = 'email' AND date = 'date'
print_r($select->__toString());
// execute
$results = $db->fetchAll($select);
print_r($results);
I use array solution very often as it is most flexible solution for query conditionals
$a[] = "email = 'email'";
$a[] = "firstname LIKE '%firstname%'";
$a[] = "date BETWEEN 'date_a' AND 'date_d'";
$a[] = "id > 123";
$query = ... " WHERE " implode(' AND ', $a);
I'd go for adding all data that is given into an array like this:
$args = array(
'email' => 'test#test.com',
'date' => '2011-01-05',
'city' => 'MyTown'
);
Then just foreach through it adding the key and value to the search
$SQL = "WHERE ";
foreach($args as $key => $val) {
$SQL .= $key."='".$val."'";
//And add the AND or OR where needed
}
Common approach is to create an array that will contain different query parts and just add elements to them, depending on what you need to filter. For example:
<?php
$sql_parts = array(
'select' => array(),
'from' => array(),
'where' => array()
);
if ($filter_by_name != ''){
$sql_parts['select'][] = 'u.*';
$sql_parts['from'][] = 'users AS u';
$sql_parts['where'][] = "u.name = '".mysql_real_escape_string($filter_by_name)."'";
}
if ($filter_by_surname != ''){
$sql_parts['select'][] = 'u.*';
$sql_parts['from'][] = 'users AS u';
$sql_parts['where'][] = "u.surname = '".mysql_real_escape_string($filter_by_surname)."'";
}
//filter by data from another table
if ($filter_by_city_name != ''){
$sql_parts['select'][] = 'u.*, c.*';
$sql_parts['from'][] = 'cities AS c';
$sql_parts['from'][] = 'users AS u';
$sql_parts['where'][] = "c.cityname = '".mysql_real_escape_string($filter_by_city_name)."'";
$sql_parts['where'][] = "c.id = u.cityid";
}
$sql_parts['select'] = array_unique($sql_parts['select']);
$sql_parts['from'] = array_unique($sql_parts['from']);
$sql_parts['where'] = array_unique($sql_parts['where']);
$sql_query = "SELECT ".implode(", ", $sql_parts['select']).
"FROM ".implode(", ", $sql_parts['from']).
"WHERE ".implode(" AND ", $sql_parts['where']);
?>

Categories