Pass IDs to pre_get_posts query in function - php

I am trying to pass the post ids to the function's query->set and function will return the posts.
add_action( 'pre_get_posts', 'query_booked_posts' );
function query_booked_posts( $query ) {
if ( $condition ) { //the condition
if ( is_home() && $query->is_main_query() )
$results = $wpdb->get_col($wpdb->prepare( "SELECT booked_id FROM $wpdb->userbooking WHERE userid = %d",$current_user_id));
foreach($results as $result){
$results_separated = $result.',';
}
$query->set ('post__in', array($results_separated)); // pass results (post ids) to post__in
return $query;
}
}
After this, the function returns nothing.
If I do $query->set ('post__in', array(45,121));, the query will return the posts of id 45 and id 121, so the query works fine.
But I want to make $results_separated pass the post ids like 45,121,132 to the query, and then $query->set ('post__in', array($results_separated)); will work correctly.
How can I make this happen?
pre_get_posts reference

I guess you have actually a PHP problem. When you do array($results_separated) you're basically creating an array from a string that looks like this: "12,114,56,". By doing that, PHP is creating an array like this:
array(
0 => "12,114,56,"
)
And obviously WordPress cannot find any posts with such ID! What you want is actually an array like this:
array(
0 => "12",
1 => "114",
2 => "56"
)
And actually that's what get_col() returns, so you just need to pass $results to set() function:
$query->set ( 'post__in', $results );
EDIT: Actually I realised that your problem is when you call $wpdb->get_col(...), because it's interfering with the $query you will execute later on... Those variables are using some other global variables that probably get overriden, and that's why you're not getting any results...

Except the extra array() over $results_separated, in my case I had to apply
if (!$query->is_main_query()) {
return $query;
}
at the top of my function (found it in, otherwise, queries inside would be executed for several times and not properly.
Comments in the answer helped me to figure this out.

Related

Codeigniter 4 Search Pagination not counting and returning page

I'm working on a simple search project where I'm returning the results. The search function appears to work however, the total and page return the wrong values. The total field returns the total number of rows inside the data, not the total number of results from the search and the page is always {}.
Here's the model->function I've created:
public function search($string)
{
$results = $this->select('*')->orLike('title', $string)->orLike('excerpt', $string);
if ( empty( $results ) )
{
return [];
} else
{
$data = [
'results' => $results->paginate(2),
'total' => $results->countAllResults(),
'page' => $this->pager,
];
return $data;
}
}
What's puzzling is if I place the total field above the results value the count works, but then the result fields returns everything in the database at paginate(2).
Ok, I managed to solve this query by adding two separate queries to the database. The processing cost appears to be minimal and it should be alright when caching the responses. As it turns out you can chain queries but only in a particular order and if you use grouping (see ->groupStart() )
$results = $this->select('title, image, categories, id, excerpt')->groupStart()->like('title', $search)->orLike('excerpt', $search)->groupEnd()->where('status','live')->paginate(2);
$total = $this->select('title, image, categories, id, excerpt')->groupStart()->like('title', $search)->orLike('excerpt', $search)->groupEnd()->where('status','live')->countAllResults();
Some may argue the inefficiency of the two queries, but this works for my use case :) Hope this helps anyone else stuck on a similar problem.

Add multiple value to a query variable in WordPress

I am using the below code in functions.php to add custom query variables to my WordPress project.
<?php
function add_custom_query_var( $vars ){
$vars[] = "brand";
return $vars;
}
add_filter( 'query_vars', 'add_custom_query_var' );
?>
And then on the content page I am using:
<?php echo $currentbrand = get_query_var('brand'); ?>
So now I can pass a URL like:
http://myexamplesite.com/store/?brand=nike
and get nike in result.
How can I pass multiple values for a brand. So I would like to have 3 values for brand say, nike, adidas and woodland.
I have tried the following and none of them works:
http://myexamplesite.com/store/?brand=nike&brand=adidas&brand=woodland
It just returns the last brand, in this case woodland.
http://myexamplesite.com/store/?brand=nike+adidas+woodland
This returns all three with spaces. I kind of think this is not the correct solution. So may be there is a correct way to pass multiple values for a query variable and retrieve them in an array may be so that a loop can be run.
Usually you would pass the parameter like ?brand[]=unresponsibleCompany1&brand[]=otherBrandThatDoesNotCareMuch&brand[]=bunchOfCriminals .
In your WordPress PHP code, then get_query_var( 'brand' ) will return you an Array.
Everything else sounds like a relatively cheap but costy workaround.
You will need to pass query parameters in this way;
brand1=nike&brand2=adidas&brand3=woodland
So, different key for each brand
On the page, recieving values
$params = $_GET;
$brands = array();
foreach($params as $k=>$v) {
if(substr($k,0,5)=="brand") {
$brands[] = $v;
}
}
Alternatively
Using your 2nd method
http://myexamplesite.com/store/?brand=nike+adidas+woodland
$brands = explode(" ", $_GET['brand']);
Alternative method looks easier 🙂

Assigning a value to a variable?

I'm working on a PHP project and would love to get some help on variables.
I have a function that looks like this:
function custom_get_tour_nearest_booking_dates( $tour_id, $limit = 2, $exclude_booked_tickets = false ) {
$result = array();
if ( $tour_id < 1 ) {
return $result;
}
The database holds a set of products, each of these with a unique ID made up by numeric values, like 1233,2355,6532 and so on.
If I want to display the characteristics of one of these products, how do I link the ID to the variable $tour_id?
Somewhere you call that method: custom_get_tour_nearest_booking_dates(4);
Like the example above, 4 is the tour_id. Besides that, your method is kinda useless.

Calling a PHP function from within MySQL

I'm not even sure if this is possible, but essentially I want to have a function stored within my MySQL database, so here I have my database
Database->pages:
[id] [name ] [content ] [enabled] [main] [parent]
[6 ] [login] [login();] [1 ] [0 ] [5 ]
Now I'll have the set returned
public function viewPage() {
global $db;
$query = <<<SQL
SELECT content
FROM pages
WHERE id = :getid
SQL;
$resource = $db->sitedb->prepare( $query );
$resource->execute( array (
':getid' => $_GET['id'],
));
foreach($resource as $row){
echo $row['content'];
}
}
Last but not least I have my viewPage.php page that has
$static->viewPage();
So when I go to viewPage.php?id=6 I want it to pull the data and since content is login(); I want it to call the login(); function which would be translated into an include file. Is this even possible?
You can use variable functions to achieve this effect. We would need to verify that the function is_callable beforehand.
Let's say we get a row back with the field name set to login. You can do this:
if( is_callable($row['name']) )
$row['name']();
This will call the function login. You can also pass parameters if you want, as you would any other function.

Best way to ensure a PHP variable is an array

I have a javascript client passing a parameter to a server function (I'm using ExtJS Direct). Sometimes the client sends a single object, sometimes it sends an array of objects.
Currently I'm using this EnsureArray function to ensure the parameter is an array, and then I do foreach:
// Wraps a non array variable with an array.
function EnsureArray( &$aVar )
{
if ( !is_array( $aVar ) )
$var = array( $aVar );
}
function Destroy( $aRecords )
{
// $aRecords might be a single object or an array of objects. Ensure it's wrapped as an array.
$this->EnsureArray( $aRecords );
foreach ( $aRecords as $aRecord )
{
sql( "UPDATE Groups SET deleted = true WHERE id = $aRecord->id LIMIT 1" );
}
return array(
'success' => true,
);
}
Is there a trick, neater way, one line that can do the same?
Edit: Since posting this question, I've found that ExtJS has an option to send all records wrapped in array.
You could try the following, instead of the function:
$aRecords = is_array($aRecords) ? $aRecords : array($aRecords);
That's probably the best way tbh, if you're not going to enforce that you're always being sent an array.
I would make the function Destroy require arrays as its parameter:
function Destroy(array $aRecords) { ... }
The client should then also always send arrays. If, for whatever reason, that is not possible, the code that is receiving the (non-)array from the client and is passing it on to Destroy() needs to be responsible for passing it along as an array, because it's the interface between the (non-compliant) client and the standardized function.
There's probably going to be one endpoint for each possible action the client can call, so you don't even need to figure out whether the data is an array or not, you simply know. I.e.:
// someaction.php
include 'destroy.php';
$data = json_decode($_POST['data']);
Destroy($data);
but:
// anotheraction.php
include 'destroy.php';
$data = json_decode($_POST['data']);
Destroy(array($data));
If the client erratically sends different formats to the same action, fix the client.
Simply typecast the variable to an array:
function Destroy( $aRecords )
{
foreach ( (array)$aRecords as $aRecord )
{
sql( "UPDATE Groups SET deleted = true WHERE id = $aRecord->id LIMIT 1" );
}
return array(
'success' => true,
);
}
See http://php.net/manual/en/language.types.type-juggling.php

Categories