I have tried several things but I can't get the MySQL query in my php code to work. Note that the query DOES WORK when I hard-code the variable $lastmsg which is an integer.
The code works in two instances:
When the page loads, the query runs, ignoring $pagination because $lastmsg is not set.
A button sends a value for lastmsg to this page, which runs the code again, this time looking at $pagination because lastmsg is set.
Again, the query DOES WORK. The proof being that it runs perfectly fine in the first instance and returns properly when the variables are hard coded. Firebugs reports that lastmsg is being sent by post.
The problem is that the query isn't receiving the value for $lastmsg (I get no values returned). I know this is because $lastmsg is sitting inside $pagination.
P.S. I am aware it needs injection protection... I'm just trying to get this to work:
if(isset($_POST['lastmsg']) &&is_numeric($_POST['lastmsg'])){
$lastmsg = $_POST['lastmsg'];
$pagination = 'AND $wpdb->posts.ID < ".$lastmsg."';
} else {
$pagination = '';
}
$pageposts = $wpdb->get_results($wpdb->prepare("
SELECT * FROM $wpdb->posts
LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)
LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
WHERE $wpdb->posts.post_status = 'publish'
AND $wpdb->posts.post_type = 'post'
AND $wpdb->posts.post_date < NOW()+INTERVAL 1 DAY
AND $wpdb->term_taxonomy.taxonomy = 'category'
AND $wpdb->term_taxonomy.term_id IN(3)
".$pagination."
ORDER BY $wpdb->posts.post_date DESC
LIMIT 10
"), OBJECT);
The following DOES NOT work
$pagination = 'AND $wpdb->posts.ID < ';
$pageposts = $wpdb->get_results($wpdb->prepare("
SELECT * FROM $wpdb->posts
LEFT JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)
LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
WHERE $wpdb->posts.post_status = 'publish'
AND $wpdb->posts.post_type = 'post'
AND $wpdb->posts.post_date < NOW()+INTERVAL 1 DAY
AND $wpdb->term_taxonomy.taxonomy = 'category'
AND $wpdb->term_taxonomy.term_id IN(3)
".$pagination."
".$lastmsg."
ORDER BY $wpdb->posts.post_date DESC
LIMIT 10
"), OBJECT);
Any solutions?
This is not the string you're looking for:
$pagination = 'AND $wpdb->posts.ID < ".$lastmsg."';
That will leave a literal AND $wpdb->posts.ID < ".$lastmsg." inside $pagination and that string won't do anything useful when you hand it to MySQL.
You want double quotes on the outside (for interpolation) and no single quotes at all:
$pagination = "AND $wpdb->posts.ID < $lastmsg";
Or, if $lastmsg is a string rather than a number:
$pagination = "AND $wpdb->posts.ID < '$lastmsg'";
That should get your first version working.
Now go forth and add all your mysql_real_escape_string calls.
PHP parser will ignore the lines quoted with single quotes('') as if they are normal strings. You can force PHP parser to parse the strings too by enclosing them inside double quotes ("").
In your case $pagination goes like this
$pagination = 'AND $wpdb->posts.ID < ".$lastmsg."';
Outer quotes are single quotes so it will be ignored by PHP and $wpdb->posts.ID and even $lastmsg will be considered as simple strings, they wont get their PHP values.
just change your string to
$pagination = "AND $wpdb->posts.ID < '$lastmsg'";
again if $lastmsg is numeric you don't need inner quotes
Related
Good evening all.
Is there one that will give me an example of how to make such a script here:
I try to make a while combining 2 different tables in my database to get correct mysqli_num_rows.
Like this:
$Querypris ("SELECT * FROM" wpd2_posts` where post_status = 'wc-failed' and select * From `wpd2_postmeta` where meta_key = '_ order_total' and meta_value> 300 ')
$Num_rowspris = mysqli_num_rows ($ query price);
So I want to get mysqli_num_rows from all those who are post_status = 'wc-completed' but also meta_value> 300
Hope you understand what I mean :)
Well, your php code will not work like this. At least variable names must be consistent.
You should use JOIN clause in your sql statement. I suppose, there is a column like "post_id" in both tables.
$query_price = "SELECT * FROM wpd2_posts JOIN wpd2_postmeta USING (post_id) WHERE post_status = 'wc-completed' AND meta_key = '_order_total' AND meta_value > 300";
$result = mysqli_query($connection, $query_price);
$number_of_rows = mysqli_num_rows($result);
UPDATE:
If names of the columns, referring to ID of the post, are different in those tables, for example "ID" in "wpd2_posts" and "post_id" in "wpd2_postmeta", then you should use a following query:
SELECT * FROM wpd2_posts p JOIN wpd2_postmeta pm
ON p.ID = pm.post_id
WHERE p.post_status = 'wc-completed'
AND pm.meta_key = '_order_total' AND pm.meta_value > 300
UPDATE: removed space from '_ order_total'. changed to '_order_total'
SELECT * FROM wpd2_posts,wpd2_postmeta where wpd2_posts.post_status = wc-completed and wpd2_postmeta.meta_key = _ order_total and wpd2_postmeta.meta_value > 300 and wpd2_posts.fk=wpd2_postmeta.fk
this thing might not work for not having foreign key
SELECT * FROM wpd2_posts CROSS JOIN wpd2_postmeta where wpd2_posts.post_status = wc-completed and wpd2_postmeta.meta_key = _ order_total and wpd2_postmeta.meta_value > 300
Its better to use foreign keys.
hope this will help
If your site is WordPress then use this:
global $wpdb;
$sql="SELECT * FROM wpd2_posts pt INNER JOIN wpd2_postmeta pmt ON pmt.post_id = pt.ID WHERE pt.post_status = 'wc-completed' AND pmt.meta_key = '_order_total' AND pmt.meta_value>300";
$results = $wpdb->get_results($sql, ARRAY_A );
$num_rowspris = count($results);
// OR ---------
$results = $wpdb->query($sql);
$num_rowspris = $results->num_rows;
else :
Note: $conn is your DB connection
$results = mysqli_query($conn, $sql);
$num_rowspris = mysqli_num_rows($results);
I have 2 almost identical queries. One checks for posts before a certain time stamp another one checks for pts after a certain time stamps. However the one that is used for the future posts has all the necessary values and is used to create a link to those events where is the one for the previous posts doesn't for some reason :(
Here is the code:
$previous = $wpdb->get_row("SELECT MONTH(post_date) AS month, YEAR(post_date) AS year
FROM $wpdb->posts
LEFT OUTER JOIN $wpdb->term_relationships ON($wpdb->posts.ID = $wpdb->term_relationships.object_id)
LEFT OUTER JOIN $wpdb->term_taxonomy ON($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
LEFT OUTER JOIN $wpdb->terms ON($wpdb->term_taxonomy.term_id =$wpdb->terms.term_id )
WHERE ( $wpdb->posts.post_date < '$thisyear-$thismonth-01'
AND $wpdb->terms.slug = 'events'
AND $wpdb->posts.post_status = 'publish'
AND $wpdb->posts.post_type = 'post')
ORDER BY post_date DESC
LIMIT 1");
$next = $wpdb->get_row("SELECT MONTH(post_date) AS month, YEAR(post_date) AS year
FROM $wpdb->posts
LEFT OUTER JOIN $wpdb->term_relationships ON($wpdb->posts.ID = $wpdb->term_relationships.object_id)
LEFT OUTER JOIN $wpdb->term_taxonomy ON($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
LEFT OUTER JOIN $wpdb->terms ON($wpdb->term_taxonomy.term_id =$wpdb->terms.term_id )
WHERE ( $wpdb->posts.post_date > '$thisyear-$thismonth-{$last_day} 23:59:59'
AND $wpdb->terms.slug = 'events'
AND $wpdb->posts.post_status = 'publish'
AND $wpdb->posts.post_type = 'post')
ORDER BY post_date ASC
LIMIT 1");
Here is the code where those values are used:
<tr>';
if ( $previous ) {
$calendar_output .= "\n\t\t".'<td colspan="3" id="prev">« ' . $wp_locale->get_month_abbrev($wp_locale->get_month($previous->month)) . '</td>';
} else {
$calendar_output .= "\n\t\t".'<td colspan="3" id="prev" class="pad"> </td>';
}
$calendar_output .= "\n\t\t".'<td class="pad"> </td>';
if ( $next ) {
$calendar_output .= "\n\t\t".'<td colspan="3" id="next">' . $wp_locale->get_month_abbrev($wp_locale->get_month($next->month)) . ' »</td>';
} else {
$calendar_output .= "\n\t\t".'<td colspan="3" id="next" class="pad"> </td>';
}
$calendar_output .= '
</tr>
SUMMARY :
WHAT'S WRONG?!
Hard to tell from what is given, but my guess is that 'date' field type is strictly date, whereas in second query you are trying to use it as some kind of datetime. Like it can be yyyy-mm-dd but not yyyy-mm-dd hh:mm:ss.
Another guess is that is something not SQL-specific, like $last_day is not set or string format is wrong etc.
Anyway, please consider two advices in future:
Use MWE (Minimum Working Example). I am almost sure that if you cut out all them JOINs and other stuff the error will still persist. So to say, just try to reduce it to SELECT * FROM table WHERE ( $wpdb->posts.post_date > '$thisyear-$thismonth-{$last_day} 23:59:59'.
Second part of your code is, sorry to say this, of absolutely no use to tell what is wrong. It is obvious that if query returns no data, using this absent data will result in error. Would be much better to include raw result of first query and result/error of second one.
I have this custom query I need to do that will check against both post_metadata values and taxonomy terms. I'm using code that I modified from Wordpress's codex, but it is returning zero results consistently. Is there a mistake I've made? (UPDATED: shows where it is being loaded into a variable first)
global $wpdb;
$querystr = "
SELECT * FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta ON($wpdb->posts.ID = $wpdb->postmeta.post_id)
LEFT JOIN $wpdb->term_relationships ON($wpdb->posts.ID = $wpdb->term_relationships.object_id)
LEFT JOIN $wpdb->term_taxonomy ON($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
LEFT JOIN $wpdb->terms ON($wpdb->term_taxonomy.term_id = $wpdb->terms.term_id)
WHERE $wpdb->terms.name = '" . $service . "'
AND $wpdb->term_taxonomy.taxonomy = 'Services'
AND $wpdb->postmeta.meta_value = '" . $county . "'
AND $wpdb->posts.post_status = 'publish'
AND $wpdb->posts.post_type = 'post'
AND $wpdb->postmeta.meta_key = 'order'
ORDER BY $wpdb->postmeta.meta_value ASC";
$pageposts = $wpdb->get_results($querystr, OBJECT);
I would suggest logging the actual string that is executed (save this select to a variable and log the variable, then pass the variable to the wpdb query). Once you have the sql, you can more easily troubleshoot it (or post it here for further assistance).
In "category.php" file I need to order my posts in this strange way:
First all the posts where author is different than "admin" (in alphabetical order by title)
Than all the post by "admin" (in the same alphabetical order)
Here is the standard code I use to do my query:
<?php global
$wp_query;
query_posts(
array_merge(
array('orderby' => 'title', 'order' => 'ASC'),
$wp_query->query
)
);
?>
Any idea about how to accomplish it without nesting two queries?
Thanks in advance!
EDIT: Following is some code that was tried, as suggested by Sepster in a previous version of his answer. But at the moment this code starts showing all the posts from 'admin' (instead of the others) until the posts with author different than 'admin' come. At that point it breaks the results and jump to the next page of results.
<?php
global $wp_query;
query_posts(
array_merge(
array('orderby' => 'title', 'order' => 'ASC'),
$wp_query->query
)
);
$adminPosts = false;
for ($i=1; $i<=2; $i++) {
while ( $wp_query->have_posts() ) {
$wp_query->the_post();
$author = get_the_author();
if ($author == 'admin' && $adminPosts == false) break;
if ($author != 'admin' && $adminPosts == true) break;
// ALL MY STUFF
} // end while
rewind_posts();
$adminPosts=true;
} // end FOR
?>
Update:
I've finally come up with a somewhat workable solution for this, but it's fair to say this really is an excercise in academics; Yes, it's do-able without executing a second loop, but really, it's pretty convoluted.
The solution is, in summary
Develop a custom SQL statement that will return the rows in the order required.
This is because in SQL, the only way to get the results in the order you need is by doing a UNION of your two subsets. To my knowledge there's no way of doing that using the "normal" WP query operations.
Execute this query, and loop over its results rather than a standard "the loop".
This is because we're getting back a recordset, rather than a WP_Query object.
Set the "Blog pages show at most X posts" setting to 1.
(on /wp-admin/options-reading.php)
A common complaint is pagination breaking when using custom queries (incidentally, the query_posts() method you're using is susceptible to this issue).
There are numerous turorials on how to do this properly, eg:
https://codex.wordpress.org/Making_Custom_Queries_using_Offset_and_Pagination
https://codex.wordpress.org/Pagination#Troubleshooting_Broken_Pagination
The first of those recommends the implementation of "Offset and Manual Pagination".
The closest I've found to an implementation of this in conjunction with a custom SQL statement is this https://wordpress.stackexchange.com/a/28717. I've borrowed heavily from this answer (and so I recommend you go over and give it an up-vote!).
However, this technique (among other more "standard" custom query approaches) suffers from a known behaviour where WP produces a 404 on the final page (if I understand correctly, because WP is still using its own query and associated max-page=posts-per-page/posts calculations to map between the page number in the URL and the delivered content).
Refer http://wordpress.org/support/topic/explanation-and-workaround-for-error-404-on-category-pagination?replies=14 for details about this issue, and a proposed solution (which unfortunately won't work for our custom SQL approach).
A known "work-around" for this issue is to reduce the number of posts-per-page to 1, as per eg http://wordpress.org/support/topic/custom-post-type-pagination-404-on-last-page
So, assuming you're happy with a global setting of 1 posts-per-page (remember you'd need to override this manually in your custom queries), here's the code:
functions.php:
...
function get_users_posts_last($userDisplayName = 'Admin', $categoryName = '') {
global $wpdb, $paged, $max_num_pages;
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$post_per_page = 5;
$offset = ($paged - 1)*$post_per_page;
$sql = "
SELECT SQL_CALC_FOUND_ROWS q.* FROM
(
(
SELECT
p.*
FROM
{$wpdb->posts} p
INNER JOIN {$wpdb->users} u ON p.post_author = u.ID
LEFT JOIN {$wpdb->term_relationships} tr ON p.ID = tr.object_id
LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
LEFT JOIN {$wpdb->terms} t ON tt.term_id = t.term_id
WHERE
tt.taxonomy = 'category'
AND p.post_status = 'publish'
AND p.post_type = 'post'
AND u.display_name != '{$userDisplayName}'
" . ( $categoryName != '' ? "AND t.name = '{$categoryName}'" : "" ) . "
ORDER BY
p.post_title ASC
)
UNION
(
SELECT
p.*
FROM
{$wpdb->posts} p
INNER JOIN {$wpdb->users} u ON p.post_author = u.ID
LEFT JOIN {$wpdb->term_relationships} tr ON p.ID = tr.object_id
LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
LEFT JOIN {$wpdb->terms} t ON tt.term_id = t.term_id
WHERE
tt.taxonomy = 'category'
AND p.post_status = 'publish'
AND p.post_type = 'post'
AND u.display_name = '{$userDisplayName}'
" . ( $categoryName != '' ? "AND t.name = '{$categoryName}'" : "" ) . "
ORDER BY
p.post_title ASC
)
) q
LIMIT {$offset}, {$post_per_page};
";
$sql_result = $wpdb->get_results( $sql, OBJECT);
$sql_posts_total = $wpdb->get_var( "SELECT FOUND_ROWS();" );
$max_num_pages = ceil($sql_posts_total / $post_per_page);
return $sql_result;
}
...
category.php:
...
$postList = get_users_posts_last('admin'); // Note you can also pass a category name if necessary
if($postList) {
global $post;
foreach( $postList as $key=>$post ) {
setup_postdata($post);
// Render the post here
?>
<header class='entry-header'><h1 class='entry-title'><?php the_title(); ?></h1></header>
<div class='entry-content'><?php the_content(); ?></div>
<?php
}
// Render pagination here
?>
<div class="navigation">
<div class="previous panel"><?php previous_posts_link('« Previous page',$max_num_pages) ?></div>
<div class="next panel"><?php next_posts_link('Next page »',$max_num_pages) ?></div>
</div>
<?php
}
...
Or, just set up two separate queries ;-)
SELECT
SQL_CALC_FOUND_ROWS posts.*,
CASE
WHEN postmeta.meta_value REGEXP '$regex'
THEN 1
ELSE 0
END AS keyword_in_title,
MATCH ( posts.post_content )
AGAINST ( '".addslashes( $s )."' ) AS mysql_score
FROM
$wpdb->posts as posts,
$wpdb->postmeta as postmeta
WHERE
posts.post_date_gmt <= now()
AND postmeta.post_id = posts.ID
AND postmeta.meta_key='_headspace_page_title'
AND posts.post_password = ''
AND posts.post_status = 'publish'
AND posts.post_type != 'attachment'
AND ( postmeta.meta_value REGEXP '$regex'
OR posts.post_content REGEXP '$regex')
GROUP BY
posts.ID
ORDER BY
charindex($s, 'keyword_in_title') DESC
LIMIT
$offset,
$limit
As to the order issue (Apart from the escaping issue #Gumbo pointed out in the comment), CHARINDEX is not a valid mysql string function. The LOCATE function looks to be identical (at least from a cursory glance between the docs on SQLServer and MySQL)...
$s = mysql_real_escape_string($s);
$order = 'ORDER BY LOCATE(\''.$s.'\', `keyword_in_title`) DESC';
I'm assuming that the code above does not work and hence you're asking a question.
Try adding charindex($s, 'keyword_in_title') AS cOrder in your SELECT clause and then ORDER BY cOrder DESC
Good luck!