Anyone can help with this please? It's driving me crazy.
I have 2 taxonomies on my website, the built-in categories and one I created called Countries ('country'). I want to order all the posts that lead to custom taxonomy by title and keep the posts that lead to built-in categories in order by date.
I am using the following code, but it gives me posts on both taxonomies ordered by title. What I am doing wrong?
add_action( 'pre_get_posts', 'theme_taxonomy_order' );
function domino_taxonomy_order($query){
if(!$query->is_main_query()) return $query;
if(is_country) $query->set( 'orderby', 'title' );
if(is_country) $query->set( 'order', 'ASC' );
return $query;
}
I made it work eventually! That's the correct code:
//Customise Country taxonomy archive display
add_action( 'pre_get_posts', 'customise_country_taxonomy_archive_display' );
function customise_country_taxonomy_archive_display ( $query ) {
if (($query->is_main_query()) && (is_tax('country'))){
$query->set( 'orderby', 'title' );
$query->set( 'order', 'ASC' );
}
}
Related
I have created code as below and the focus part is PM.meta_key !='_price' and I don't know how true it is, it didn't work but it's also possible to remove all products otherwise, I need a correct way.
Also here is a picture, some products don't have the "_price" key and this way the product looks very bad, the strange thing is that they are still in stock.
Here is an example photo.
add_action( 'init', 'automatically_trash_instock_empty_price' );
function automatically_trash_instock_empty_price() {
// Get any existing copy of our transient data
if ( false === ( $automatically_trash_instock_empty_price = get_transient( 'automatically_trash_instock_empty_price' ) ) ) {
// It wasn't there, so regenerate the data and save the transient
global $wpdb;
$wpdb->query( "UPDATE {$wpdb->posts} P JOIN {$wpdb->postmeta} PM ON P.ID = PM.post_id SET P.post_status='trash' WHERE P.post_type='product' and PM.meta_key != '_price'" );
set_transient( 'automatically_trash_instock_empty_price', true, 1 * HOUR_IN_SECONDS );
}
}
I know you asked for MySQL query but why not use native functions for this? You can query all your products and foreach create a product object using the following function:
$product = wc_get_product( $post_id );
And after that you will be able to access all product's data. All available methods can be found here, but the ones you probably need are:
$product->get_regular_price();
$product->get_sale_price();
$product->get_price();
Then check if $product->get_price(); is null, empty and/or zero and just:
wp_trash_post($product->get_id());
Trash post doc
Finally, you could also set this up as a cron job to run daily/weekly and clean up your products regularly.
EDIT
As per your comments here is a full working example of a scheduled function via wp-cron to do what you asked regularly:
// Your scheduled function
function trash_products_without_price_stock() {
$get_all = new WP_Query(
array(
'post_type' => 'product',
'posts_per_page' => -1,
)
);
if ( $get_all->have_posts() ) :
while ( $get_all->have_posts() ) :
$get_all->the_post();
// Start : Your conditionals here
if ( ! get_post_meta( get_the_ID(), '_price', true ) && get_post_meta( get_the_ID(), '_stock', true ) ) {
wp_trash_post( get_the_ID() );
}
// End
endwhile;
wp_reset_postdata();
endif;
}
// Schedule Cron Job Event
if ( ! wp_next_scheduled( 'clean_my_products' ) ) {
// here you can use 'hourly', 'twicedaily', 'daily', and 'weekly'
wp_schedule_event( time(), 'daily', 'clean_my_products' );
}
add_action( 'clean_my_products', 'trash_products_without_price_stock' );
Put the above in functions.php
I'm using Timber for Wordpress and when I use a custom query in archive.php to get posts of a custom post type, it returns posts of multiple post types.
I tried the exact same query in page.php and it worked perfectly.
Here's the query I'm using:
global $paged;
if (!isset($paged) || !$paged){
$paged = 1;
}
$args = array(
'post_type' => 'horse',
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page' => 20,
'paged' => $paged
);
$context['horses'] = new Timber\PostQuery( $args );
I would expect that to return all items of post type 'horse', but other post types are also mixed in.
Any ideas why this might be happening?
I'm not sure if this is related, but I also added this to functions.php, inside the StarterSite class, in order to add my custom post type to the archive page:
function namespace_add_custom_types( $query ) {
if( is_category() || is_tag() && empty( $query->query_vars['suppress_filters'] ) ) {
// Get all your post types
$post_types = get_post_types();
$query->set( 'post_type', $post_types );
return $query;
}
}
And this was added to the existing function named __construct:
add_filter( 'pre_get_posts', array($this, 'namespace_add_custom_types') );
How are you calling it in the twig file?
{% for post in horses %}
{{ post.name }}
{% endfor %}
Also, are you sure the post type name is horse and not horses? If the wrong post type name is included in 'post_type' it would show all post types.
I want to use ACF frontend form function to create a form with custom fields
I see this issue for create new term, #Alhana
ACF front end form to create term
but I want to generate the form with old data
Well, i didn't see that question, but if it's still actual, here's a solution.
First of all, make sure you have ACF group, linked to your taxonomy. You will need ID of this group, it can be found in url on group edit page, for example:
http://site.ru/wp-admin/post.php?post=340&action=edit
In this case group ID is 340. If you don't want to use hardcoded ID (if your groups are changing from time to time), you can get it, using group name (in this example group name is Technic CPT):
global $wpdb;
$group_ID = $wpdb->get_var( "SELECT ID FROM $wpdb->posts WHERE post_title = 'Technic CPT'" );
Then, you'll need ID of term you're updating. I think, it's not nesessary to write about getting it since it's WP basics :) You'll end with something like this:
$term_id = 405;
And finally, you'll need your taxonomy's slug. In this example it's technic. So, let's render our form!
acf_form_head();
$acf_form_args = array(
'id' => 'technic_edit_form',
'post_id' => 'technic_'.$term_id,
'form' => true,
'submit_value' => 'Update technic',
'field_groups' => array($group_ID),
'updated_message' => 'Technic is updated!';
);
acf_form( $acf_form_args );
Now your term's custom fields will be shown in this form. But to save term data after editing you'll need to add some more code. ACF form assumes that you're saving post data, we'll add some logic to detect saving data for term.
add_filter( 'acf/pre_save_post', 'acf_handle_form_save', 10, 1 );
function acf_handle_form_save( $post_id ) {
// Function accepts id of object we're saving.
// All WordPress IDs are unique so we can use this to check which object it is now.
// We'll try to get term by id.
// We'll get term id with added taxonomy slug, for example 'technic_405'.
// For checking term existence we must cut out this slug.
$cut_post_id = str_replace( 'technic_', '', $post_id );
$test_tax_term = get_term_by( 'id', $cut_post_id, 'technic' );
// If $test_tax_term is true - we are saving taxonomy term.
// So let's change form behaviour to saving term instead of post.
if ( $test_tax_term ) :
// Get array of fields, attached to our taxonomy
global $wpdb;
$group_ID = $wpdb->get_var( "SELECT ID FROM $wpdb->posts WHERE post_title = 'Technic CPT'" );
$acf_fields = acf_get_fields_by_id( $group_ID );
// Then sanitize fields from $_POST
// All acf fields will be in $_POST['acf']
foreach ( $acf_fields as $acf_field ) :
$$acf_field[ 'name' ] = trim( esc_attr( strip_tags( $_POST[ 'acf' ][ $acf_field[ 'key' ] ] ) ) );
endforeach;
// We need to have some fields in our group, which are just duplicates of standard term fields: name, slug, description.
// In this example it's only one field - term name, called 'technic_name'.
$name = 'technic_name';
// Update base term info, in this example - only name.
$term = wp_update_term( $cut_post_id, 'technic', array( 'name' => $$name ) );
// If all is correct, update custom fields:
if ( !is_wp_error( $term ) ) :
foreach ( $acf_fields as $acf_field ) :
update_field( $acf_field[ 'name' ], $$acf_field[ 'name' ], 'technic_' . $cut_post_id );
endforeach;
endif;
else :
// Here is saving usual post data. Do what you need for saving it or just skip this point
endif;
return $post_id;
}
Please note: validation of $_POST data may be more complex. For example, you may have to validate array of values if there are ACF galleries or relationships among your taxonomy fields. In my example i have only common text fields.
Hope that helps!
The answer from Alhana worked for me with one change. The term object works if sent as the the value for the post_id:
$term_obj = get_term($term_id);
$acf_form_args = array(
'post_id' => $term_obj,
'post_title' => false,
'submit_value' => 'Update Term',
'field_groups' => array($group_ID),
);
I would like to display a message in my-account if the customer has no orders I would like to show "No orders currently".
I guessing there's a function I could use to hook into this somewhere?
Had a good search and cant find anything to get me started.
Thanks.
Modifying from this tutorial I think this would work:
function wc_get_customer_orders() {
// Get all customer orders
$customer_orders = get_posts( array(
'numberposts' => 1,
'meta_key' => '_customer_user',
'meta_value' => get_current_user_id(),
'post_type' => wc_get_order_types(),
'post_status' => array_keys( wc_get_order_statuses() ),
) );
$customer = wp_get_current_user();
// Text for our message
$notice_text = sprintf( 'Hey %1$s 😀 We noticed you haven\'t placed any orders with us.', $customer->display_name );
// Display our notice if the customer has no orders
if ( count( $customer_orders ) == 0 ) {
wc_print_notice( $notice_text, 'notice' );
}
}
add_action( 'woocommerce_before_my_account', 'wc_get_customer_orders' );
Basically, on the account page we query for a single order by the currently logged in user. If we don't get an order back we show the notice.
Copied my-orders.php to local folder and added an else clause:
else{
echo "No orders";
}
This can be styled using WC css
I am now discovering the Yii framework and doing it by trying to develop a simple application which allows to create Leagues and assign Players to it. The relationship between these is many to many (a player can subscribe to many leagues, and one league contains many players). So I have three db tables - tbl_league, tbl_player and tbl_league_player and I created foreign keys like this:
ALTER TABLE tbl_league_player ADD FOREIGN KEY league_id_idxfk (league_id) REFERENCES tbl_league (id);
ALTER TABLE tbl_league_player ADD FOREIGN KEY player_id_idxfk (player_id) REFERENCES tbl_player (id);
Now I am trying to display League with the list of all players subscribed to it, so my actionView in LeagueController says:
public function actionView($id)
{
$issueDataProvider = new CActiveDataProvider('Player', array(
'criteria' => array(
'condition' => 'league_id=:leagueId',
'params' => array(
':leagueId' => $this->loadModel($id)->id
),
),
'pagination' => array(
'pageSize' => 1,
),
));
$this->render('view',array(
'model'=>$this->loadModel($id),
'issueDataProvider' => $issueDataProvider,
));
}
What I am trying to do here is to get all players from the Player table subscribed to a particular league ID. For this I have the Player model with relation defined like this:
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'League' => array(self::MANY_MANY, 'League', 'tbl_league_player(player_id, league_id)'),
);
}
The problem is that I go to, for example, league/view&id=2, I am getting this error: "SELECT COUNT(*) FROM tbl_player t WHERE league_id=:leagueId" so it looks like the relation does not work. What am I missing?
Thanks a lot!
So, first, the reason for the error is that you are adding a WHERE league_id = condition to your Player CActiveDataProvider, and your Player table does not have a league_id column.
What you should do to get a list of the players in your View is:
1) NOT make a CActiveDataProvider - just pass in the $model to your view
public function actionView($id)
{
$this->render('view',array(
'model'=>$this->loadModel($id),
));
}
2) Then, in your view, just lazy-load your MANY_MANY relation and loop through it like so:
<?php foreach($model->League as $player): ?>
<?php echo $player->name ?>
<?php endforeach; ?>
I would rename your "League" relation "players" or something.
If you really need to use a CActiveDataProvider... I can't remember how to (or if you can) pass in a a relation, but you can do it my manually adding join criteria to your CActiveDataProvider.
I hope this helps! Cheers
try this.
Inside LeagueController
public function actionView($id)
{
$criteria=new CDbCriteria;
$criteria->with='League';
$criteria->together=true;
$criteria->condition='league_id=:leagueId';
$criteria->params=array(':leagueId'=>$this->loadModel($id)->id);
$issueDataProvider = new CActiveDataProvider('Player',array(
'criteria'=>$criteria,
),
'pagination' => array(
'pageSize' => 1,
),
));