Wordpress custom query on two tables to get hierarcal data - php

Working with Wordpress and using its functions to query the database on two custom tables. I am trying to output data as a "tree/grouped" format. Example:
Team Name One
- Player Name One
- Player Name Two
- Player Name Three
- Etc...
Team Name Two
- Player Name one
- Player Name Two
- Player Name Three
- Etc...
I am not sure of what would be needed to get the results to display this way. Here is one query I have that joins the tables...
global $wpdb;
$user_id = '1';
$teamlist = $wpdb->get_results( $wpdb->prepare(
"
SELECT
fv_teams.team_id AS team_teamid,
fv_players.player_id,
fv_teams.team_name AS teamname,
fv_players.player_fname AS fname,
fv_players.player_lname AS lname,
fv_players.player_team AS team,
fv_players.player_position AS position
FROM
fv_teams
INNER JOIN fv_players ON fv_teams.team_id = fv_players.team_id
WHERE
fv_teams.user_id = %d
",
$user_id
), OBJECT );
I can certainly get results doing the following...
foreach ( $teamlist as $teamrow )
{
echo 'Team: ' . $teamrow->teamname . '<br />';
echo 'Player ID: ' . $teamrow->fname . '<br />';
}
But the team name will be duplicated in the results as
Team Name One
- Player One
Team Name One
- Player Two
Team Name One
- Player Three
- Etc...
I am fairly certain I need to add a nested loop in there, but I am uncertain as to the coding required.
Any thoughts or direction would be very much helpful to a guy who just lost a good portion of his hair on this. ; )

Not sure on the etiquette for answering your own question but I was able to get what I needed based on nesting the second query within a loop.
$teamlist = $wpdb->get_results( $wpdb->prepare(
"SELECT *
FROM fv_teams
WHERE user_id = '1'
",
$user_id
), OBJECT );
foreach ( $teamlist as $teamrow )
{
$get_team_id = $teamrow->team_id;
echo '<hr>';
echo '<h2>' . $teamrow->team_name . '</h2>';
$playerlist = $wpdb->get_results( $wpdb->prepare(
"SELECT *
FROM fv_players
WHERE team_id = %d
",
$get_team_id
), OBJECT );
echo '<ul>';
foreach ( $playerlist as $playerrow )
{
echo '<li>Player Name: ' . $playerrow->player_fname . '</li>';
}
echo '</ul>';
}
It needs cleaning up but does work for me.

You need a Group by on the teamid.
Examples: http://www.techonthenet.com/sql/group_by.php
Edit you need to write two loops.
<?php
// in plain language
if(TeamName has another value)
display name;
if (playername has another value)
display playername;
end if
end if
?>

Related

PHP - Queries and looping through data structure

I'm working on a project that has multi-tiered PHP tasks, one of which combines some MySQL queries with the PHP structures to print results to a text file. I have the connection, txt file creation, and queries completed and successfully functioning. My issues is in the PHP loop for the data structure and the nested loop to iterate/loop through the structure for the results and print them properly. The data structure loop is correct:
$userQuery = "SELECT title, last_name, first_name
FROM film_actor
LEFT JOIN film f
ON film_actor.film_id = f.film_id
LEFT JOIN actor a
ON a.actor_id = film_actor.actor_id
ORDER BY title";
$filmActors =fopen("FilmActors.txt","w");
while ($row = mysqli_fetch_assoc($result))
{
$title = $row['title'];
$last = $row['last_name'];
$first = $row['first_name'];
$filmActor["$title"][] = "$last".","."$first";
}
The nested loop begins correctly for the key value, but every step I've used to loop and print results only prints the word 'array' rather than the elements. My SQL query is for a database that lists film names, and the actors in the films, so some of these films have 5+ actors listed. My goal is to print them to a text file like so: Film Name: Number of actors: Actor 1 last name, actor 1 first name; etc.
Here is what I"ve successfully started for the nested loop:
while ($k_v = each($filmActor)) {
foreach($filmActor as $k_v => $value) {
//$k_v => $value;
fputs($filmActors, "$title:$value\n");
}
Easiest solution looks like this one:
...
$filmActors = fopen("FilmActors.txt","w");
$text = '';
foreach ($filmActor as $film_title => $actors) {
$text .= $film_title . ':' . count($actors) . ':' . implode(';', $actors) . PHP_EOL;
}
fwrite($filmActors, $text);
fclose($filmActors);

How to display all posts under main category and its subcategories?

I have a custom php/mysql blog. In single post page, I have a sidebar where I am displaying categories. I want to display number of posts those belong to a main category and its subcategories in brackets as we usually see in WordPress. For now I have
Music
Pop
Nature
Lakes
Sea
I want to achieve
Music (5)
Pop (3)
Nature (8)
Lakes (2)
Sea (4)
As you see Music category has 5 posts under it and Pop has 3. But it doesn't mean there are 8 posts in reality. There are actually only 5 posts because Pop is subcategory of main category Music. 2 posts are directly under the main category Music while 3 posts are falling in its subcategory Pop. Thus 2 + 3 = 5.
The categories table looks as (Note that it has nth level of subcategories):
The posts table looks as (Note that a particular post can have its only one category parent i.e. a post can not have its multiple parents)
My code to fetch categories and their subcategories is
public function get_category_hierarchy(&$output, $parent_url, $parent = 0)
{
$sql = "SELECT * FROM `tb_categories` WHERE `category_parent` = " . $parent . " ORDER BY `category_name`";
$rows = $this->get_by_sql($sql);
// Removing trailing slash
$parent_url = rtrim($parent_url, "/");
if(is_array($rows))
{
foreach($rows as $row) :
$url = $parent_url . "/" . $row->category_url;
$output.= "<li><a href='" . $url . "'>" . $row->category_name . "</a></li>";
if($row->category_id != $parent)
{
$this->get_category_hierarchy($output, $url, $row->category_id);
}
endforeach;
}
return $output;
}
On sidebar, I am displaying these categories by following code:
$output = '';
// Create post object
$post_obj = new Post();
echo $post_obj->get_category_hierarchy($output, SITE_URL . 'category');
Now I'm wondering what code need to be add for fetching number of posts (post counts) that fall under a main category and subsequently its sub-sub-categories? Though I tried to fetch them but the result didn't come accurate.
Thank you in advance.
EDIT:
I modified function get_category_hierarchy() by doing following amendment:
foreach($rows as $row) :
$url = $parent_url . "/" . $row->category_url;
// Build database query
$sql = "SELECT COUNT(*) AS 'total_posts' FROM `tb_posts` WHERE `post_parent` = " . $row->category_id . " GROUP BY `post_parent`";
// Execute database query
$rows = $this->get_by_sql($sql);
$output[] = "<li><a href='" . $url . "'>" . $row->category_name . " (" . $rows[0]->total_posts . ")</a></li>";
But oops! It is giving me following result:
Music (2)
Pop (3)
Nature (2)
Lakes (2)
Sea (4)
Obviously, the parent category is having total number of post which are directly associated to it and not to its children. How to fix it?
The approach that I could think of :
Do a group by on the posts table on the post_parent.
From that form an associative array with the index as category_id and pair value as post_count.
Ex. $category_post_counts = array("4" => 5, "5" =>
10)
Now run a foreach loop for all the category ids and fetch its
corresponding parent.
Update the post count by using the indexes.
Suppose for category id 4(pop) there were 5 posts and in music there
were 10 posts. Now in the loop if the category parent is anything
else apart from 0 then update the post count in the array.
Ex.
$category_post_counts["<category_parent_id>"] =
$category_post_counts["<category_parent_id>"] +
$category_post_counts["<category_child_id>"]
This way your end result
will be an associative array with the category ids and all the post
counts.
Pseudo Code
//exctracting all the data
$rows = execute_this_query("SELECT COUNT(post_id) AS `post_count`, `post_parent` FROM `posts` GROUP BY `post_parent`");
//forming the associative array
foreach ($rows as $value) {
$associative_array[value["post_parent"]] = $value["post_count"];
}
$data = execute_this_query("SELECT `category_id`,`category_parent` FROM `categories` WHERE `category_parent` <> 0");
foreach ($data as $value) {
$associative_array[$value["category_parent"]] += $associative_array[$value["category_id"]];
}
//Your final associative array has the exact category_id and net post count as you want.
First you can populate an associative array for the quantity in each category like: category_id => post_qty.
After that, you can use the function bellow to calculate for every category and its children:
function count_posts($category_id, $cache) {
$sum = 0;
$sql = "SELECT * FROM `tb_categories` WHERE `category_parent` = " . $category_id;
$rows = $this->get_by_sql($sql);
foreach ($rows as $child) {
$sum += count_posts($child->category_id, $cache);
}
$sum += $cache[$category_id];
return $sum;
}

Display data from several fields in MySQL-table with specific id

I have the following code (SQL-query tested in phpMyAdmin and seems to work) that fetch data from selected columns:
$ids = isset($_REQUEST['id']) ? $_REQUEST['id'] : array();
if (is_array($ids)) $ids = implode(',', $ids);
if (!empty($ids)) {
$sql = "SELECT upload, upload2, upload3, upload4, upload5 FROM wp_site_table WHERE cid IN($ids) ORDER BY FIELD(cid, $ids)";
$results = $wpdb->get_results($sql) or die(mysql_error());
foreach( $results as $result ) { ... } }
The problem I have is that I want to output all fields from selected cid.
This code will only display the first cid result.
echo $result->upload;
Let's say $ids contain cid 1, 4 and 7 I'd like to output upload, upload2, upload4, upload5 from all those specific rows. How? Use an array in some way?
kind regards
Johan
If you want to echo all the fields, just do it:
echo $result->upload . '<br>' . $result->upload2 . '<br>' . $result->upload3 .
'<br>' . $result->upload4 . '<br>' . $result->upload5;
You should perhaps consider redesigning your database so you don't have repeated fields in each row. It would be better to have another table where each upload is in a row of its own, so there's no hard-coded limit on the number of these values. Then you can use a JOIN query to get all the uploads, and they'll be in an array.
With '$wpdb->get_results' output defaults to OBJECT type. Try using pre defined constant : ARRAY_A , it will result the output as an associative array.
$sql = "SELECT upload, upload2, upload3, upload4, upload5 FROM wp_site_table WHERE cid IN($ids) ORDER BY FIELD(cid, $ids)";
$results = $wpdb->get_results($sql, ARRAY_A) or die(mysql_error());
To access, simply use :
foreach( $results as $result ){
echo $result['upload'];
}

PHP Arrays - Help storing and sorting multiple columns

I'm working on a search system for my database where I break the search phrase into individual search words, search my mySQL database keyword table for any occurrence of those words, and then output a list of IDs associate with the keyword.
I want to add those ID's to a new array that will also contain a count value and (from a new query) the name of the place belonging to the ID, resulting in:
array(ID, count, name)
For each search word I want to go through this process and if the ID is already in the above array I want to increase the count value and if not, I want to add it with a count value of 1.
When the array is built and all the counting is done, I want to sort it by count and then name, and then output the results.
I've programmed PHP for quite some time but I've never been good with building and manipulating arrays so any help related to building, searching, editing, and sorting a 3-column array is appreciated.
Here's some code below where I'm just trying to insert data into the array and spit it out, which obviously doesn't work:
<?php
$id = 5;
$count = 1;
$name = "PlaceName1";
$arrayPlaces = array($id, $count, $name);
echo "5: " . $arrayPlaces[5] . "<br />";
?>
<?php
$id = 5;
$count = 1;
$name = "PlaceName1";
$arrayPlaces = array(
$id => array(
'count' => $count,
'name' => $name
)
);
echo "5: " . $arrayPlace[5]['name'] . "<br />";
?>

Foreach key not incrementing

I'm creating a class book list - there's a master list of books, and a list of the books that the class can be assigned. I need to create an array of the master list, remove the books that have already been assigned to the class, then create a select list of the remaining books. I have most of it working, but I'm stuck on a small part.
First, I load the array (the book_id is the key, the book_title is the value):
while ($master_book = mysql_fetch_array($big_book_list)) {
$b_id = $master_book['master_book_list_id'];
$book_list[$b_id] = $master_book['book_title'];
}
then I remove the class's primary book (it's already been set):
unset($book_list[$primary_book]);
now I load an array of the secondary books that have already been assigned (primary and secondary books come from the same list):
$secondary_query = "select * from class_books cb, master_book_list mbl where class_id ='$class_id' and cb.book_id = mbl.master_book_list_id;";
$secondary_list = mysql_query($secondary_query);
Now I remove the books from $secondary_list from the main list:
while ($secondary_book = mysql_fetch_array($secondary_list)) {
$b_id = $secondary_book['book_id'];
unset($book_list[$b_id]);
}
at this point, print_r shows my array correctly. but this code:
foreach ($book_list as $book2) {
$the_key = key($book_list);
echo $the_key . ' and book2 is '. $book2 . '<br/>';
}
it will iterate the predicted number of times, but the key stays at the same value (which is '2', the first value in the array.
Can anyone see what I'm doing wrong?
You can grab the key from the foreach loop:
foreach ($book_list as $the_key => $book2) {
echo $the_key . ' and book2 is '. $book2 . '<br/>';
}

Categories