WordPress Filtering Custom Post Type by Metadata and Search Heirachy - wordpress-theming

I have a custom Post Type called cptMovie which has two Custom Field (Metadata) "Language" and "Box office" assigned to it.
I also have a Custom Taxonomy called movieTax with 4 tax Terms "Action", "Comedy", "Family" ,and "Horror" .
In a WordPress File structe like below:
index.php
page.php
page-movie.php
taxonomy.php
taxonomy-movieTax.php
I am able to list and display all the Custom Post Types (movie) under Taxonomy (movieTax) using indexed page page-movie.php and custom wp-query and eventually link them to the taxonomy-movieTax.php to have all Post under each tax terms.
Up to here I am Ok and getting the resut BUT I need to add some Filters for users like Filtering the result by Language or Boc office Metadata,
Now my question is Which Part of the WP Template Hierarchy is in charge of displaying the result? Do I have to create the search.php if so how a query like this:
$arg = array(
'meta_query' => array(
array(
'key' => 'language',
'value' => 'english'
)
)
);
$filter-lang = new WP_Query( $arg );
in page-movie.php will end up in search.php?
Thanks,

You don't need to create a "search.php" file.
You can add the below code in "page-movie.php" or "taxonomy-movieTax.php" file, as per your requirement.
$arg = array(
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'language',
'value' => $lang_val,
'compare' => '='
),
array(
'key' => 'box_office',
'value' => $box_office_val,
'compare' => '='
)
)
);
$filter-lang = new WP_Query( $arg );
Here, $lang_val & $box_office_val are values to search for language key & box office key respectively. However, if you want to create separate search file, you also need to specify post type in arguments.

Related

Wordpress Meta Query when Meta type is object

I have a meta user of type object on my custom post type.
Now I would like to query all custom-posts which have this meta value. I have not found a way how to query meta values of type object. Is there a way actually ?
$args = array(
'post_type' => 'custom-posts',
'post_status' => 'publish',
'posts_per_page' => -1,
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'user.id',
'value' => $this->user_id,
),
)
);
Thanks in advance.
When WordPress (or a theme or plugin) stores an object or an array as the value of an item of metadata, it first serializes the object into a text representation.
For example, this object
$obj = array ('first'=>'Jeff', 'last'=>'Atwood',);
when serialized is this text string:
a:2:{s:5:"first";s:4:"Jeff";s:4:"last";s:6:"Atwood";}
So, if you want to search this item of metadata for, let's say, Jef, you'll need something like this:
$args = array(
'post_type' => 'custom-posts',
'post_status' => 'publish',
'posts_per_page' => -1,
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'user.id',
'value' => 'Jef',
'compare' => 'LIKE'
),
)
);
It will search the text of the serialized object for any row that contains the consecutive letters Jef. In SQL, it uses meta_value LIKE '%Jef%' to look for the string you're matching.
This is acknowledged by everybody involved with it to be a sloppy and slow kind of search. You must check the results it returns to make sure it didn't match the wrong thing. It will match what you do want, but it also may match other things.

WordPress query posts without ACF repeater subfields AND specific value

I have two custom post types, playlists and games. Playlists have a ACF repeater field, that contain games.
My goal: I am trying to build a simple query, that gets all playlists that DO NOT have this game listed in the repeater field AND alll playlists that are empty (do not have any repeater fields / database entries at all). I want to use the get_posts() function to achieve my goal, if possible.
My problem: I can only get the query to show ONLY the playlists that HAVE the game by using the = operator in the "game_filter" meta query compare field (but I want the opposite). If I choose the != or <> or IS NOT operator, it spits out all available posts. And if I also include my "empty_playlists" meta query, it ALWAYS shows me all playlists, no matter what operators I use, even tho it is a OR and the listed posts do have entrys.
I tried a lot but just cant get it to work. All exmaples I found were about different things, mostly about the % problem with the repeater field names and its solution. I hope someone can help me with this real quick. What am I doing wrong? Please help fellow and better coders! :-)
This is my code
$excluded_playlists_game_id = 274;
$user_id = 1;
$args = array(
'post_type' => PSiCorePostTypes::PLAYLISTS,
'author' => $user_id,
'order_by' => 'title',
'order' => 'ASC',
'suppress_filters' => false,
'meta_query' => array(
'relation' => 'OR',
'game_filter' => array(
'type' => 'NUMERIC',
'key' => 'psi_playlist_games_%_item',
'compare' => '!=',
'value' => $excluded_playlists_game_id,
),
'empty_playlists' => array(
'key' => 'psi_playlist_games_%_item',
'compare' => 'NOT EXISTS',
),
),
);
$user_playlists = get_posts( $args );
and this function for the % problem.
add_filter( 'posts_where', 'get_user_playlists_query_allow_wildcard' );
function get_user_playlists_query_allow_wildcard( $where ) {
global $wpdb;
$where = str_replace(
"meta_key = 'psi_playlist_games_%_item",
"meta_key LIKE 'psi_playlist_games_%_item",
$wpdb->remove_placeholder_escape( $where )
);
return $where;
}

How to solve more complex wp_query meta_query with WP title

If I were using a SQL statement, this is what it would look like:
select * from courses where active = 1 AND (title = $string OR description = $string)
'courses' is a custom post type
'active' is a custom field created with ACF
'description' is a custom field created with ACF
'title' is the standard WP title for posts
This is what I have so far:
$args_courses = array(
'post_type' => 'courses',
'posts_per_page' => 9999,
'meta_query' => array(
array(
'key' => 'active',
'value' => 1,
'compare' => '='
),
'relation' => 'AND',
array(
'key' => 'description',
'value' => $string,
'compare' => '='
),
'relation' => 'OR',
array(
'key' => 'title',
'value' => $string,
'compare' => '='
)
),
);
It seems as though I can't access the WP title through a meta_query, but can't figure out how to turn my query around so 'active' remains the first column to check on.
Thanks in advance for any help!
What you are trying to do is not supported by the default WP_Query functionality, however you can extend it as described in the following answer from the WordPress Stackexchange site. Note that you you may need to alter it further for your specific use case.
https://wordpress.stackexchange.com/questions/178484/wp-query-args-title-or-meta-value
A few notes on your current query.
relation should only be used once in your meta_query. WordPress uses arrays to do the grouping, and wouldn't know to use "AND" or "OR" in your example.
It looks like you want "all" posts, not really 9999 posts, so you should use -1 to fetch everything in one result set.

CakePHP HABTM Association not working

I've been trying to find an answer to my problem for hours. I am currently working with cakePHP 2.4.
I have two models, Users and Groups. I have created the following associations for each:
(User.php)
public $hasAndBelongsToMany = array(
'Group' =>
array(
'className' => 'Group',
'joinTable' => 'groups_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'group_id',
'unique' => true,
)
);
and (Group.php):
public $hasAndBelongsToMany = array(
'GroupUser' =>
array(
'className' => 'User',
'joinTable' => 'groups_users',
'foreignKey' => 'group_id',
'associationForeignKey' => 'user_id',
'unique' => true,
)
);
The reason I use GroupUser and not "User" is I get an error because I have already used "User for some other relation.
My form looks like this:
echo $this->Form->create('Group', array('controller' => 'group','action' => 'add'));
echo $this->Form->input('User.id', array('type' => 'hidden', 'value' => $authUser['id']);
echo $this->Form->input('Group.address');
echo $this->Form->end(__('Save', true));
I also have a table called groups_users with "id", "user_id" and "group_id"
When I submit the form, it created the new Group and saves the data, but the association is not created.
I tried manually filling a groups_users record with an existing user_id and group_id but still, when I use find(All), it doesn't find the expected association like it should according to the books.
I debugged the array that is being saved and it looks like this:
Array
(
[User] => Array
(
[user_id] => 39
)
[Group] => Array
(
[address] => asdasd, San Antonio, Texas 78233, EE. UU.
)
)
This is the code in my GroupsController add function:
if ($this->Group->save($this->request->data)) {
// redirect or do something
}
I have tried changing the array to work with saveAll like in the books, still only created new record but no association. And as I said, I mannually created a record and tried finding it and it wouldn't find it anyway.
I solved it apparently, I think it was because I hadn't created the GroupsUser.php model file. Not rreally sure because I changed a bunch of stuff! But maybe it helps someone.

Retrieve all data from one table, and some from another in CakePHP

In my CakePHP site, I want to make a drop-down list of all Venues, and any Restaurants that have is_venue=1.
I've tried this in my events_controller:
$venueOptions = array(
'fields' => array('id', 'name_address'),
'order' => array('name'),
'join' => array(
array(
'table' => 'restaurants',
'alias' => 'Restaurants',
'type' => 'inner',
'fields' => array('id', 'name'),
'foreignKey' => false,
'conditions' => array('restaurants.is_venue = 1')
)
),
);
$venues = $this->Event->Venue->find('list', $venueOptions);
But it appears to still just be getting the venues. I don't really need an association between the two, since their associations will both be with an event, not each other.
Where have I gone wrong? Am I close, but just need to tweak this code, or am I just all-together doing it wrong?
I think you could do something along the lines of:
<?php
....
$v = $this->Venue->find( 'list' );
$r = $this->Restaurant->find( 'list' );
$venues = Set::merge( $v, $r );
natcasesort( $venues );
// print_r( $venues );
$this->set( 'venues', $venues );
...
?>
Which is quite like the code above - I just use the Set class and make sure to Controller::set the variable to the view.
Also added some basic sorting to show you one option even though array sorting has nothing really specific to do with CakePHP.
Also fixed some bad variable names where I had originally used $venues, and $restaurants - changed to be consistently $v and $r.
Join will not work if there's no relation between. Venue and Restaurant. You should call them separately and merge the results
$venues = $this->Event->Venue->find('list', $venueOptions);
$restaurants = $this->Event->Restaurant->find('list', array('conditions' => array('is_venue' => '1')));
$results = array_merge($venues, $restaurants);
// sort results
asort($results);