I'm using ACF relationship fields. I'm displaying multiple hand selected posts blocks. There is a last posts block where I want to exclude all the hand selected ones before.
How do I make an array of all ACF's to select them to exclude them from the loop?
This is my code so far (not working, it works if I only use one variable)
<?php
$excluir = get_field('bloque_6_posts');
$excluir2 = get_field('bloque_2_posts');
$excluir3 = get_field('post_destacado');
$excluir4 = get_field('posts_destacados');
$excluir5 = get_field('bloque_4_posts');
$excluirtodo = array (
$excluir,
$excluir2,
$excluir3,
$excluir4,
$excluir5
);
$paged = (get_query_var('page')) ? get_query_var('page') : 1;
$args = array(
'posts_per_page' => 9,
'paged' => $paged,
'post__not_in' => $excluirtodo
);
$the_query = new WP_Query( $args );
?>
EDIT [SOLVED]: as #disinfor pointed on the comments the solution was array_merge instead of array
Adding my answer from the comments to help future visitors
You are currently passing an array of arrays to the post__not_in. You need to use array_merge to combine the arrays into a single array.
<?php
$excluir = get_field('bloque_6_posts');
$excluir2 = get_field('bloque_2_posts');
$excluir3 = get_field('post_destacado');
$excluir4 = get_field('posts_destacados');
$excluir5 = get_field('bloque_4_posts');
// NEW CODE HERE
$excluirtodo = array_merge(
$excluir,
$excluir2,
$excluir3,
$excluir4,
$excluir5
);
// END ARRAY_MERGE
$paged = (get_query_var('page')) ? get_query_var('page') : 1;
$args = array(
'posts_per_page' => 9,
'paged' => $paged,
'post__not_in' => $excluirtodo
);
$the_query = new WP_Query( $args );
?>
It seems to me a bad method to call 5 ACF fields and then combine them into an array at the time the page is built.
For me, this method is better:
1. Create a text AСF field - hide_excluir
2. Add filter in functions.php (When editing our page, all ACF fields with exceptions will be merged into an array and saved in the field that we created before).
add_filter('acf/save_post', 'excluir_post_filter', 20);
function excluir_post_filter($post_id) {
if ( $post_id != 2 ) //Change to your page ID (or if you need use post type or page template, need modify)
return;
$excluir = get_field('bloque_6_posts');
$excluir2 = get_field('bloque_2_posts');
$excluir3 = get_field('post_destacado');
$excluir4 = get_field('posts_destacados');
$excluir5 = get_field('bloque_4_posts');
$all_excluir = array_merge(
$excluir,
$excluir2,
$excluir3,
$excluir4,
$excluir5
);
update_post_meta($post_id, 'hide_excluir', $all_excluir ); //Save array to our field
}
3. We use our field with get_post_meta
$paged = (get_query_var('page')) ? get_query_var('page') : 1;
$args = array(
'posts_per_page' => 9,
'paged' => $paged,
'post__not_in' => get_post_meta( $post->ID, 'hide_excluir', true ) //Get our field with post array
);
$the_query = new WP_Query( $args );
For testing methods, you can install the Query Monitor plugin and see the difference in the number of queries to the database.
Related
I am trying to make a custom filter for the loop grid in Elementor, and am having an issue. This code lists the items as they should be listed.
function my_query_by_filter( $query ) {
$meta_query = $query->get( 'meta_query' );
// If there is no meta query when this filter runs, it should be initialized as an empty array.
if ( ! $meta_query ) {
$meta_query = [];
}
$floorplans = '93';
//$floorplans = $_GET['floorplans'];
$meta_query[] = [
'key' => 'layout',
'value' => $floorplans,
'compare' => 'in',
];
$query->set( 'meta_query', $meta_query );
}
add_action( 'elementor/query/filter_condos', 'my_query_by_filter' );
While this code only shows correctly for the first page when using pagination.
function my_query_by_filter( $query ) {
$meta_query = $query->get( 'meta_query' );
// If there is no meta query when this filter runs, it should be initialized as an empty array.
if ( ! $meta_query ) {
$meta_query = [];
}
//$floorplans = '93';
$floorplans = $_GET['floorplans'];
$meta_query[] = [
'key' => 'layout',
'value' => $floorplans,
'compare' => 'in',
];
$query->set( 'meta_query', $meta_query );
}
add_action( 'elementor/query/filter_condos', 'my_query_by_filter' );
Please also note that this is a simplification of the code to hilight the issue. My actual code looks like this.
function my_query_by_filter( $query ) {
$start_time = hrtime(false);
// Get current meta Query
$meta_query = $query->get( 'meta_query' );
// If there is no meta query when this filter runs, it should be initialized as an empty array.
if ( ! $meta_query ) {
$meta_query = [];
}
global $wpdb;
//filter based on city
$city = $_GET['city'];
echo '<script>console.log("city: ' . $city . '");</script>';
$floorplans = array();
$layouts = $wpdb->get_results('SELECT term_id FROM wp_termmeta INNER JOIN wp_postmeta ON wp_termmeta.meta_value=wp_postmeta.post_id WHERE wp_postmeta.meta_key="city" AND wp_postmeta.meta_value="' . $city . '" GROUP BY term_id', ARRAY_N);//returns each layout //I will take care of security flaws later
foreach($layouts as $layout) {
$floorplans[] = '' . $layout[0];
}
$meta_query[] = [
'key' => 'layout',
'value' => $floorplans,
'compare' => 'in',
];
$query->set( 'meta_query', $meta_query );
$end_time = hrtime(false);
$execution_time = ($end_time[1] - $start_time[1]);
echo '<script>console.log("Query took ' . $execution_time . ' nanoseconds to execute");</script>';
}
add_action( 'elementor/query/filter_condos', 'my_query_by_filter' );
I am using Elementor Pro and Pods Admin, along with code snippets.
I have tried setting both global and static variables, along with everything that I can think of, but nothing has worked so far. If there is a better technique to do this, I am open to hearing about it. I just need the user to be able to filter.
want to get wp_attachment_metadata in my own way. I want to get the file name :
a:5:{s:5:"width";i:500;s:6:"height";i:500;s:4:"file";s:25:"2016/08/sprite_1500ml.jpg";s:5:"sizes";a:5:{s:9:"thumbnail";a:4:{s:4:"file";s:25:"sprite_1500ml-150x150.jpg";s:5:"width";i:150;s:6:"height";i:150;s:9:"mime-type";s:10:"image/jpeg";}s:6:"medium";a:4:{s:4:"file";s:25:"sprite_1500ml-300x300.jpg";s:5:"width";i:300;s:6:"height";i:300;s:9:"mime-type";s:10:"image/jpeg";}s:14:"shop_thumbnail";a:4:{s:4:"file";s:25:"sprite_1500ml-180x180.jpg";s:5:"width";i:180;s:6:"height";i:180;s:9:"mime-type";s:10:"image/jpeg";}s:12:"shop_catalog";a:4:{s:4:"file";s:25:"sprite_1500ml-300x300.jpg";s:5:"width";i:300;s:6:"height";i:300;s:9:"mime-type";s:10:"image/jpeg";}s:11:"shop_single";a:4:{s:4:"file";s:25:"sprite_1500ml-400x400.jpg";s:5:"width";i:400;s:6:"height";i:400;s:9:"mime-type";s:10:"image/jpeg";}}s:10:"image_meta";a:12:{s:8:"aperture";s:1:"0";s:6:"credit";s:0:"";s:6:"camera";s:0:"";s:7:"caption";s:0:"";s:17:"created_timestamp";s:1:"0";s:9:"copyright";s:0:"";s:12:"focal_length";s:1:"0";s:3:"iso";s:1:"0";s:13:"shutter_speed";s:1:"0";s:5:"title";s:0:"";s:11:"orientation";s:1:"0";s:8:"keywords";a:0:{}}}
Well, I am stuck. I don’t know how to separate that array. Anyone knows how to separate that array in order I can get the file name (url file).
my code now :
$command = $_GET['command'];
switch ($command) {
case 'list_product':
$loop = new WP_Query(
array(
'post_type' => 'product'
)
);
if( $loop->have_posts() ) :
$data = array( "api_status" => 1, "api_message" => "success");
$meta = array();
while ( $loop->have_posts() ) : $loop->the_post();
$meta[] = array(
"id" => get_the_ID(),
"post_name" => get_the_title(),
"stock_status" => get_post_meta( get_the_ID(), '_stock_status', true ),
"price" => get_post_meta( get_the_ID(), '_price', true ),
"reguler_price" => get_post_meta( get_the_ID(), '_regular_price', true ),
"image" => get_post_meta( get_the__ID(), '_wp_attachment_metadata', true ),
);
endwhile;
endif;
echo json_encode($meta);
break;
i mean when i use :
"image" => get_post_meta( get_the__ID(), '_wp_attachment_metadata', true ),
my result doesnt show anything
what improvement in my code so its can work like what i want ?
If you want an image url, I show you another way to to this. I suppose you want the post thumbnail of a spicific post.
// First we get the image id
$post_thumbnail_id = get_post_thumbnail_id( get_the_ID() );
// Then we get the image data, we will get an array with some informations
$image = wp_get_attachment_image_src( $post_thumbnail_id, 'large' );
// the image url is the first index of this array
$image_url = $image[0];
In this example you get the image url for the largeversion. If you want antoher size, just change it to e.g. meidum or full. Read the documentation of wp_get_attachment_image_src() for more details.
This code must be placed inside the loop. Make sure that get_the_ID() returns the current POST ID. Make also sure that the POST have a post thumbnail.
Basically you can get an image url if you have an ID of an attachmend post (image).
My code:
$this->PackageCustomer->id = $customer_id;
$data['PackageCustomer'] = array(
'shipment' => 2,
'comments' => $this->request->data['Ticket']['content'],
'shipment_equipment' => $this->request->data['Ticket']['shipment_equipment'],
'shipment_note' => $this->request->data['Ticket']['shipment_note'],
'issue_id' => $this->request->data['Ticket']['issue_id']
);
pr($data); exit;
$this->PackageCustomer->save($data['PackageCustomer']);
//var_dump($this->PackageCustomer->invalidFields());
// pr($this->PackageCustomer->error);
echo $this->PackageCustomer->getLastQuery(); exit;
I inspect array $data. Data is being revived properly. And getLastQuery function is:
function getLastQuery() {
$dbo = $this->getDatasource();
$logs = $dbo->getLog();
$lastLog = end($logs['log']);
return $lastLog['query'];
}
Which is defined in appModel. I am using cakephp 2.6.9. But last query is :COMMIT which does not make any sense. I check My model convention. It is okay. Now what is the problem in my code?
Try this::
$this->PackageCustomer->id = $customer_id;
$data['PackageCustomer'] = array(
'shipment' => 2,
'comments' => $this->request->data['Ticket']['content'],
'shipment_equipment' => $this->request->data['Ticket']['shipment_equipment'],
'shipment_note' => $this->request->data['Ticket']['shipment_note'],
'issue_id' => $this->request->data['Ticket']['issue_id']
);
pr($data); exit;
$this->loadModel('PackageCustomer');
$this->PackageCustomer->save($data['PackageCustomer']);
//var_dump($this->PackageCustomer->invalidFields());
// pr($this->PackageCustomer->error);
echo $this->PackageCustomer->getLastQuery(); exit;
If the above code doesn't work I need the following answered to help further...
I need bit more information can you confirm the following:
What is the name of the table you are trying to save to?
What is the name of the class relating the to the table you are trying to save to?
Are you trying to edit or create a new record in this table?
Looking to limit the returned fields of a WP Query to help with speeding up the response from the server and reducing the amount of data retrieved. For the query I'm using, it only needs up to 3 fields of data, the rest is brought in through ACF get_field_object in the loop. Other functions I'm using such as get_posts or get_terms have field options but are limited to a small number of things, such as 'slug' only or 'id => slug'.
I'm used to developing in CakePHP, which has the option to specify each and every field to return, but the project calls for wordpress for other functionality and so I'm quite limited.
TL;DR need to speed up getting posts from Wordpress
I used fields parameter in the query and run get posts on this query.
For example: In my case, I just needed to get the Post ids for multiple categories, so I created a query like this:
$the_query = new WP_Query( array(
'ignore_sticky_posts' => 1,
'posts_per_page' => -1,
'cat' => '2,6,7' ,
'fields' => 'ids',
'post_type' => 'post',
'post_status' => 'publish',
)
);
Run the get_posts on this query:
$posts = $the_query->get_posts();
$posts will get only the IDs of particular categories posts.
Or it can also be done with the standard and popular way and i.e., by running the loop of have_posts:
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
$post_id_array[] = get_the_ID();
}
}
These are the two ways to help with speeding up the response from the server and reducing the amount of data retrieved
WP_Query will return objects...so it's pretty fast. However, if you really want to limit what's returned, you can do so with the Return Fields Parameter of WP_Query.
I don't know how much it will help but below is how I'm getting a flattened array from a CPT. It's not the fastest but it could be worse. I'm using ACF to get a Custom Field but you could just get back the slug or you could get back multiple fields instead:
// Query Jobs Args
$query_args = array(
'post_type' => 'job',
'posts_per_page' => -1,
'fields' => 'ids'
);
// Get Jobs Query
$query = new WP_Query($query_args);
// Loop Persistent Vars
$job_ids = array();
// Loop Over Jobs
foreach($query->posts as $post_id) {
$job_ids[] = get_field('job_id', $post_id);
}
// Do stuff with flattened array of job ids
This is what I've done to limit the fields from WP_Query, especially, when I want to json_encode them. The $return variable contains my array of posts with only the fields listed in the $fields array.
$query = new WP_Query( array( 'post_type' => 'my_custom_type' ) );
$return = array();
$fields = array('post_title', 'ID'); //list of fields I want in $return
$posts = $query->get_posts();
foreach($posts as $post) {
$newPost = array();
foreach($fields as $field) {
$newPost[$field] = $post->$field;
}
$return[] = $newPost;
}
Interestingly enough, you can do this with the WP Rest API using the _fields parameter
https://yoursite.com/wp-json/wp/v2/posts?_fields=author,id,excerpt,title,link
More info on the API here: https://developer.wordpress.org/rest-api/
I am able to obtain the $data array from a form and I can generate data for each item... But during the binding and storing with jTable object it saves only the latest item why... I am using native JTableMenu class to bind and save by using my own class which is extended by native one. Early trials I used database object to save items with sql syntax but some columns of table remains empty lft and rgt to fill them I used table object but it gives this issue.
The whole code is following:
function addcumulative($data){
$db = JFactory::getDBO();
$component = & JComponentHelper::getComponent('com_dratransport');
$menus = array();
$query = array();
$countries = DraTransportHelperArrays::countries();
$cities = DraTransportHelperArrays::cities();
$title = array();
$alias = array();
$path = array();
$link = array();
if(empty($data['parent_id']) && $data['parent_id'] == 0){
$data['parent_id'] = 1;
}else{
$parent_id = explode('.',$data['parent_id']);
$data['parent_id'] = $parent_id[1];
}
if(!empty($data['locationQuery'])){ //actually this part will be used
$loc = ($data['locationQuery'] == 'countries') ? $countries : $cities['Turkey'] ;
foreach($loc as $k => $c){
$query[0] = $data['general'];
foreach($data as $key => $dat){
if(!empty($dat) && strpos($key,'Query') !== false){
$v = explode('Q',$key);
if($v[0] !== 'location'){
$query[] = '&'.$v[0].'='.$dat;
}else{
$query[] = '&'.$dat.'='.$k;
}
}
}
$title[] = $data['viewQuery'].'-'.$k;
$alias[] = $data['viewQuery'].'-'.$k;
$path[] = $data['viewQuery'].'-'.$k;
$link[] = implode('',$query);
$query = array();
}
}else{
$query[0] = $data['general'];
foreach($data as $key => $dat){
if(!empty($dat) && strpos($key,'Query') !== false){
$v = explode('Q',$key);
$query[] = '&'.$v[0].'='.$dat;
}
}
$link[] = implode('',$query);
}
foreach($link as $n => $l){
$menus[] = array(
'menutype' => $data['menutype'],
'title' => $title[$n],
'alias' => $alias[$n],
'path' => $path[$n],
'link' => $link[$n],
'type' => 'component',
'published' => 1,
'parent_id' => $data['parent_id'],
'level' => 1,
'component_id' => $component->id,
'access' => $data['access'],
'params' => $data['params'],
'language' => '*'
);
}
$count = $data['count'] == 0 ? count($loc) : $data['count'];
foreach($menus as $menu){
// Bind the data.
$table = $this->getTable();
$table->bind($menu);
$table->store();
}
}
Yes you are totally right. Let say $countries=array('England','France','Germany'); then I wrote my code in model to generate links in #__menu table. So I write
foreach($countries as $country){
$link='index.php&option=com_mycomponent&view=members&type=1&countries='.$country;
$table->bind();
$table->save();
}
I am generating links like this, view and the type values in query comes from the form submitted to make parmaters same for all menus except countries;
and I assign all parametes to manu item and menu items to an array as array item...
to save database the table comes with nested.
$menus->$each menu as $menus array item->menu item parameters
while the table is first created in above code code just adds the last menu item but if I take it insede the foreach it adds all of them but parent_id and level parameters assigned to 0 bye the native code altought I set them as 1