Ok, I assume that the title is not the best title, but let me explain my problem: I'm creating a website that needs to show posts of people (anyway), and I have to show their gravatar's profile picture, so this what I did:
<?php
function get_gravatar( $email, $s = 80, $d = 'mm', $r = 'g', $img = false, $atts = array() ) {
$url = 'https://www.gravatar.com/avatar/';
$url .= md5( strtolower( trim( $email ) ) );
$url .= "?s=$s&d=$d&r=$r";
if ( $img ) {
$url = '<img src="' . $url . '"';
foreach ( $atts as $key => $val )
$url .= ' ' . $key . '="' . $val . '"';
$url .= ' />';
}
return $url;
}
require("db.php");
$sql = "SELECT * FROM posts ORDER BY date DESC";
foreach ($db->query($sql) as $row) {
// var_dump($row);
$user = $row['user_id'];
$sql_user = "SELECT email FROM users WHERE id = $user";
foreach ($db->$sql_user as $row_user) {
var_dump($row_user);
echo "<img src=\"".get_gravatar($row_user['email'])."\"/>";
}
echo "<h2>".$row['title']."</h2><br/>";
echo "<p>".$row['content']."</p><br/>";
}
But, it doesn't work (well, it works, but it doesn't shows me the profile picture of the user, only the post).
So, I think the problem is that I can't call 2 times the variable $db at the same time, but I'm not sure, so that's m=why I'm asking if there is a way to fix my problem or to select 2 tables at the same time.
you can short your logic
$sql="SELECT u.email "
. "FROM posts AS p "
. "LEFT JOIN users AS u "
. "ON u.id=p.user_id "
. "ORDER BY p.date DESC";
use join
SELECT * FROM users join posts on users.id =Posts.user_id ORDER BY date DESC
you don't apply query to sql string in second foreach
foreach ($db->query($sql_user) as $row_user) {
see your second foreach you miss to put query function
foreach ($db->query($sql) as $row) {
foreach ($db->query($sql_user) as $row_user) {
You could just use JOIN
JOIN clause is used to combine rows from two or more tables, based on
a related column between them.
Related
I am new to PHP and hope someone can help me with this.
I currently use the below lines to retrieve a value from a db and to output it as an array with the item's ID and value which works as intended.
Now I would need to do the same for multiple items so my input ($tID) would be an array containing several IDs instead of just a single ID and I would need the query to do an OR search for each of these IDs.
I was thinking of using a foreach loop for this to append " OR " to each of the IDs but am not sure if this is the right way to go - I know the below is not working, just wanted to show my thoughts here.
Can someone help me with this and tell me how to best approach this ?
My current PHP:
$content = "";
$languageFrm = $_POST["languageFrm"];
$tID = $_POST["tID"];
$stmt = $conn->prepare("SELECT tID, " . $languageFrm . " FROM TranslationsMain WHERE tID = ? ORDER BY sortOrder, " . $languageFrm);
$stmt->bind_param("s", $tID);
$stmt->execute();
$result = $stmt->get_result();
while($arr = $result->fetch_assoc()){
$content[] = array("ID" => $arr["tID"], "translation" => $arr[$languageFrm]);
}
My thought:
foreach($tID as $ID){
$ID . " OR ";
}
Many thanks for any help,
Mike
There are two approaches, assuming $tID is an array of IDs
Using MySQL IN() clause
This will work also when $tID is not an array, but a single scalar value.
$tID = array_map('intval', (array)$tID); // prevent SQLInjection
if(!empty($tID)) {
$query .= ' WHERE tID IN(' . implode(',', $tId) . ')';
} else {
$query .= ' WHERE 0 = 1';
}
Using OR clause, as you suggested
A bit more complicated scenario.
$conds = array();
foreach($tID as $ID) {
$conds[] = 'tID = ' . intval($ID);
}
if(!empty($conds)) {
$query .= ' WHERE (' . implode(' OR ', $conds) . ')';
} else {
$query .= ' WHERE 0 = 1';
}
As per above conditions you can try with implode();
implode($tID,' OR ');
You can also use IN condition instead of OR something like this.
implode($tID,' , ');
I have this query:
$relatedtags = $video->tags;
$relatedtagsagain = explode(",", $relatedtags);
$query_parts = array();
foreach ($relatedtagsagain as $item) {
$query_parts[] = "'%".mysql_real_escape_string($item)."%'";}
$string = implode(",", $query_parts);
$result = $cachedb->get_results("SELECT ".DB_PREFIX."videos.title,".DB_PREFIX."videos.id as vid,".DB_PREFIX."videos.thumb, ".DB_PREFIX."videos.views,".DB_PREFIX."videos.duration,".DB_PREFIX."users.name, ".DB_PREFIX."users.id as owner FROM ".DB_PREFIX."videos LEFT JOIN ".DB_PREFIX."users ON ".DB_PREFIX."videos.user_id = ".DB_PREFIX."users.id where ".DB_PREFIX."videos.tags LIKE {$query_parts[0]} OR ".DB_PREFIX."videos.tags LIKE {$query_parts[1]} limit 0,".get_option('related-nr')." ");
How can get results for more $query_parts[] like $query_parts[2] and $query_parts[3] or from all the array? using LIKE $query_parts[] wont work.
lets go back to the basic of programming, this can be solved in many ways, like using array_mapping(see comment of scrowler), loops and many more:
sample using foreach loop:
foreach ($relatedtagsagain as $item) {
$query_parts[] = " videos.tags LIKE " . "'%". mysql_real_escape_string($item) . "%' ";
}
$parsed_query_parts = implode('OR', $query_parts);
$result = $cachedb->get_results("SELECT ".DB_PREFIX."videos.title,".DB_PREFIX."videos.id as vid,".DB_PREFIX."videos.thumb, ".DB_PREFIX."videos.views,".DB_PREFIX."videos.duration,".DB_PREFIX."users.name, ".DB_PREFIX."users.id as owner FROM ".DB_PREFIX."videos LEFT JOIN ".DB_PREFIX."users ON ".DB_PREFIX."videos.user_id = ".DB_PREFIX."users.id WHERE" . $parsed_query_parts . " limit 0,".get_option('related-nr')." ");
I'm trying to come up with the correct syntax for a SQL query using PHP (in a drupal site) but I need some guidance.
Here is my idea (in Drupal module - already designed). User makes selections from multi-page form (3 pages, radio buttons on each page, only 1 selection allowed per page). I want these to be submitted to the database and have the MySQL database return recommendations for the user depending on what their selections were, ranked in order of how many of their selections match those criteria in the resources in the database. So for example a user might select novice for exp level and founder for role and entrepreneuralship (made up word) as their topics of interest (the 3 questions in the form).
If a Resource in the database had all 3 of these set for those fields (as part of a field list), we'd want it returned near the top of the results (if more than 1 had all 3 we'd want them ordered alphabetically - ascending), followed by any resources that had at least 2 of these matching list terms (with corresponding alphabetic ranking between those second tier resources), followed by items that matched only ONE of the checked items. Items that return 0 matches shouldn't be displayed at all.
What I've done is put together a Drupal and PHP code-based concept I'm hoping for feedback on this. The code below is the function that's called after the user submits the form and are redirected to the /recommendations page. What I'd like feedback on primarily is setting the PHP variables at the top, the SQL in my $result var which is my best guess how this would work, and then a bunch of if/while statements to do the ordering and returning of data to the screen.
Any help in making this more functional code would be greatly appreciated. Thank you!
function pathfindertool_recommendations_page() {
$output = '';
$level = $_SESSION['level'];
$level = mysql_real_escape_string($level);
$role = $_SESSION['role'];
$role = $level = mysql_real_escape_string($role);
$topic = $_SESSION['topic'];
$topic = mysql_real_escape_string($topic);
$result = db_query("SELECT n.nid, n.title, n.type, fdb.body_value, fdfe.field_experience_level_value, fdfi.field_icon, fdfl.field_link_url, fdfr.field_role_value, fdft.field_topics_value FROM {node} as n INNER JOIN {field_data_body} as fdb INNER JOIN {field_data_field_experience} as fdfe INNER JOIN {field_data_field_icon} as fdfi INNER JOIN {field_data_field_link} as fdfl INNER JOIN {field_data_field_role} as fdfr INNER JOIN {field_data_field_topics} as fdft on n.nid = fdb.entity_id on n.nid = fdfe on n.nid = fdfi on n.nid= fdfl on n.nid = fdfr on n.nid = fdft WHERE n.type = :type", array(':type' => 'resource',) "AND fdfe.field_experience_level_value = :level", array(':level' => '$level',) "AND fdfr.field_role_value = :role", array(':role' => '$role',) AND fdft.field_topics_value = :topic", array(':topic' => '$topic',) ORDER BY ASC);
if($result) {
while ($row = $result->fetchAssoc()) {
// If all three match
while (($row['field_data_experience_level'] = $level) && ($row['field_data_field_role'] = '$role') && ($row['field_data_field_topics'] = $topic)) {
$title = row['title'];
$link = row['field_data_field_link'];
$body = row['body_value'];
$icon = row['field_icon'];
$output .= '<p> . $title . <br> . $icon . <br> . $body . <br> . $link';
return $output;
}
// If at least two match
while (($row['field_data_experience_level'] = $level) && ($row['field_data_field_role'] = '$role') OR ($row['field_data_field_topics'] = $topic)) {
$title = row['title'];
$link = row['field_data_field_link'];
$body = row['body_value'];
$icon = row['field_icon'];
$output .= '<p> . $title . <br> . $icon . <br> . $body . <br> . $link';
return $output;
}
while (($row['field_data_experience_level'] = $level) OR ($row['field_data_field_role'] = '$role') && ($row['field_data_field_topics'] = $topic)) {
$title = row['title'];
$link = row['field_data_field_link'];
$body = row['body_value'];
$icon = row['field_icon'];
$output .= '<p> . $title . <br> . $icon . <br> . $body . <br> . $link';
return $output;
}
// Just if only one matches
while (($row['field_data_experience_level'] = $level) OR ($row['field_data_field_role'] = '$role') OR ($row['field_data_field_topics'] = $topic)) {
$title = row['title'];
$link = row['field_data_field_link'];
$body = row['body_value'];
$icon = row['field_icon'];
$output .= '<p> . $title . <br> . $icon . <br> . $body . <br> . $link';
return $output;
}
}
}
Here's my SQL:
$result = db_query("
SELECT n.nid,
n.title,
n.type,
fdb.body_value,
fdfe.field_experience_level_value,
fdfi.field_icon,
fdfl.field_link_url,
fdfr.field_role_value,
fdft.field_topics_value
FROM {node} AS n
INNER JOIN {field_data_body} AS fdb
INNER JOIN {field_data_field_experience} AS fdfe
INNER JOIN {field_data_field_icon} AS fdfi
INNER JOIN {field_data_field_link} AS fdfl
INNER JOIN {field_data_field_role} AS fdfr
INNER JOIN {field_data_field_topics} AS fdft ON n.nid = fdb.entity_id ON n.nid = fdfe ON n.nid = fdfi ON n.nid= fdfl ON n.nid = fdfr ON n.nid = fdft
WHERE n.type = :type
",
array(':type' => 'resource',) "AND fdfe.field_experience_level_value = :level", array(':level' => '$level',) "AND fdfr.field_role_value = :role", array(':role' => '$role',) AND fdft.field_topics_value = :topic", array(':topic' => '$topic',) ORDER BY ASC);
I'm trying to determine whether a combination of topics related to a forum is unique. This is done while adding topics to a forum. The uniqueness is checked with this code and query:
$options = array(); //here's your choices
$options[] = 'blablabla';
$options[] = 'blabla';
foreach($options as $key => $value)
{
echo '<li>' . $value . '</li>';
}
$sql_unique = "SELECT Forums_ForumID, list
FROM (
SELECT Forums_ForumID, GROUP_CONCAT( Topics_TopicID ) AS list
FROM (
SELECT *
FROM Topics_crosstable
ORDER BY Topics_TopicID
)H
GROUP BY Forums_ForumID
)A
WHERE list = (
SELECT GROUP_concat( TopicID )
FROM Topics
WHERE Name IN (";
$sql_unique .= implode(",",$options);
$sql_unique .= ") ORDER BY Forums_ForumID ASC )";
$result = mysql_query($sql_unique);
//print "$result";
//echo $result;
//echo mysql_num_rows($result);
//$assoc = mysql_fetch_assoc($result);
var_dump($result);
I'm sure the query works fine when using fixed values in WHERE. With the current code I can't get any output. The vardump gives a result 'false' no matter if the combination of topics is unique or not. I've been trying for days now, so I really help you can help me out!
Thanks in advance!
You have to quote your options if they are strings.
$sql_unique .= "'". implode("','", $options) ."'";
I've got a SQL query within a foreach loop. Sometimes there can be many, and I mean a lot of queries to do, depending on several criteria, up to 78 queries potentially.
Now, I know that premature optimisation is root cause of all evil, but I don't want to see 78 queries - it's just not healthy.
Here's the code:
$crumbs = explode(",", $user['data']['depts']);
foreach ($crumbs as &$value) {
$data = $db->query("SELECT id FROM tbl_depts WHERE id = '" . $value . "'");
$crumb = $data->fetch_assoc();
$dsn = $db->query("SELECT msg, datetime FROM tbl_motd WHERE deptid = '" . $value . "'");
$motd = $dsn->fetch_assoc();
if ($motd['msg'] != "") {
<?php echo $motd['msg']; ?>
}
}
Can I make it any better?
Use IN MySQL operator to search over a set of values for id:
$ids = '"' . implode('", "',$crumbs) . '"';
$query1 = "SELECT id FROM tbl_depts WHERE id IN (" . $ids . ")";
$query2 = "SELECT msg, datetime FROM tbl_motd WHERE deptid IN (" . $ids . ")";
And so you will not need to retrieve all data you need using foreach loop, so you will have only 2 queries instead of 78.
Example: I have a table named table with 10 records which ids are: 1,2,3,4,5,6,7,8,9,10 (auto-incremented). I know I need records with ids 1,5,8. My query will be:
$sql = "SELECT * FROM `table` WHERE id in (1,5,8);";
And I don't understand why do you need to use & operator in foreach loop if you don't modify the $crubms arrays values.
I think this is want you want.
SELECT msg, datetime
FROM tbl_depts td
INNER JOIN tbl_motd tm ON td.id = tm.deptid