How to sort results (by name) of an array? - php

I am using which code which returns taxonomies which match 2 values.
Everything works as it should, but I can't figure out how to order my results. Right now they are displayed in some set order, it might be date not sure. I am trying to get them to display alphabetically (by name)..
My Code from my php template is pasted here http://pastie.org/5083124
The array I am talking about is this
<?php
foreach ( $all_terms as $all_term) {
//print_r($all_terms);
$tax_test = get_option('woo_categories_panel_taxonomies_'.$all_term->taxonomy);
$post_images = array();
$posts_aray = array();
$parent_id = $all_term->term_taxonomy_id;
$term_name = $all_term->name;
$term_parent = $all_term->parent;
$term_slug = $all_term->slug;
$term_id = $all_term->term_id;
$term_link = get_term_link( $all_term, $all_term->taxonomy );
$counter_value = $all_term->count;
?>
<div class="childListings">
<div class="block">
<a href="<?php echo $term_link; ?>">
<?php
$block_counter++;
?>
</a>
<h2><?php echo $term_name ?> <br/><span>(<?php echo $counter_value; ?> Solicitors)</span></h2>
</div><!-- /.block -->
</div><!-- /.child Listings-->
<?php
if ( $block_counter % 6 == 0 ) {
?>
<div class="fix"></div>
<?php
} // End IF Statement
// End IF Statement
?>
<?php
} // End For Loop
?>
I have looked at a few different options with $args and ksort, but I get a bit lost and can't seem to get my results on the frontend of the site to be sorted alphabetically.
Can anyone identify in my code how I would be able to have my results have a sort order?
Thanks

You can avoid bothering to sort in the PHP by sorting slightly earlier, when you're querying the database. This should be faster.
Change:
$all_terms = $wpdb->get_results("SELECT * FROM ipt1y7_term_taxonomy,ipt1y7_terms WHERE ipt1y7_term_taxonomy.parent='{$ex[2]}' AND ipt1y7_term_taxonomy.term_id=ipt1y7_terms.term_id");
...to:
$all_terms = $wpdb->get_results("SELECT * FROM ipt1y7_term_taxonomy,ipt1y7_terms WHERE ipt1y7_term_taxonomy.parent='{$ex[2]}' AND ipt1y7_term_taxonomy.term_id=ipt1y7_terms.term_id ORDER BY ipt1y7_terms.name");
i.e. just add ORDER BY name to your original query. The results will be returned sorted by name with no need for you to do anything further in the PHP, and the sort will happen on the database server. The WordPress database table terms has an index on the name column, so this should be very fast; effectively the data is pre-sorted for you. (See the description of the terms table in the WP database schema.)

Have a look at the examples in http://php.net/manual/en/function.sort.php
$fruits = array("lemon", "orange", "banana", "apple");
sort($fruits);
foreach ($fruits as $key => $val) {
echo "fruits[" . $key . "] = " . $val . "\n";
}
The above example will output:
fruits[0] = apple
fruits[1] = banana
fruits[2] = lemon
fruits[3] = orange

This is possible using usort and your own comparison function:
<?php
/**
* For a bit of testing.
*/
$all_terms = array( );
$names = array( 'foo', 'baz', 'bar', 'qux', 'aaa' );
foreach( $names as $name ) {
$tmp = new stdClass();
$tmp->name = $name;
$all_terms[] = $tmp;
}
/**
* Here, we do the sorting:
*/
usort( $all_terms, function( $a, $b ) {
if( $a->name === $b->name ) {
return 0;
}
return ( $a->name < $b->name ) ? -1 : 1;
});
/**
* And the results:
*/
var_dump( $all_terms );

Related

Trouble creating parent-child relationship between two database tables using php codeigniter

I have two databases tables called article_category and article_case. They are supposed to be combined in a webpage as below:
Article category[title]
Article category[description]
Article case[title]
Article case[contents]
Article case[title]
Article case[contents]
This should repeat itself using foreach until all article categories are populated on the page.
Each article_case will also use foreach, but it has to respect its 'category_id' value which matches the 'id' in article_category .
I'm having trouble filtering the article_case table so that it only picks up rows from its parent 'category_id'.
This is my current php code (which only makes an array of each table):
$this->db->select( "id,title,description" );
$this->db->from( 'article_category' );
$query_article_category = $this->db->get_compiled_select();
$query = $this->db->query( $query_sustainability_category . 'ORDER BY sort ASC ' );
foreach ($query->result_array() as $val) {
$data['article_category_posts'][$val['id']] = $val;}
$this->db->select( "id,category_id,title,contents" );
$this->db->from( 'article_case' );
$query_article_case = $this->db->get_compiled_select();
$query = $this->db->query( $query_article_case);
$data[ 'article_cases' ] = $query->result_array();
And here is my html:
<?php foreach ($article_category_posts as $key => $val) { ?>
<section>
<h2><?php echo $val['title']; ?></h2>
<p><?php echo $val['description']; ?></p>
</section>
<?php foreach ($article_cases as $key => $val) { ?>
<section>
<h3><?php echo $val['title']; ?></h3>
<p><?php echo $val['contents']; ?></p>
</section>
<?php } ?>
<?php } ?>
The current setup will input all article_cases disregarding the category_id.
How can I use foreach while assigning each article_case to their respective article_cateogry?
This would generate unnecessary amount of queries to the DB server.
The rly basic approach would be:
select all categories (as you have) SELECT * FORM a_category
for each category select cases SELECT * FROM a_case WHERE category_id = {$category['id']}
The second one is to combine the categories and cases right in the query with join and adjust the resulting data in php:
SELECT cat.title, cat.description, case.id AS case_id, case.category_id, case.title, case.content
FROM a_case case
INNER JOIN a_category cat ON cat.id = case.category_id
You can use a query to get all the records of article_case with related article_category.
group the query result by category_id.
$this->db->select("cat.title,cat.description,case.category_id,
case.title AS case_title, case.contents" );
$this->db->from( 'article_category cat');
$this->db->join('article_case case','case.category_id=cat.id');
$result=$this->db->get()->result_array();
$result_group = array_group_by($result, 'category_id');
array group by function
function array_group_by(array $array, $key)
{
if (!is_string($key) && !is_int($key) && !is_float($key) && !is_callable($key)) {
trigger_error('array_group_by(): The key should be a string, an integer, or a callback', E_USER_ERROR);
return NULL;
}
$func = (is_callable($key) ? $key : NULL);
$_key = $key;
// Load the new array, splitting by the target key
$grouped = [];
foreach ($array as $value) {
if (is_callable($func)) {
$key = call_user_func($func, $value);
} elseif (is_object($value) && isset($value->{$_key})) {
$key = $value->{$_key};
} elseif (isset($value[$_key])) {
$key = $value[$_key];
} else {
continue;
}
$grouped[$key][] = $value;
}
// Recursively build a nested grouping if more parameters are supplied
// Each grouped array value is grouped according to the next sequential key
if (func_num_args() > 2) {
$args = func_get_args();
foreach ($grouped as $key => $value) {
$params = array_merge([$value], array_slice($args, 2, func_num_args()));
$grouped[$key] = call_user_func_array('array_group_by', $params);
}
}
return $grouped;
}
in view you can show as below
<?php foreach ($result_group as $key => $cat_result) { ?>
<section>
<h2><?php echo $cat_result[0]['title']; ?></h2>
<p><?php echo $cat_result[0]['description']; ?></p>
<div class="box-bd-doted">
</section>
<?php foreach ($cat_result as $key => $val) { ?>
<section>
<h3 style="color:red"><?php echo $val['case_title']; ?></h3>
<p><?php echo $val['contents']; ?></p>
</section>
<?php }
}
?>

Array Reverse and sorting is possible?

I'm trying to sort names in alphabetical order after a reverse array.
It's a code done for ordering last name/first name in right order.
A few bugs, (like with names with middle names) but it works except the sorting.
Here is the code:
<?php
$terms = get_terms( 'pa_artist' );
if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){
echo '<ul class="artists">';
foreach ( $terms as $term ) {
$array = explode(" ", $term->name);
if ($array[3]) {
$array[3] = strtoupper($array[3]);
$array[3] = "<strong>".$array[3]."</strong>";
}
elseif ($array[2]) {
$array[2] = strtoupper($array[2]);
$array[2] = "<strong>".$array[2]."</strong>";
} elseif ($array[1]) {
$array[1] = strtoupper($array[1]);
$array[1] = "<strong>".$array[1]."</strong>";
} else {
$array[0] = strtoupper($array[0]);
$array[0] = "<strong>".$array[0]."</strong>";
}
$rarray = array_reverse($array);
sort($rarray);
echo '<li>' . implode(" ", $rarray) . '</li>';
}
echo '</ul>';
}
For now the names are ordered as if the reverse was never done.
Some examples, at first it showed like this:
Auguste Renoir
Pablo Picasso
Paul Gauguin
After the reverse and If strings, it's like this:
RENOIR Auguste
PICASSO Pablo
GAUGUIN Paul
When i need it:
GAUGUIN Paul
PICASSO Pablo
RENOIR Auguste
I tried every sort fonction, can't make it work… I can't find a way to sort after a reverse array, is it even possible?
It's for a list of names builded with attributes on wordpress/woocommerce.
If I right understand -- it can be done simple like this:
$artists = array(
array('Auguste', '', 'Renoir'),
array('Pablo', '', 'Picasso'),
array('Paul', '', 'Gauguin'),
);
usort($artists, function($a, $b) {
return strcasecmp($a[2], $b[2]);
});
// print_r($artists);
You need to put each individual artist array into a bigger array, and then sort that:
<?php
$terms = get_terms( 'pa_artist' );
$artists = array();
foreach ( $terms as $term ) {
$array = explode(" ", $term->name);
if ($array[3]) {
$array[3] = strtoupper($array[3]);
$array[3] = "<strong>".$array[3]."</strong>";
}
elseif ($array[2]) {
$array[2] = strtoupper($array[2]);
$array[2] = "<strong>".$array[2]."</strong>";
} elseif ($array[1]) {
$array[1] = strtoupper($array[1]);
$array[1] = "<strong>".$array[1]."</strong>";
} else {
$array[0] = strtoupper($array[0]);
$array[0] = "<strong>".$array[0]."</strong>";
}
$rarray = array_reverse($array);
$artists[] = $rarray;
}
usort($artists, function($a, $b) {
return strcasecmp($a[2], $b[2]);
});
// now run your foreach loop again to output the markup you want...

How to output a multidimensional array?

I am new to multidimensional array in php, I read this SO answer and I tried to create my bidimensional array but how do I output it?
$nPost = array("orange, table");
$count_values = array("fruit, forniture");
$final_array = array(array($count_values), array($nPost));
Output would have to be:
Fruits: orange, Forniture: table
Tried
print_r($final_array);
But i got
Array ( [0] => Array ( [0] => Array ( [0] => fruit, forniture ) ) [1] => Array ( [0] => Array ( [0] => orange, table ) ) )
0 fruit, forniture
UPDATE
Real life full code is (explanation in code comments):
<?php
$stack = array();
$userID = array();
$nPost = array();
$blogusers = get_users( 'orderby=nicename&role=author' );
foreach ( $blogusers as $user ) {
// get the language list for each user, and push to array
$descTokens = explode(',', $user->user_description);
$stack = array_merge($stack, $descTokens);
// get the ID for each user, and push to the array
// get the number of posts for each user ID and push to array
$the_user_id = $user->ID;
$numPosts = count_user_posts( $the_user_id );
array_push($userID, $the_user_id);
array_push($nPost, $numPosts);
}
// get the count for each language by counting the duplicate strings
$count_values = array();
foreach ($stack as $a) {
#$count_values[$a]++;
}
$total_duplicates = 0;
foreach ($count_values as $a) {
if($count_values[$a]<=1){
unset($count_values[$a]);
} else{
$total_duplicates += $count_values[$a];
}
}
for($i = 0; $i < count($count_values); $i++){
$final_array[$count_values[$i]] = $nPost[$i];
}
foreach($final_array as $label => $item){
echo "$label: $item, ";
}
?>
// This gives me a correct result but not the n. posts
<ul>
<?php
foreach ($count_values as $key=>$count) {
echo '<li>'.$key.' '.$count.'</li>';
}
?>
</ul>
What we're trying to achieve is:
1 French with 2 posts
3 English with 5 posts
<?php
class User {
public $id;
public $numPosts;
public $languages = array();
public function __construct($id, $numPosts, $lang = array()){
$this->id = $id;
$this->numPosts = $numPosts;
$this->languages = $lang;
}
}
$users = array();
$john = new User(1, 4, array("English", "French"));
$fred = new User(2, 3, array("English"));
$dave = new User(3, 7, array("German", "French", "Spanish"));
$users[] = $john;
$users[] = $fred;
$users[] = $dave;
$langPostCount = array();
$langUserCount = array();
foreach($users as $user){
foreach($user->languages as $lang){
$langUserCount[$lang] += 1; // this is what you already have from $count_values
//$langPostCount[$lang] += $user->numPosts; // can be done here but we'll do another loop
}
}
/*
* the following can be done in the above loop, but you already have that functionality in your code
* just need to do another loop through your languages, tallying the number of posts in that language
* keep in mind this is not entirely accurate as your users have multiple languages. they might have
* one post in english and 4 in french. A better way to do this would be to select the number of posts
* in each language directly from the posts database.
*/
foreach($langUserCount as $lang => $userCount){
foreach($users as $user){
if(in_array($lang, $user->languages)){
$langPostCount[$lang] += $user->numPosts;
}
}
}
echo "<ul>";
foreach($langUserCount as $lang => $userCount){
echo "<li>$userCount $lang with " . $langPostCount[$lang] . " posts.</li>";
}
echo "</ul>";
?>
OUTPUT
2 English with 7 posts.
2 French with 11 posts.
1 German with 7 posts.
1 Spanish with 7 posts.
As you can see, not entirely accurate. You're better off getting post count by querying your posts dataset than by working from the bottom up.
Try This
Adds a new tally to the foreach loop at the top, and changes the ul loop at the end.
$postsPerLanguage = array(); // add this
foreach ( $blogusers as $user ) {
$descTokens = explode(',', $user->user_description);
...
$numPosts = count_user_posts( $the_user_id );
...
// add this loop
foreach($descTokens as $lang){
$postsPerLanguage[$lang] += $numPosts;
}
}
...
<ul>
<?php
foreach ($count_values as $key=>$count) {
echo '<li>'.$key.' '.$count.' with '. $postsPerLanguage[$key] .' posts</li>';
}
?>
</ul>
Your output doesn't need multidimensional array you can achieve it like this:
$final_array = array('Fruits'=> 'orange', 'Furniture'=> 'table')
but for example if you have multiple fruits or furniture you can make something like this:
$final_array = array('Fruits'=> array('orange', 'apple'), 'Furniture'=> array('table', 'sofa'))
and you can access apple like this:
echo $final_array['Fruits'][1];
and for print_r($final_array) we have this:
[Fruits] => (
[0] => orange,
[1] => apple
)
[Furniture] => (
[0] => table,
[1] => sofa
)

Create multidimensional array from keys

Is there a way to create dynamicaly multidimensional array? I have stored in database "path" for each field=>value like that:
field_name : [slideshow][slide][0][title]
field_value : my title
field_name : [slideshow][slide][0][desc]
field_value : my desc
field_name : [slideshow][slide][1][title]
field value : my other title
field_name : [slideshow][slide][1][desc]
field value : my other desc
field_name : [slideshow][settings][duration]
field value : 300
and now I'm trying to figure out how to make it an array again. Obviously there can be lots of fields and complexity so I wanted to avoid some recursions if possible, cause I'm not sure how it will impact performance.
I was playing around with variable variables and trying something like:
$array_name = 'arr';
${$array_name}[slideshow][slide][1][title] = $field->field_value;
print_r($arr);
but this works only if its literally that, and nothing like this works:
${$array_name}.$field->field_name = $field->field_value;
I basically need to store every field as individual row (e.g. for searches in those fields), values can be diffrent types (even serialized arrays), and contain html.
Any advice appreciate.
The basic idea is to split up your field_name string and loop over the parts backward to build up the array. Some recursion is used to merge the arrays, though any performance impact should be negligible.
Example:
// Set up sample data.
$field = new stdClass();
$field->field_name = '[slideshow][slide][0][title]';
$field->field_value = 'my title';
$fields[] = $field;
$field = new stdClass();
$field->field_name = '[slideshow][slide][0][desc]';
$field->field_value = 'my desc';
$fields[] = $field;
$field = new stdClass();
$field->field_name = '[slideshow][slide][1][title]';
$field->field_value = 'my other title';
$fields[] = $field;
$field = new stdClass();
$field->field_name = '[slideshow][slide][1][desc]';
$field->field_value = 'my other desc';
$fields[] = $field;
$field = new stdClass();
$field->field_name = '[slideshow][settings][duration]';
$field->field_value = '300';
$fields[] = $field;
// End sample data.
// array_merge_recursive() doesn't do what we want with numeric keys, so use this
function merge($base, $array) {
foreach ($array as $key => $value) {
if (isset($base[$key]) && is_array($base[$key]) && is_array($value)) {
$base[$key] = merge($base[$key], $value);
} else {
$base[$key] = $value;
}
}
return $base;
}
$result = [];
foreach ($fields as $field) {
$parts = array_reverse(explode('][', trim($field->field_name, '[]')));
$value = $field->field_value;
foreach ($parts as $part) {
$value = [$part => $value];
}
$result = merge($result, $value);
}
print_r($result);
Output:
Array
(
[slideshow] => Array
(
[slide] => Array
(
[0] => Array
(
[title] => my title
[desc] => my desc
)
[1] => Array
(
[title] => my other title
[desc] => my other desc
)
)
[settings] => Array
(
[duration] => 300
)
)
)
You could try something like this.
$cars = array
(
array("Volvo",22,18),
array("BMW",15,13),
array("Saab",5,2),
array("Land Rover",17,15)
);
<?php
echo $cars[0][0].": In stock: ".$cars[0][1].", sold: ".$cars[0][2].".<br>";
echo $cars[1][0].": In stock: ".$cars[1][1].", sold: ".$cars[1][2].".<br>";
echo $cars[2][0].": In stock: ".$cars[2][1].", sold: ".$cars[2][2].".<br>";
echo $cars[3][0].": In stock: ".$cars[3][1].", sold: ".$cars[3][2].".<br>";
?>
<?php
for ($row = 0; $row < 4; $row++) {
echo "<p><b>Row number $row</b></p>";
echo "<ul>";
for ($col = 0; $col < 3; $col++) {
echo "<li>".$cars[$row][$col]."</li>";
}
echo "</ul>";
}
?>

Include "required questions" in a random selection

I'm selecting a set of random questions without any duplicates using the following:
<?php
$amount = get_field('select_number_of_questions');
$repeater = get_field("step_by_step_test");
shuffle($repeater);
$repeater_limit = array_slice($repeater,0,$amount);
foreach($repeater_limit as $repeater_row) {
echo "<p>".$repeater_row['question']."</p>";
$rows = $repeater_row['answer_options'];
foreach($rows as $row) {
echo $row['answer']."<br />";
}
}
?>
Each question has a field: get_field('required_question'); that has a yes/no dropdown. The questions that have yes selected ALWAYS have to be incorporated into the loop above.
E.g The test has 20 questions to select from, 10 will be selected at random. Within the 20 questions, there are 2 required questions (i.e these will always be selected). So it will need to grab the 2 required questions and select 8 other random questions.
How can I include the required questions within the random selection?
The Question doesn't state it, but all suggests this is an Advanced Custom Fields set up using the Repeater Add-on.
In that case, this is the test configuration I've done:
Note that here I'm using $repeater_row['title'] instead of the OP's $repeater_row['question']. Also, I removed the answer_options part. See comments for details:
// Get fields
$amount = get_field( 'select_number_of_questions' );
$repeater = get_field( 'step_by_step_test' );
// Auxiliary arrays to separate fields by Field Name
$not_enabled = array();
$enabled = array();
// Separate
foreach( $repeater as $field )
{
if( 'no' == $field['enabled'] )
$not_enabled[] = $field;
else
$enabled[] = $field;
}
// Discount the enabled from the the total amount
$amount = (int)$amount - count( $enabled );
// Shuffle before slicing
shuffle( $not_enabled );
$repeater_limit = array_slice( $not_enabled, 0, $amount );
// Add enabled fields and shuffle again
$final_array = array_merge( $repeater_limit, $enabled );
shuffle( $final_array );
foreach( $final_array as $repeater_row ) {
echo "<p>" . $repeater_row['title'] . "</p>";
}
First you need to filter out the required questions like so:
$all_questions = get_field("step_by_step_test");
$required = $optional = array();
foreach($all_questions as $question) {
if( $a['required_question']) $required[] = $question;
else $optional[] = $question;
}
$amount = get_field("select_number_of_questions")-count($required);
shuffle($optional);
$final = array_merge($required,array_slice($optional,0,$amount));
foreach($final as $repeater_row) {
...
}
Hope I helped you again :p

Categories