Here's my recursive function:
function get_descendants($category_id)
{
global $descendants;
$categories = get_ancestors($category_id);
echo "get_ancestors($category_id);<br>";
// print_r($categories);exit;
if (!is_array($categories))
return;
foreach ($categories as $category)
{
$descendants[] = $category['id'];
// Look for other leafs
get_descendants($category['id']);
}
return $descendants;
}
function get_ancestors($parent_id)
{
global $db, $locale;
$result = $db->query("
SELECT ...
AND parent_id = $parent_id
");
$categories = $result->fetch_all(MYSQLI_ASSOC);
if ($result->num_rows > 0)
{
foreach ($categories as $category)
$data[] = $category;
return $data;
}
}
The problem it's making the same call twice. So this is the result of running the code:
get_ancestors(8);
get_ancestors(1);
get_ancestors(2);
get_ancestors(4);
get_ancestors(5);
get_ancestors(3);
get_ancestors(6);
get_ancestors(8);
get_ancestors(1);
get_ancestors(2);
get_ancestors(4);
get_ancestors(5);
get_ancestors(3);
get_ancestors(6);
Where I should only see:
get_ancestors(8);
get_ancestors(1);
get_ancestors(2);
get_ancestors(4);
get_ancestors(5);
get_ancestors(3);
get_ancestors(6);
What's wrong?
Thanks.
The problem is that you don't want $descendants to be global.
You are sharing one variable across all the recursive calls. It really needs to be local for the logic you're using to be correct.
Instead of global $descendants; do $descendants = array();.
Related
I'm having troubles with my function and how to retrieve the data. Here is what i got.
public function getImages()
{
$array = array();
//Test query
$query = $this->connect()->query("SELECT * from user");
while ($row = $query->fetch()) {
$array[] = $row;
return $array;
}
}
Now I'm calling this function but i can not use foreach to access the array.
include "header.html";
include "autoload.php";
spl_autoload_register('my_autoloader');
$users = new User;
$users->getImages();
foreach ($users as $value) {
echo $value["username"];
}
What am I doing wrong? I'm only getting one result but there are many in my database. Or if i call the $array in foreach it says undefined.
A couple things. First, your function is only ever returning an array with one element in it. If you want to finish populating the array, don't return until after the loop:
while ($row = $query->fetch()) {
$array[] = $row;
}
return $array;
And second, you're trying to iterate over the object which has the function, not the value returned from the function. Get the return value and iterate over that:
$userDAO = new User;
$users = $userDAO->getImages();
foreach ($users as $value) {
echo $value["username"];
}
You just need to put the return statement out of the while loop.
public function getImages() {
$array = array(); //Test query
$query = $this->connect()->query("SELECT * from user");
while ($row = $query->fetch()) {
$array[] = $row;
}
return $array;
}
public function getCats($model){
$levels = array();
$tree = array();
$cur = array();
foreach($model as $rows){
$cur = &$levels[$rows['id']];
$cur['parent_id'] = $rows['parent_id'];
$cur['title'] = $rows['title'];
if($rows['parent_id'] == 0){
$tree[$rows['id']] = &$cur;
}
else{
$levels[$rows['parent_id']]['children'][$rows['id']] = &$cur;
}
}
return $tree;
}
public function getTree($arr){
echo '<ul>';
foreach($arr as $k=>$v){
echo '<li>';
echo ''.$v['title'].'';
if(!empty($v['children'])){
echo getTree($v['children']);
}
echo '</li>';
}
echo '</ul>';
}
public function allCats($pos) {
$model = Category::model()->findallBySql('SELECT id, parent_id, title FROM {{category}} WHERE position="'.$pos.'"');
$cats = getCats($model);
echo getTree($cats);
}
I wonder, why these functions don`t work in model file(inside class)?
If i use them inside controllers, they work fine, and if i paste them inside model(class) file, they stop working(as if they are becoming invisible). The last function causing the above two functions.
You are calling getCats($model) which would be a global function. But it's defined as a class function/method. Call it $this->getCats($model) and $this->getTree($cats) and it should work.
I couldn't find solution for this and I don't have much time for this. So what I want is to make function that I give category ID and it returns all ID's of categories which are it's child categories.
function getID($var) {
$categories = array();
function getChildren($id) {
$result = mysql_query("SELECT * FROM categories WHERE parentID = '$id'");
echo "<ul>";
while ($row = mysql_fetch_array($result)) {
echo "<li><a>{$row['ID']}</a>";
$categories[] = $row['ID'];
getChildren($row['ID']);
echo "</li>";
}
echo "</ul>";
}
getChildren($var);
return $categories;
}
I wan't to store everything in $categories array. $var is category ID which I give to function. When I call this function it prints list of exactly what I want't but array is empty.
It seems you have a scope problem. Try this:
function getChildren(&$categories, $id) {
$result = mysql_query("SELECT * FROM categories WHERE parentID = '$id'");
echo "<ul>";
while ($row = mysql_fetch_array($result)) {
echo "<li><a>{$row['ID']}</a>";
$categories[] = $row['ID'];
getChildren($categories, $row['ID']);
echo "</li>";
}
echo "</ul>";
}
function getID($var) {
$categories = array();
getChildren($categories, $var);
return $categories;
}
Here is the PHP reference page describing how to pass by reference instead of by value. Basically it says that any function parameter which has a & in front of it will be passed by reference instead of by value.
$categories only exists in the scope of get children. You could either pass it by reference as second parameter or create get children as a closure with use (&$categories)
function getChildren($id, $categories)
should work.
The array was out of scope, so the function didn't touch the one you are returning. It created a new local $categories inside the function.
I got this problem trying to echo out a big array.
print_r looks like this:
http://codepaste.net/5js97a
There's no problem echoing out the first 2 rows like this in a foreach loop:
$item['name'], but for the rest of them deeper inside the array, I just get an error.
Thanks!
Code:
function categories($parent = NULL) {
$query = $this->db->where('parent_id', $parent)->get('categories');
$results = $query->result_array();
foreach($results as $result) {
$child_array = Forummodel::categories($result['id']);
if(sizeof($child_array) == 0) {
array_push($results, $result['name']);
} else {
array_push($results, array($result['name'], $child_array));
}
}
return $results;
}
Im also using codeigniter
You are iterating on an increasing array. Here is your code:
function categories($parent = NULL) {
$query = $this ->db ->where('parent_id', $parent) ->get('categories');
$results = $query->result_array();
foreach($results as $result) {
$child_array = Forummodel::categories($result['id']);
if(sizeof($child_array) == 0) {
array_push($results, $result['name']);
} else {
array_push($results, array($result['name'], $child_array));
}
}
return $results;
}
The foreach is iterating down the array $results and you are adding to it with each loop, plus, by the time you hit an iteration where $result doesn't contain 'id' or 'name' you are probably getting the error. You might want to put the child arrays into another array and merge them after the foreach loop if you still want to do that.
I've written this piece of code, which outputs the profile_display_fields for the $USER:
$appearance = profile_display_fields($USER->id);
if (empty($appearance)) {
//Do nothing
} else {
foreach ($appearance as $c) {
$custom .= '<a href=\''.$CFG->wwwroot.'/course/view.php?id='.$c->id.'\'>'.$c->fullname.'</a>';
}
}
Here is the function I'm using:
function profile_display_fields($userid) {
global $CFG, $USER;
if ($categories = get_records_select('user_info_category', '', 'sortorder ASC')) {
foreach ($categories as $category) {
if ($fields = get_records_select('user_info_field', "categoryid=$category->id", 'sortorder ASC')) {
foreach ($fields as $field) {
require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
$newfield = 'profile_field_'.$field->datatype;
$formfield = new $newfield($field->id, $userid);
if ($formfield->is_visible() and !$formfield->is_empty()) {
print_row(s($formfield->field->name.':'), $formfield->display_data());
}
}
}
}
}
}
What I'm looking to do is try some var_dumps to output the correct data.
However can anyone help me identify the variables?
In your function you are not returning any value but above that in your code, you have assigned a variable to this function:
$appearance = profile_display_fields($USER->id);
You need to return some variable/data from the function and that is the one to be var dumped.
I suppose you are using the print_row to print the data, not returning the response to be used out of the function.