Ordering by multiple meta keys wordpress - php

Im aware there are several posts relating to this issue but i am yet to find a fix for my current problem.
Im reasonably new to Wordpress and am still getting used to it, however...
The Problem
I'm implementing a front end sorting system for users to filter out schools, i am using a rating plugin (comment rating field pro) and the issue i have is that when users sort by star rating i also want it to sub sort by number of reviews (comments). Currently it is only sorting by rating and simply ignoring the number of comments and sorting by title. I have tried various combinations of query parameter arrays such as meta_query and multiple meta keys but the issue appears to be that it refuses to sort the second value. Both are numbers in the database.
TL:DR it needs to sort by stars and then by number of reviews.
Unfortunatly a custom query is out of the question as the array is being fed into another plugin which appears to only accept an array of args.
This is the sort of idea im going for (this does not work)
Array ( [post_type] => surf-school [posts_per_page] => 12 [paged] => 0 [meta_key] => crfp-average-rating [orderby] => meta_value crfp-total-rating [order] => DESC )
Any help would be greatly appreciated as its driving me insane!
Thanks in advance.
Update
I have managed to fix this using from a comment reply to this post which now appears to have been deleted :(
I managed it by adding a filter to wp_query and forcing a custom order by as seen here Plugin API/Filter Reference/posts orderby - Codex
function edit_posts_orderby($orderby_statement) {
$orderby_statement = "wp_postmeta.meta_value DESC, wp_posts.comment_count DESC";
return $orderby_statement;
}
placed in functions.php and
add_filter('posts_orderby', 'edit_posts_orderby');
placed just before the query. Hope this helps someone else :)

Related

PHP - Sort and order an array of objects by category name

I am learning PHP and have decided to code my own OOP MVC framework. Now, I have realized several times already that it might not be the smartest move but I mean to see this out to the end. And then onwards...
My issue is creating a listing sidebar based on categories and a second based on year-month-postname.
I am officially stuck on the first one, let alone the second damn option. I have included some code and description of what I have tried. The lack of OOP info on the net is daunting or maybe it is because I am searching for the wrong thing, I dont know. But the tutorials have not given me any insight as to how to actually do this in a way where my database is in a model file and my class logic is in the class file.
Sorting logic should be like this Array-Object-Propertyname-Value.
The value, as I hope is easy to understand in my example below, is the category name eg Javascript, PHP, HTML. By that category i wish to sort my blog posts. But not in the way that requires me to manually input the category names to the code. I want to allow users to enter categories if they so choose.
I also wish to display the blog posts inside said category, lets say 5 most recent. But that should not be too hard with a
for($i=0,$i<5,i++)
nested inside whatever solution in the end will work for the category sort.
I have tried MySQLI procedural solutions ranging from multiple google searches and tutorials. Can do it, but dont want to do it procedurally. Tried foreach loop and nesting multiple foreach loops - simply cannot get either the problem of having duplicates based on the shared category name or if trying to group in the SQL query, it simply groups results with same category and then displays only the first one in the group. While loops with mysqli procedural work but with pdo in my case they produce infinite loops, no matter the condition I try to set.
So foreach is the way to go I believe. I have read up on loops and array sorting but I've yet to find a solution. I thought of sorting by key because that is what i need but to no applicable solutions.
It's easy to display the category names and dates and all that. But with category I always get duplicates.
Ive tried some logic where as to assign category names as variables but only to have them all be different variables, meaning still having duplicates or only rewriting the variable with each iteration.
Also, array sorts havent worked because I havent gotten any to work with sorting either on property or if converting Objects to a multidimensional array. Granted that may be because I am a beginner and not understood the syntax but I am not going to post them all here I think.
If you think an array sorting function will do the trick then perhaps give me an example and I will look into it with some new perspective hopefully.
PDO query :
'SELECT * FROM postTable
INNER JOIN userTable ON postTable.postUserId = userTable.id
INNER JOIN postCategories ON postTable.postCategoryId = postCategories.categoryName
ORDER BY postTable.postDate DESC'
Tried also to add
GROUP BY categoryName
but that resulted in only one entry per category shown when using var_dump. Sidenote - same is when grouping by creation date. Is there another layer added to the array when using group in the SQL command and I missed that in the docs?
PDO returns to view file :
$this->stmt->fetchAll(PDO::FETCH_OBJ);
this all gets passed into an array of
$results
and then that is sent to the php on the view page where the resulting array has this structure with var_dump.
array() {
[0]=>
object(stdClass)# () {
["categoryName"]=>
string() "Help"
}
[1]=>
object(stdClass)# () {
["categoryName"]=>
string() "Me"
}
and so on.
Note - also tried using -
fetchAll(PDO::FETCH_ASSOC);
But ive had similar failures with attempting any sorting or limiting to just one category name displayed but all entries under said category being displayed correctly and not just one per category.
I will be checking back when i finish work tomorrow so in about 20-22 hours from the time of posting.
If you need any more info just let me know and I'll post it.
You can order by multiple columns. Use:
ORDER BY categoryName, postDate DESC
This will keep all the posts in the same category together, and in decreasing date order within each category.
See How can i list has same id data with while loop in PHP? for how you can output the results, showing a heading for each category.
If you just want to get the 5 latest posts in each category, see Using LIMIT within GROUP BY to get N results per group?

SQL - Writing an order by case or if statement

Some beforehand layout knowledge about the database
I have a database with my store items that has the following four fields
`c.postdate`, `c.regularprice`, `c.isonsale`, `c.saleprice`
The standard call to the database is something like the following:
query("SELECT * FROM items WHERE `s.cat` IN (idsarrayishere) AND `s.isactive` = '1' $sort")
This works to just pull everything from the database. The default value for $sort is just blank since I am not worried about that at this time as I will most likely just sort them by newest date using the c.postdate field listed above.
Sorting items by specific variables
I would love to be able to take advantage of the ORDER BY CASE that mysql has to be able to sort my items from price highest - lowest and vice versa. The issue I am running into is I don't know how to write the query so that if the c.isonsale = '1' then order by the the c.saleprice instead of the c.regularprice, and if it's not, order by the c.regularprice, so when they select lowest price first, it will show them the sale items in with the lower priced items. This is what I've found so far for ORDER BY with case
ORDER BY
CASE `type`
WHEN 'Member' THEN LNAME
WHEN 'Group' THEN GROUPNAME
ELSE 1 END
ASC
Not sure the correct way to adapt this to what I am trying to do though. Any help on this matter would be appreciated as the MySQL doc's are a little vague when learning this process.
Edit
In response to the reply about adding sample data and expected result since my post isn't clear about this apparently, say I have these three items
item => 1
c.regularprice => 9.99
c.isonsale => 0
c.saleprice => 0
item => 2
c.regularprice => 19.99
c.isonsale => 1
c.saleprice => 6.99
item => 3
c.regularprice => 10.99
c.isonsale => 0
c.saleprice => 0
I need to be able to sort by price lowest first, then go to highest. So with this example, I would expect item 2, item 1, item 3 in that order. Even though the regular price of item 2 is higher than the others, its on sale and cheaper so should show first.
Since you're only switching between two possible options, I think IF will be simpler than CASE.
ORDER BY IF(c.isonsale, c.saleprice, c.regularprice)
That IF expression will return the sale price if the item is on sale, and the regular price if it isn't.

How to use a relationship in the where parameter when finding records using the pods framework?

my question has to do with the pods framework plugin for wordpress sites. I am using pods version 2.2 and have been having trouble with the where parameter in the find() function.
I'd be suprised if I am the first person to encounter this problem but I have searched extensively and haven't found anyone providing an answer (or question at that).
Anyway, I'll give an example to highlight my problem.
Say I have a Bands Pod and a Records Pod and these two pods have a bi-directional multi-select relationship between them (that is, an n to n relationship). Hence a band can have numerous records and a record can have multiple bands. Further, the relationship exists between the fields BandsPod('records') and RecordsPod('bands').
Now, I can retrieve all records in the records pod like so (note the where is commented out):
$pods = pods('records');
$params = array(
'select' => 't.*',
'limit' => -1
//,'where' => '???'
);
$pods->find($params);
Then do whatever I want with them, e.g. template(), fetch(), etc.
My trouble occurs when I want to filter by band. What should my where statement be if I want to retrieve all records by band with id 1?
My view is that it should be something like this:
$params = array(
'select' => 't.*',
'limit' => -1,
'where' => '1 IN bands.id'
);
$pods->find($params);
However, this does not work (not that I especially expected it to).
It would also be desirable to know how this would work for filtering by multiple bands. E.g.
'where' => '(1, 2) IN bands.id'
As I said before, I've been trying to get this to work for some time and with little joy. I have managed to get it working but in a very ugly way. I.e.
Get bands from Bands Pod with relevant band ids,
Collect all ids of records from the bands pod records field,
Write params for Records Pod
Use the ids in the where statement to check they match with t.id,
$pods->find(); //where $pods=pods('records');
Thanks in advance for taking the time to read this and any answers you may give.
Cheers,
Joe
N.B. I know about the filters() function and it does not do what I'm after. I'd like stuff specifically for the where statement please.
You would want:
'where' => 'bands.id IN ( 1, 2 )'
If your bands are a custom post type, it would be:
'where' => 'bands.ID IN ( 1, 2 )'

Go to or create array index base an second array of indexnumbers

OK, this may sound like an odd question so first let me lay out the basic situation:
At our company we're using a ticketsystem. This system has a FAQ dbase. I can't change the structure of the database in any way because we would have to change the ticketsystem to cope with that change and that is not an option.
So with that out of the way...
Because there is no seperate field available we add a chapter number to the title of every item to have a sort of index.
So you'd get something like this:
1 start
1.1 some subchapter
2 new chapter
3 another chapter
3.1 sub of chapter
3.1.1 sub sub chapter
etc..
Offcourse with a nifty regex it's easy to extra the chapter part from the string. But the next step would be to make it easy to find the corresponding subchapters based on the parent chapter. Easiest way to make this searchable without a database would be a multidimensional array, right?
So you would get this:
array( 3 => array(
'item' => 'data', 1 => array('item', 2 = array() ) ) ) etc...
What I've done now is to create an array of chapter indexes ( [3,1,1] in the case of 3.1.1 ) and because I know the there are always between 1 and 3 items in this array I made a switch based on the array length and then did this:
$array[$index[0]][$index[1]]['item'] = $content;
But I feel this is a very dirty and unlfexible way of doing this. Normally I'd vote for changing the database structure no matter what, but without that option I'm unsure what the best method would be.
Any help would be great!
EDIT: Added my comment below for better readability
Titles are one line indeed, but that part I have working with a regex to extract the chapter part. So that's working.
What I basicly build is a form that uses the array of indexes to build a list of checkboxes for each chapter or chapterpart. But I don't want to search through the array and compare keys to find subchapters. So if I'd choose 3.1 I'd check 3.1.1, 3.1.2 and because the key starts with 3.1 I'd know to print it.
Faster would be to be able to do this:
Choose 3.1.1 => return $chapters[3][1][1]['item']
But that's only possible when I can build the initial array in that form.
The situation has changed and we are creating a second database structure with a better setup to handle the situation above.
Basicly we use that to both print a well formatted PDF as well as pushing the info in the FAQ of the ticket system.
This gives us the best of both world and thus solving the issue above.

How do I find the qty of products ordered for a specific attribute option in Ubercart?

I'm trying to make a custom order summary module for Ubercart/Drupal that will display information something like this:
S M L
Prod1 10 20 40
Prod2 0 15 0
where S, M, and L are options for a custom attribute (size in this case), and the numbers are the quantities ordered of each product of each size.
I notice that the selected option is specified in the data field for the product in the uc_order_products table of the database. I can figure out all the arithmetic and everything if someone can tell me a good way of finding all the uc_order_products rows which contain a specific option for a specific attribute. I'd even be happy with just a simple way to return the data field as an object or associative array.
Alternate solutions involving Ubercart's API are also welcome, but from what I saw in the docs, there don't really appear to be functions for this kind of thing.
Thanks!
I found my answer in PHP's own unserialize(). I'd never had any experience with serialization in PHP, so I didn't recognize the format when I saw it.

Categories