Recursive function return null value [duplicate] - php

This question already has answers here:
How to use return inside a recursive function in PHP
(4 answers)
Closed 9 months ago.
I have Used recursive function to get the category full path like Access Control/CARDS/FOBS from above table structure but my recursive function return null value.
function xyz($id,$parent) {
if($parent == '0') {
//my code working fine
//return
}
else
{
$catid = $id; //here 25 coming
$cat_array = array();
$category_array = $this->Recursive($catid,$cat_array);
//echo $category_array;exit; getting Null result
return $category_array ;
}
}
function Recursive($catid,$cat_array)
{
$sql = mysql_query("Select bg_category_id,parent_id,title from categories_list
Where bg_category_id = '".$catid."'");
$result = mysql_fetch_array($sql);
array_push($cat_array,$result['title']);
if($result['parent_id'] != '0') {
$this->Recursive($result['parent_id'],$cat_array) ;
} else {
if(count($cat_array) > 0){
$k = implode("/",$cat_array);
}
//echo $k;exit; getting desired result FOBS/CARDS/Access Control
return $k;
}
}

You need to return the recursive function when you recurse, otherwise it will return nothing.
if($result['parent_id'] != '0') {
return $this->Recursive($result['parent_id'],$category_array) ;
}

Related

Codeigniter SQL query return single value [duplicate]

This question already has answers here:
getting the value of the single field output using the codeigniter active record
(5 answers)
Closed 2 years ago.
I am working with CodeIgniter and I want to get the highest ID out of a table. This i realize with a function in the Model. But I don't get the result, which is a single value, as value back.
Code:
function get_highest_answer_id(){
$this->db->query('SELECT MAX(id) AS answerid FROM pa_it_answer;');
if ($query = $this->db->get()) {
if ($query->num_rows() > 0) {
return $query->result();
} else {
return array();
}
} else {
return FALSE;
}
}
How do I have to Change the code that when I call this function in my Controller I get the single value?
Below code is works fine for me.
$MAXID = 0;
$row = $this->db->query('SELECT MAX(id) AS answerid FROM pa_it_answer')->row();
if ($row) {
$MAXID = $row->answerid;
}
Change your query in codeigniter like this
function get_highest_answer_id(){
$this->db->select('MAX(id) AS answerid');
if ($query = $this->db->get('pa_it_answer')) {
if ($query->num_rows() > 0) {
return $query->result();
} else {
return array();
}
} else {
return FALSE;
}
}
You just have to simplify your method with row()
function get_highest_answer_id(){
$record = $this->db->query('SELECT MAX(id) AS answerid FROM pa_it_answer;')->row();
if ($record) {
return $record->answerid;
}
else {
return FALSE;
}
}
Try this:
function get_highest_answer_id(){
$this->db->query('SELECT MAX(id) AS answerid FROM pa_it_answer;');
if ($query = $this->db->get()) {
if ($query->num_rows() > 0) {
return $query->row(); // here!!!
} else {
return array();
}
} else {
return FALSE;
}
}
I recommended use the querybuilder of CI (EDITED)
$this->db->select_max('id', 'answerid');
$query = $this->db->get('pa_it_answer');
var_dump( $query );
var_dump( $query->answerid );
die();

While Loop Through An Array

Creating a block builder that loops through blocks pulled form database in order.
if( loop_blocks()) {
while( loop_blocks()) {
if( have_block('standard-content-block')) {
echo 'standard-content-block';
}
elseif( have_block('executive-intro-block')) {
echo 'executive intro block';
}
}
}
My function loop_blocks pulls the blocks from the database in order and set the array as a global variable:
function loop_blocks() {
global $db;
$page_id = get_page_id();
$GLOBALS['loop_position'] = 0;
$loop_position = $GLOBALS['loop_position'];
$stm = $db->prepare("SELECT * FROM page_blocks WHERE page_id = :id ORDER BY `block_order` ASC");
$stm->execute(array(':id' => $page_id));
$res = $stm->fetchAll();
$GLOBALS['block_loop'] = $res;
if(!$res) {
return false;
} elseif(!$GLOBALS['block_loop'][$loop_position]) {
return false;
} else {
return true;
}
}
The function have_block gets the current loop position and determines whether the name as determined, exists in the array and increases the loop position:
function have_block($block_name) {
$loop_position = $GLOBALS['loop_position'];
if(!$GLOBALS['block_loop'][$loop_position]) {
return false;
} elseif(!$GLOBALS['block_loop'][$loop_position][block_name] = $block_name) {
return false;
} else {
$GLOBALS['loop_position'] = $loop_position+1;
return true;
}
}
This returns an infinite loop however and I can't figure out a way to move the while loop onto the next step?
EDIT I'm using a while loop because the function have_block will set-up a global variable for the current block id. This will then be used within a function called the_element. Such as:
if( loop_blocks()) {
while( loop_blocks()) {
if( have_block('standard-content-block')) {
the_element('heading');
}
}
}
If I don't use the function have_block to set this up, then I'd need to pass the block id from the foreach loop into every element as a second argument.
I fixed this by, as #Jim, noted I was re-setting the loop_position within loop_blocks() which was why the while loop was repeating infinitely. It was then a simple case of an error when typing:
} elseif(!$GLOBALS['block_loop'][$loop_position][block_name] = $block_name) {
return false;
Should have been:
} elseif($GLOBALS['block_loop'][$loop_position][block_name] != $block_name) {
return false;
Note that I had the exclamation point in the incorrect place.
This now works perfectly as I need.

Return a value properly from a tree with recursion [duplicate]

This question already has answers here:
How to use return inside a recursive function in PHP
(4 answers)
Closed 9 months ago.
This is my code
https://eval.in/157357
You can use a json parser if you wanna see the tree. This tree is returned by the Magento SOAP Api.
http://www.magentocommerce.com/api/soap/catalog/catalogCategory/catalog_category.tree.html
<?php
function getCategoryId($tree,$needle,&$val)
{
if(!empty($tree["name"]) && $tree["name"] === $needle)
{
$val = $tree["category_id"];
return $tree["category_id"];
}
else
{
if(isset($tree["children"]["category_id"]))
{
getCategoryId($tree["children"],$needle,$val);
}
else
{
foreach ($tree["children"] as $child) {
getCategoryId($child,$needle,$val);
}
}
}
}
function main()
{
$testjson = <<<EOL
{"category_id":"1","parent_id":"0","name":"Root Catalog","is_active":null,"position":"0","level":"0","children":[{"category_id":"2","parent_id":"1","name":"catroot","is_active":"1","position":"1","level":"1","children":[{"category_id":"3","parent_id":"2","name":"cat1","is_active":"1","position":"1","level":"2","children":[{"category_id":"7","parent_id":"3","name":"cat11","is_active":"0","position":"1","level":"3","children":[]},{"category_id":"8","parent_id":"3","name":"cat12","is_active":"0","position":"2","level":"3","children":[]}]},{"category_id":"9","parent_id":"2","name":"cat2","is_active":"0","position":"2","level":"2","children":[{"category_id":"11","parent_id":"9","name":"cat21","is_active":"0","position":"1","level":"3","children":[{"category_id":"12","parent_id":"11","name":"cat211","is_active":"0","position":"1","level":"4","children":[]},{"category_id":"13","parent_id":"11","name":"cat212","is_active":"0","position":"2","level":"4","children":[]}]}]},{"category_id":"10","parent_id":"2","name":"cat3","is_active":"0","position":"3","level":"2","children":[{"category_id":"14","parent_id":"10","name":"cat31","is_active":"0","position":"1","level":"3","children":[]},{"category_id":"15","parent_id":"10","name":"cat32","is_active":"0","position":"2","level":"3","children":[{"category_id":"16","parent_id":"15","name":"cat321","is_active":"0","position":"1","level":"4","children":[{"category_id":"17","parent_id":"16","name":"cat3211","is_active":"0","position":"1","level":"5","children":[]}]}]}]}]}]}
EOL;
$result = (json_decode($testjson,true));
$res = getCategoryId($result,"cat211",$val);
var_dump($res);
var_dump($val);
}
main();
?>
Why my function getCategoryId return NULL ? I don't want use the reference $val that was juste for testing.
You need to return the result from the recursive calls:
<?php
function getCategoryId($tree,$needle,&$val)
{
if(!empty($tree["name"]) && $tree["name"] === $needle)
{
//var_dump($tree);
//var_dump($tree["category_id"]);
$val = $tree["category_id"];
return $tree["category_id"];
}
else
{
if(isset($tree["children"]["category_id"]))
{
return getCategoryId($tree["children"],$needle,$val);
}
else
{
foreach ($tree["children"] as $child) {
$return = getCategoryId($child,$needle,$val);
if($return){
return $return;
}
}
}
}
}
function main()
{
$testjson = <<<EOL
{"category_id":"1","parent_id":"0","name":"Root Catalog","is_active":null,"position":"0","level":"0","children":[{"category_id":"2","parent_id":"1","name":"catroot","is_active":"1","position":"1","level":"1","children":[{"category_id":"3","parent_id":"2","name":"cat1","is_active":"1","position":"1","level":"2","children":[{"category_id":"7","parent_id":"3","name":"cat11","is_active":"0","position":"1","level":"3","children":[]},{"category_id":"8","parent_id":"3","name":"cat12","is_active":"0","position":"2","level":"3","children":[]}]},{"category_id":"9","parent_id":"2","name":"cat2","is_active":"0","position":"2","level":"2","children":[{"category_id":"11","parent_id":"9","name":"cat21","is_active":"0","position":"1","level":"3","children":[{"category_id":"12","parent_id":"11","name":"cat211","is_active":"0","position":"1","level":"4","children":[]},{"category_id":"13","parent_id":"11","name":"cat212","is_active":"0","position":"2","level":"4","children":[]}]}]},{"category_id":"10","parent_id":"2","name":"cat3","is_active":"0","position":"3","level":"2","children":[{"category_id":"14","parent_id":"10","name":"cat31","is_active":"0","position":"1","level":"3","children":[]},{"category_id":"15","parent_id":"10","name":"cat32","is_active":"0","position":"2","level":"3","children":[{"category_id":"16","parent_id":"15","name":"cat321","is_active":"0","position":"1","level":"4","children":[{"category_id":"17","parent_id":"16","name":"cat3211","is_active":"0","position":"1","level":"5","children":[]}]}]}]}]}]}
EOL;
$result = (json_decode($testjson,true));
$res = getCategoryId($result,"cat211",$val);
var_dump($res);
var_dump($val);
}
main();
?>

PHP - putting if statement coding inside of a variable

I am trying to get an if statement to dynamically code itself based on user input. So the if statement code is being inserted into a variable ($if_statement_variable), like this:
$if_statement_variable = "if (";
$price = trim($_GET["Price"]);
if (!empty($price)) {
$if_statement_variable .= " $Product->price < $price ";
}
$product_name = trim($_GET["Product_name"]);
if (!empty($product_name)) {
$if_statement_variable .= " && $Product->$product_name == 'product_name_string' ";
}
// plus many more if GET requests
$if_statement_variable .= ") ";
Then results from an XML file will be displayed based on user values submitted and the $if_statement_variable.
$XMLproducts = simplexml_load_file("products.xml");
foreach($XMLproducts->product as $Product) {
echo $if_statement_variable; // Here is where the problem is
{ // opening bracket for $variable_if_statement
echo $Product->$product_name; // products displayed based on if statement code in $if_statement_variable
} //closing bracket for $variable_if_statement
}
The echo $if_statement_variable above correctly displays $price from this variable string, but does NOT display $Product->price. Assuming $price had a value of 1000, the output is if ( == 1000 ). How can I get $Product->price to correctly insert itself into the $if_statement_variable so that it displays the $Product->price values from the XML file?
If you're trying to generate a boolean value dynamically, based on some complicated logic, just assign the true/false value to a variable, (say, $booleanValue) and then do if($booleanValue){}
Something like:
$price = trim($_GET['price']);
$product_name = trim($_GET['Product_name']);
if(!empty($price)){
$booleanValue = ($Product->price < $price);
}
if(!empty($productName)){
$booleanValue = ($booleanValue && $Product->$product_name == 'product_name_string')
}
if($booleanValue){
echo $Product->$product_name;
}
In other words, create a variable to hold the actual boolean value, not a string to hold an expression that will evaluate to a boolean value.
Do not build PHP source as a string. In this case callables are a better solution. A callable is a function inside a variable. In PHP this might be an function name, and array with an object and a method name, an anonymous function or an object implementing invoke.
Here is an example for anonymous functions:
function getCondition($parameters) {
$conditions = [];
if (isset($parameters['Price']) && trim($parameters['Price']) != '') {
$price = trim($parameters['price']);
$conditions[] = function($product) use ($price) {
return $product->price < $price;
}
}
if (isset($parameters['Product_name']) && trim($parameters['Product_name']) != '') {
$productName = trim($parameters['Product_name']);
$conditions[] = function($product) use ($productName) {
return $product->product_name == $productName;
}
}
return function($product) use ($conditions) {
foreach ($conditions as $condition) {
if (!$condition($product)) {
return FALSE;
}
}
return TRUE;
}
}
$condition = getConditon($_GET);
if ($condition($product)) {
...
}
It is important that each function can be called the same way. So if you call the condition function you not need to know, which condition it is. In the example above you can imagine that the getCondition() function can get really complex really fast if you add additional conditions.
If you encapsulate the conditions into classes, the usage becomes more readable:
$condition = new \YourCompany\Product\Conditions\Group(
new \YourCompany\Product\Conditions\PriceMaximum($_GET, 'Price'),
new \YourCompany\Product\Conditions\Name($_GET, 'Product_name')
);
if ($condition($product)) {
...
}
This way you separate the actual condition logic from the from the use. The source of all classes is some more then the anonymous function variant. But you you can put each class in it's own file and use them in any combination you need.
The classes need to implement __invoke().
class Group {
private $_conditions = array();
public function __construct() {
$this->_conditions = func_get_args();
}
public function __invoke($product) {
foreach ($this->_conditions as $condition) {
if (!$condition($product)) {
return FALSE;
}
}
return TRUE;
}
}
class Name {
private $_productName = NULL;
public function __construct($parameters, $name) {
if (isset($parameters[$name]) && trim($parameters[$name]) > 0) {
$this->_productName = trim($parameters[$name]);
}
}
public function __invoke($product) {
return (
NULL === $this->_productName ||
$product->product_name == $this->_productName
);
}
}
class PriceMaximum {
private $_maximum = NULL;
public function __construct($parameters, $name) {
if (isset($parameters[$name]) && trim($parameters[$name]) > 0) {
$this->_maximum = trim($parameters[$name]);
}
}
public function __invoke($product) {
return (
NULL === $this->_maximum ||
$product->price < $this->_maximum
);
}
}
This concept can even be used together with an anonymous function:
$condition = new \YourCompany\Product\Conditions\Group(
new \YourCompany\Product\Conditions\PriceMaximum($_GET, 'Price'),
new \YourCompany\Product\Conditions\Name($_GET, 'Product_name'),
function ($product) {
return $product->category == 'food';
}
);

How to return true with a recursive function [duplicate]

This question already has answers here:
How to use return inside a recursive function in PHP
(4 answers)
Closed 9 months ago.
I have below recursive function in my model with CI, working.
In my controller, i need to check if function worked correctly like:
if($this->my_model->level_corrector($id_page,$level)) echo 'Levels are corrected';
But as the function always return false (to end the recursion), I couldn't figure out how to achieve my goal.
function level_corrector($id_page_of_parent,$level_of_parent)
{
$sql = "
SELECT id_page, id_parent, level
FROM page
WHERE id_parent = $id_page_of_parent";
$query = $this->db->query($sql);
if($query->num_rows() > 0)
{
$result = $query->result_array();
foreach ($result as $r)
{
$data = array('level'=>$level_of_parent+1);
$this->db->where('id_page', $r['id_page']);
if($this->db->update('page', $data))
{
$this->level_corrector($r['id_page'],$level_of_parent+1);
}
else
{
// let me handle it what to do
return false;
}
}
}
else
{ // again let me handle it to log a message or sth
return false; // (2)
}
return true; // (3) means it all gone right, so I can move on.
}
You need to do two things:
If there is an error, return false. Otherwise, at the end of the function, return true by default
If, when you call the function recursively, an error occurred, return false.
Edit: Based on your answers to my questions in the comments, what you want is this:
function level_corrector($id_page_of_parent,$level_of_parent)
{
$sql = "
SELECT id_page, id_parent, level
FROM page
WHERE id_parent = $id_page_of_parent";
$query = $this->db->query($sql);
if($query->num_rows() > 0)
{
$result = $query->result_array();
foreach ($result as $r)
{
$data = array('level'=>$level_of_parent+1);
$this->db->where('id_page', $r['id_page']);
if($this->db->update('page', $data))
{
// no error. return error code from recursive call
return $this->level_corrector($r['id_page'],$level_of_parent+1);
}
else
{
// error occured
return false;
}
}
}
// $query->num_rows <= 0. This is not an error, so return true:
return true;
}

Categories