how to explode key value pairs and use them in query - php

in my laravel project i have a db field in which user can store the parameters that to be considered for sorting and also their orders. That is, the data table "config" contains a column value like this
status-desc,priority-asc,..etc
In here, when i write the query i need to use these values as the order by pairs.
ORDER BY status desc, priority asc
I can hard code this in the query code like the above because the sorting columns can be different based on the users entry.
i already exploded two criteria separately like this
$params = explode(',', $sort_param->config_value);
so that i got $params[0] = status-desc and $params[1] = priority-asc ...
But how can i again explode these and fetch and use them in the query for order by??
what i did so far is:
$countt = count($params);
for($prm=0;$prm<$countt;$prm++){
list($k, $v) = explode('-', $params[$prm]);
}
echo $k.' '.$v;
The echo $k and $v displays priority asc

Try
$tab = 'status-desc,priority-asc,value,string,demo';
$params = explode(',',$tab);
foreach($params as $v){
$tab2[] = explode('-',$v);
}
$newTab = array_merge($params,$tab2);
print_r($newTab);

Try with this simple code
$tab = 'status-desc,priority-asc,value,string,demo';
list($statut,$priority,$value,$demo) = explode(',',$tab);
echo $statut ;

Related

Implode ids within a while loop and add commas between

I'm trying to display some sub-content so I need to get the child id's of their parent.
This is how I wanted to do it:
$ids = "SELECT * FROM `web_categories` WHERE parent_id = 14 AND published = 1";
$idscon = $conn->query($ids);
while ($ids = $idscon->fetch_array()){
$idss .= $ids['id'];
}
$project1 = "SELECT * FROM `web_content` WHERE catid in ('$idss') AND state = 1";
$projectcon1 = $conn->query($project1);
$projectcr1 = array();
while ($projectcr1[] = $projectcon1->fetch_array());
I tried imploding $idss like this:
$implode = implode(',', $idss);
But this gives me Invalid arguments passed. What am I doing wrong?
You are doing wrong in the first while loop.
Here it is, $idss .= $ids['id'];, You are doing wrong this. You are storing value in a variable as string, but when you try to implode this... It throws an error!!! Cause implode() use to make array into string. So follow the below steps.
Change $idss .= $ids['id']; to $idss[] = $ids['id']; and instead of implode() use the join().
Create an array names $idss, and push or insert the ids into that array. Then implode/join that IDs.
$idss = array();
while ($ids = $idscon->fetch_array()){
$idss[] = $ids['id'];
}
$implode = implode(',', $idss);
Now you can use this $implode variable in the next query.
You just need to store all IDs in an array, something like $yourIDs[] = $ids['id']; inside your first while loop.
With $idss .= $ids['id']; you can't use implode() because result of this action should be something like "1234" without any single comma.
You just need to use like that:
<?php
$yourIDs = array();
while ($ids = $idscon->fetch_array()){
$yourIDs[] = $ids['id']; // this will save all IDs into $yourIDs array.
}
$idss = implode(',',$yourIDs); // result of this should be 1,2,3,4 etc.
?>
I think you could most likely do that in one query
SELECT * FROM `web_content` WHERE `catid` in (
SELECT `id` FROM `web_categories` WHERE `parent_id` = 14 AND `published` = 1
) AND `state` = 1
The original code was, in effect, doing exactly this but in two stages - sub-queries can be slow sometimes but it does depend on the size of the db and the number of expected results. It is true that joins can be and generally are more efficient than dependant subqueries so perhaps that is another option to explore. As mysql executes the query plan from the outside to the inside rather than the intuitive inside to outside subqueries can cause the server to crawl - it really depends on the complexity of the subquery and the amount of data that has to be processed.

Order after executed?

Im trying to do a PHP script where it order users based on a point system. Problem is that the points is calculated after I execute the users. Like this:
$getScore = $db->prepare("SELECT * FROM `users`");
$getScore->execute();
$results = $getScore->fetchAll();
foreach($results as $row):
$likes = $get->likes("user", $row["id"]);
$subscribers = $get->subscribers("user", $row["id"]);
$score = $get->score($likes, $subscribers, $row["date"]);
echo $row["username"];
endforeach;
Without having another execution how do I order the results? I want the user with highest value on $score to be shown first. I've tried alot of things but without succession.
Thanks in advance!
You can implement this different ways.
If you have already loaded all the data from the databse you can order them using PHP.
Custom sorting can be done using usort.
PHP.net - usort documentation
Maybe you could use something like this:
$users = array();
// Load all the users and calculate scores
foreach($results as $row):
$users[$row["username"]] = $get->score($likes, $subscribers, $row["date"]);
endforeach;
// Sort users based on score
sort($users);
// Output users, sorted by score
foreach($score as $key => $row):
echo $key, " score:", $score;
endforeach;
If you would like to use a more complex data structure, all you have to do is implement the special comparision to ensure ordering by score with usort.
If you store the points in the database, then you could use a special query including an ORDER BY clause, this way returning the users already ordered.
I think using the DBMS to order the users would result in a more scalable solution. If you have really high number of users, it is not going to perform well to sort all the users each page load.
First, sorry for suggesting another execution flow. Next, this is my solution:
$getScore = $db->prepare("SELECT * FROM `users`;");
$getScore->execute();
$results = $getScore->fetchAll();
// Result is something like [rownum][colomname]
array_walk_recursive($results, function($item, $key) {
$id = $item["id"];
$date = $item["date"];
$arr = array();
$arr['likes'] = $get->likes("user", $id);
$arr['subscribers'] = $get->subscribers("user", $id);
$arr["score"] = $get->score($arr["likes"],
$arr["subscribers"],
$date);
$item = array_merge($item, $arr);
});
In this code you get the results from your database. Next you calculate things like the score and you add this to the array.
To sort this array on the score you can use the PHP multisort function (http://php.net/manual/en/function.array-multisort.php):
foreach ($results as $key => $row) {
$score[$key] = $row["score"];
}
array_multisort($score, SORT_DESC, $results);
When you're looping your loop to print the data for example you can do this:
foreach($results as $row) {
$likes = $row["likes"];
$subscribers = $row["subscribers"];
$score = $row["score"];
echo("your stuff over here");
}
Good luck!

Can I set multiple Codeigniter Where criteria from an array?

I am trying to get data from a database that meets multiple criteria of an array.
The array is something like this:
Array ([21] => 1,[23] => 0,[19] => 1);
With the key being a Question ID and the values being either yes or no.
I need to find the movie where the value for question_id = 21 is 1, value for question_id = 23 is 0 and value for question_id = 19 is 1. The way I have them stored is like this:
So my first thought was get the data for each and then put them in a bigger array. If the movie shows up the same amount of times as the number of elements in the array, then I consider it a good match. But this seems inefficient. I would rather just find the movies that match the criteria.
Since there are movie_id records with the same value, is there a way to write something like this?:
foreach($array as $key=>$value){
$i++;
$this->db->where('question_id', $key);
$this->db->where('value', $value);
}
$this->db->from('movies_values');
$query = $this->db->get();
$res = $query->result();
array_push($main,$res);
The thought behind this is to create a loop of all the WHEREs. And then run the query using those where values. This doesn't seem to work, is there something else I can do?
How about using WHERE IN (array())?
From the CI User Guide:
$names = array('Frank', 'Todd', 'James');
$this->db->where_in('username', $names);
// Produces: WHERE username IN ('Frank', 'Todd', 'James')
Use the where_in method for lists:
$this->db->where_in('value', $array);
Try doing it like this.
$where = WHERE 1
foreach($array as $key=>$value){
$where .= " AND(question_id = $key AND value = $value)";
}
$this->db->where($where);
PS. What is the $i++ doing in your loop exactly?
I think this is the right way to go, you should take care to use "or" instead to use full "ands" that way would not return any row due to a logic problem (I mean question_id = 1 and value = 1 and question_id = 2 and value = 0 we're being inconsistent due to telling that we want question_id = 1 and question_id = 2 won't match nothing!, the same applies to "values").
$array = array(21 => 1,23 => 0,19 => 1);
$where = array();
foreach($array as $key => $value) {
$where[] = "(question_id=$key and value=$value)";
}
var_dump($where);
foreach ($where as $value) {
$this->db->or_where($value);
}
$q = $this->db->get('movies_values')->result();
var_dump($q);
echo $this->db->last_query();exit;
This can be done easily without loop:
$filter = array(21 => 1,23 => 0,19 => 1);
$values = implode(',',array_unique(array_values($filter))); // results into 0,1...
$keys = implode(',',array_unique(array_keys($filter))); // results into 19,21,23...
$result = $this->db
->query("select * from movies_values
where
question_id in(".$keys.")
and value in(".$values.")")
->result();
Happy coding ---> :)

php & mysql - loop through columns of a single row and passing values into array

I have a mysql table with columns id, f1, f2, f3, ..., f20 where id is productID and f1,...f20 are product features. Depending on each product, some might have all, none or only some columns filled.
Each column holds a delimited string like a#b#c#d where a,b,c,d are values in different languages (a=english, b=french etc)
I need to select a row by it's id, explode each column's value (f1,f2...) with '#' in order to get the language part I need and then pass the values to an array in order to use in my product spec page.
How do I loop through the fetched row (i'm using $row = my_fetch_array) and put the exploded value into a one dimension array like $specs=('green', 'M', '100', 'kids'...) etc?
PS:I know, is complicated but I cant come up with a better idea right now.
Try this:
$result = mysql_query("...");
while ($row = mysql_fetch_array($result, MYSQL_NUM)) {
$arr = array();
foreach ($row as $k=>$v)
{
$features = explode("#", $v);
$value = $features[1]; // get the specific language feature
$arr[] = $value;
}
$specs = join(", " , $arr);
}
Not sure this is the best way togo but you could define an array with your langs, then access the result by lang
<?php
$langs=array('eng'=>0,'fr'=>1,'ger'=>2,'geek'=>3);
while ($row=mysql_fetch_assoc($result)) {
$specs=explode('#',$row['f1']);
$other=explode('#',$row['f2']);
...
}
//Get lang from cookie that you could set elsewhere
$lang=(isset($_COOKIE['lang']))?$_COOKIE['lang']:'eng';
echo $specs[$langs[$lang]];
?>
My solution for how I understand you question:
// Make a MySQL Connection
$sQuery = "SELECT f1,f2,... FROM table WHERE id = ...";
$oResult = mysql_query($sQuery) or die(mysql_error());
//Fetch assoc to use the column names.
$aRow = mysql_fetch_assoc($oResult);
//Prepare the product properties array
$aProductProperties = array("English"=>array(),"French"=>array(),"Dutch"=>array());
//Loop over all the columns in the row
foreach($aRow as $sColName=>$sColVal){
//Explde the column value
$aExplodedCol = explode("#",$sColVal);
//The code below could be nicer when turned into a looped that looped over every language,
//But that would make the code less readable
$aProductProperties['English'][$sColName] = $aExplodedCol[0];
$aProductProperties['French'][$sColName] = $aExplodedCol[1];
$aProductProperties['Dutch'][$sColName] = $aExplodedCol[2];
}
//Done, you should now have an array with all the product properties in every language

Build SQL Select a better way ? (Oracle)

i have the following code part in one of my classes:
$l = new Location();
$result = $l->getLocIdsbyCity($city); // returns csv
$ids = explode(',', $result);
$where = 'LOC_ID = ' . $ids[0];
unset($ids[0]);
foreach ($ids as $id) {
$where .= ' OR LOC_ID = ' . $id;
}
$select->where($where);
Is there an more "elegant" way to build the select stmt? I need all records with one of the provided ids..
Assuming your csv is injection safe (contains trusted values and no user-provided input):
$l = new Location();
$result = $l->getLocIdsbyCity($city); // returns csv
$where = "LOC_ID IN ($result)";
$select->where($where);
If it's not, you should explode it, mysql_real_escape_string each value and implode back.
You can use the in operator to form a condition like:
where LOC_ID in (1,2,3,4,5)
If you are sure that $result can't contain anything harmful, you should be able to use it directly without having to split it and loop.

Categories