Need some help to determine the amount of recursive calls in PHP - php

I've got a, I think fairly easy question, but this is bugging me for a while now. So I figured, maybe I can get some help here.
Since recursive functions are always a bit tricky, and sometimes a bit unclear to me, I keep struggling to create a nice working solution to get my menudata.
In one of my classes I have this function, which gives me all menu-items recursively.
The thing I want is to determine at which recursion level a certain object was retrieved so I can create a nicely looking HTML output with indents for the levels of nesting.
public function GetObjectList($parentID = 0, $objectlist = null)
{
if(is_null($objectlist))
{
$objectlist = new ObjectList("Model_Navigation");
}
$query = MySQL::Query("SELECT * FROM `Navigation` WHERE `WebsiteID` = ".SITE_ID. " AND `LanguageID` = ".LANG_ID." AND `ParentID` = ".$parentID);
while($result = MySQL::FetchAssoc($query))
{
$object = new Model_Navigation();
$object->ID = $result["ID"];
$object->WebsiteID = $result["WebsiteID"];
$object->LanguageID = $result["LanguageID"];
$object->ParentID = $result["ParentID"];
$object->Name = $result["Name"];
$object->Page = Model_Page::GetObjectByID($result["PageID"]);
$object->ExternalURL = $result["ExternalURL"];
$object->Index = $result["Index"];
$object->Level = [here lies my problem];
$objectlist->Add($object);
self::GetObjectList($object->ID, $objectlist);
}
return $objectlist;
}

public function GetObjectList($parentID = 0, $objectlist = null, $level = 1)
{
if(is_null($objectlist))
{
$objectlist = new ObjectList("Model_Navigation");
}
$query = MySQL::Query("SELECT * FROM `Navigation` WHERE `WebsiteID` = ".SITE_ID. " AND `LanguageID` = ".LANG_ID." AND `ParentID` = ".$parentID);
while($result = MySQL::FetchAssoc($query))
{
$object = new Model_Navigation();
$object->ID = $result["ID"];
$object->WebsiteID = $result["WebsiteID"];
$object->LanguageID = $result["LanguageID"];
$object->ParentID = $result["ParentID"];
$object->Name = $result["Name"];
$object->Page = Model_Page::GetObjectByID($result["PageID"]);
$object->ExternalURL = $result["ExternalURL"];
$object->Index = $result["Index"];
$object->Level = $level;
$objectlist->Add($object);
self::GetObjectList($object->ID, $objectlist, $level+1);
}
return $objectlist;
}

Why don't you just add a parameter to the function call that stores the number of calls. At the first call just make that 0, increment the value inside the function and use it in the recursive call.

Related

Iterating over an XML file in PHP

I'm using Laravel to parse an XML file and store it into the DB. Now, it's probably some sort of a stupid mistake I can't put my finger on, but I would really appreciate if someone could check the code and the weird results I'm getting.
The XML has a deep and complex structure, here's a little piece from that's bugging me:
I'm dumping the $nizXMLsp in the end to see what's inside the array of objects:
public function upload(){
$dom = new DomDocument();
$nizBaza = DB::table('offers')->orderBy('id', 'DESC')->first();
$nizXML = array();
$objekat = new stdClass();
$dom->load("storage/X_Lista.xml");
$domXpath = new DomXPath($dom);
$upit = $domXpath->query('//offer');
foreach($upit as $of){
$objekat->Time = $of->getAttribute('Time');
$objekat->Date = $of->getAttribute('Date');
$objekat->betRound = $of->getAttribute('betRound');
$objekat->timestamp = $of->getAttribute('timestamp');
array_push($nizXML, $objekat);
}
if(is_null($nizBaza) or $nizBaza->id != $nizXML[0]->betRound) {
$kolo = new Offer();
$kolo->id = $objekat->betRound;
$kolo->ts = $objekat->Date . " " . $objekat->Time;
$kolo->posix = $objekat->timestamp;
$kolo->save();
//
$nizBaza = DB::table('sportovi')->get();
$nizXMLsp = array(); $objekat_sp = new stdClass();
foreach($dom->getElementsByTagName('sport') as $k=>$v){
$objekat_sp->id = $v->getAttribute('id');
$objekat_sp->name = $v->getAttribute('name');
$objekat_sp->betRound = $v->parentNode->getAttribute('betRound');
$nizXMLsp[$k] = $objekat_sp;
}
}
elseif($nizBaza->id == $nizXML[0]->betRound){
echo 'break1';
exit;
}
else {
echo 'break2';
exit;
}
return var_dump($nizXMLsp);
}
Now, what I see in the end is this:
instead of 4 objects with different sets of data, I get 4 objects with same set of data (all of the data comes from the last node). What could it be?
Possibly a very simple adjustment. Just reset $objekat_sp inside the loop:
foreach($dom->getElementsByTagName('sport') as $k=>$v){
$objekat_sp = "";
$objekat_sp->id = $v->getAttribute('id');
$objekat_sp->name = $v->getAttribute('name');
$objekat_sp->betRound = $v->parentNode->getAttribute('betRound');
$nizXMLsp[$k] = $objekat_sp;
}
Move
$objekat = new stdClass();
and
$objekat_sp = new stdClass();
inside their respective foreach loops.
Right now you're pushing the same object (after modifying its properties) into the array multiple times.

Calling a variable from another script

im trying assign values to my variables in ascript by calling a function and variables from another script, but currently im getting errors saying
Undefined property: stdClass::$Boys in
Undefined property: stdClass::$Girls in
im calling a function in a script called report.php from my script
report.php
public function projectReport($ID){
$get_con = $this->getConnection();
$result = mysql_query($query, $get_con);
$rep = new stdClass();
if(false !== $result){
$multis = array();
while($row = mysql_fetch_array($result, MYSQL_ASSOC)){
$count = new stdClass();
$count->Boys = (int)$row['males'];
$count->Girls = (int)$row['females'];
$multis[] = $count;
}
$rep->multiples = $multis;
}
return $rep;
}
function body of my script
$report = new Report();
$log = $report->projectReport($ID);
if($log != false){
$Boys = $log->Boys;
$Girls = $log->Girls;
print_r($Boys);
print_r($Girls);
}
return $log;
your $log can never be false so you don't need to check that. Alhtough multiples attribute might be missing.
Try this:
$report = new Report();
$log = $report->projectReport($ID);
if(property_exists($log, 'multiples')){ //check if multiples attribute exists
foreach ($log->multiples as $m) //walk through every multiples record
{
$Boys = $m->Boys; //get Boys and Girls attributes values and print them
$Girls = $m->Girls;
print_r($Boys);
print_r($Girls);
}
}
I'm pretty sure that's not what you wanna achieve, but that how it should work based on what you've got so far.

Check if property exists, if it does build off of the property

I have the following PHP code:
$alignments = new StdClass();
if ($query->num_rows > 0)
{
foreach($query->result() as $row){
$alignments->{$row->table_id} = new StdClass();
$alignments->{$row->table_id}->table_id = isset($row->table_id)?$row->table_id:NULL;
$alignments->{$row->table_id}->title = isset($row->title)?$row->title:NULL;
$alignments->{$row->table_id}->url = isset($row->url)?$row->url:NULL;
$alignments->{$row->table_id}->state_id = isset($row->state_id)?$row->state_id:NULL;
$alignments->{$row->table_id}->cross_discipline_alignment = isset($row->cross_discipline_alignment)?$row->cross_discipline_alignment:NULL;
$alignments->{$row->table_id}->common_core = isset($row->common_core)?$row->common_core:NULL;
$alignments->{$row->table_id}->grade_level = isset($row->grade_level)?$row->grade_level:NULL;
$alignments->{$row->table_id}->indicators = new StdClass();
$alignments->{$row->table_id}->indicators->{$row->indicator_id} = new StdClass();
$alignments->{$row->table_id}->indicators->{$row->indicator_id}->indicator_id = isset($row->indicator_id)?$row->indicator_id:NULL;
$alignments->{$row->table_id}->indicators->{$row->indicator_id}->indicator = isset($row->indicator)?$row->indicator:NULL;
$alignments->{$row->table_id}->indicators->{$row->indicator_id}->key = isset($row->key)?$row->key:NULL;
$alignments->{$row->table_id}->indicators->{$row->indicator_id}->extra_data = isset($row->extra_data)?$row->extra_data:NULL;
$alignments->{$row->table_id}->indicators->{$row->indicator_id}->uri_k5 = isset($row->uri_k5)?$row->uri_k5:NULL;
$alignments->{$row->table_id}->indicators->{$row->indicator_id}->uri_612 = isset($row->uri_612)?$row->uri_612:NULL;
}
return $alignments;
}
The problem is that in the foreach loop if there are multiple items with the same $row->table_id then the last one in the loop is set (ignoring all others). I have tried the !isset($alignments->{row->table_id}) and it is still overriding. I am trying to say that if the variable of $alignments->{$row->table_id} exists, use it, if not, set it to a new StdClass()
Maybe you need to wrap your initialization like this:
if (!property_exists($alignment, $row->table_id)) {
$alignments->{$row->table_id} = new StdClass();
}

Formatting information in a PHP recordset and setting it to an Array

I am attempting to use a Manager Class to take the results of a query and do formatting on pieces of information so I don't have to have logic on my view. I googled a number of solution and thought this would work, but my Array of Key=>values is coming back blank. Can someone take a look at it and see what i am doing wrong? Thanks!
I have verified that $results contains the values I am attempting to format and place back into an Array.
while($row = mysqli_fetch_array($results)){
$pets[$row['petID']] = $row['petID'];
$pets[$row['chipID']]=$row['chipID'];
$pets[$row['adoptionDate']]=Date($row['adoptionDate'],'m-d-Y');
$pets[$row['pType']]=$row['pType'];
$pets[$row['breedName2']]=$row['breedName2'];
$pets[$row['breedName1']]=$row['breedName1'];
$pets[$row['imageName']]=$row['imageName'];
$pets[$row['intakeDate']]= Date($row['intakeDate'],'m-d-Y');
$pets[$row['status']]=$row['status'];
$pets[$row['age']]=$row['age'];
$pets[$row['ageText']]= $this->getAge($row['age']);
$pets[$row['gender']]=$row['gender'];
$pets[$row['genderText']] = $this->getGender($row['gender']);
$pets[$row['breed2']]=$row['breed2'];
$pets[$row['breed']]=$row['breed'];
$pets[$row['petType']]=$row['petType'];
$pets[$row['petName']]=$row['petName'];
$pets[$row['customID']]=$row['customID'];
}
Here is the complete function that does not return anything:
public function getPets($cond,$orgID){
$pets = array();
$pg = new petsGateway();
$results = $pg->listByQuery($cond, $orgID);
while($row = mysqli_fetch_array($results)){
$pets[$row['petID']] = $row['petID'];
$pets[$row['chipID']]=$row['chipID'];
$pets[$row['adoptionDate']]=Date($row['adoptionDate'],'m-d-Y');
$pets[$row['pType']]=$row['pType'];
$pets[$row['breedName2']]=$row['breedName2'];
$pets[$row['breedName1']]=$row['breedName1'];
$pets[$row['imageName']]= $this->getImageURL($row['imageName']);
$pets[$row['intakeDate']]= Date($row['intakeDate'],'m-d-Y');
$pets[$row['status']]=$row['status'];
$pets[$row['age']]=$row['age'];
$pets[$row['ageText']]= $this->getAge($row['age']);
$pets[$row['gender']]=$row['gender'];
$pets[$row['genderText']] = $this->getGender($row['gender']);
$pets[$row['breed2']]=$row['breed2'];
$pets[$row['breed']]=$row['breed'];
$pets[$row['petType']]=$row['petType'];
$pets[$row['petName']]=$row['petName'];
$pets[$row['customID']]=$row['customID'];
}
return $pets;
}
That's rather... repetitive code... wouldn't it be easier to modify your query to fetch the rows you want AND do the date formatting directly in the DB?
e.g.
SELECT rowID, ... DATE_FORMAT(adoptionDate, '%m-%d-%Y'), ...
FROM ...
and then
while($row = mysql_fetch_assoc($result)) {
$pets[] = $row;
}
hm.... well im not sure what you want, but as you have it now, the key and the value of your array will be the same, which makes it useless.
i.e. for petName
$pets['Fido'] = 'Fido'
probably you want to get rid of the $row portion of the left side of your assignment, so that you end up with this
while($row = mysqli_fetch_array($results))
{
$pet = Array();
$pet['petID'] = $row['petID'];
$pet['chipID'] = $row['chipID'];
$pet['adoptionDate'] = Date($row['adoptionDate'],'m-d-Y');
$pet['pType'] = $row['pType'];
$pet['breedName2'] = $row['breedName2'];
$pet['breedName1'] = $row['breedName1'];
$pet['imageName'] = $row['imageName'];
$pet['intakeDate'] = Date($row['intakeDate'],'m-d-Y');
$pet['status'] = $row['status'];
$pet['age'] = $row['age'];
$pet['ageText'] = $this->getAge($row['age']);
$pet['gender'] = $row['gender'];
$pet['genderText'] = $this->getGender($row['gender']);
$pet['breed2'] = $row['breed2'];
$pet['breed'] = $row['breed'];
$pet['petType'] = $row['petType'];
$pet['petName'] = $row['petName'];
$pet['customID'] = $row['customID'];
$pets.push($pet);
}
I am guessing but I understood that you want some thing like:
while($row = mysqli_fetch_array($results)){
$pets[$row['petID']]['petID'] = $row['petID'];
$pets[$row['petID']]['chipID'] = $row['chipID'];
$pets[$row['petID']]['adoptionDate'] = Date($row['adoptionDate'],'m-d-Y');
$pets[$row['petID']]['pType'] = $row['pType'];
$pets[$row['petID']]['breedName2'] = $row['breedName2'];
$pets[$row['petID']]['breedName1'] = $row['breedName1'];
$pets[$row['petID']]['imageName'] = $row['imageName'];
$pets[$row['petID']]['intakeDate'] = Date($row['intakeDate'],'m-d-Y');
$pets[$row['petID']]['status'] = $row['status'];
$pets[$row['petID']]['age'] = $row['age'];
$pets[$row['petID']]['ageText'] = $this->getAge($row['age']);
$pets[$row['petID']]['gender'] = $row['gender'];
$pets[$row['petID']]['genderText'] = $this->getGender($row['gender']);
$pets[$row['petID']]['breed2'] = $row['breed2'];
$pets[$row['petID']]['breed'] = $row['breed'];
$pets[$row['petID']]['petType'] = $row['petType'];
$pets[$row['petID']]['petName'] = $row['petName'];
$pets[$row['petID']]['customID'] = $row['customID'];
}
This way you have an array with all the pets ID as first key and its details in the second key. You can use the array push as well.
That will rewrite $pets[KEY] each time it loops through record. You want..
$pets[]['petID'] = $row['petID'];
$pets[]['chipID'] = $row['chipID'];
and so on

PHP - simplyfy the code - something like MVC part

Im .NET programmer, but totally new in PHP. Im fighting with this for hours.
I need to simplyfy data transfer from interface to database. I have something like this:
$default = new stdClass();
// default values - all of them should be set to default value
// some of them will be overwritten later, but only one of them
$default->{'val-string'} = ''; // default values start
$default->{'val-int'} = 0;
$default->{'val-float'} = 0;
$default->{'val-image'} = ' ';
$default->{'val-datetime'} = 0;
$default->{'val-boolean'} = false; // default values end
$container = array();
$row = clone $default;
$row->{'field_id'} = 1;
$row->{'field_name'} = $nameoffield1;
$row->{'val-string'} = 'Diffrent types are filled for diffrent rows';
$container[] = $row;
$row = clone $default;
$row->{'field_id'} = 2;
$row->{'field_name'} = $nameoffield2;
$row->{'val-int'} = $valueoffield2;
$container[] = $row;
$row = clone $default;
$row->{'field_id'} = 3;
$row->{'field_name'} = $nameoffield3;
$row->{'val-datetime'} = current_time();
$container[] = $row;
// there
// is
// a lot
// of these
//rows
$result = $database->insertContainer($db_session, $container);
At the end need something like that "pseudocode .NET mixed with php"
list_of_rows.AddItem(makeRow($field_id1, $name1, (int)$dataforint)));
list_of_rows.AddItem(makeRow($field_id2, $name2, (string)$dataforstring));
list_of_rows.AddItem(makeRow($field_id3, $name3, (date)$datafordate));
list_of_rows.AddItem(makeRow($field_id4, $name4, (boolean)$dataforboolean));
$result = $database->insertContainer($db_session, list_of_rows);
If overloading like this is not possible (or very complicated) in PHP - i will be happy if someone give me any better solution than mine code at the top.
This a possible approach. You can also use the __call method to achieve this. This is just a quick example. Either this, or you might use an ORM like propel to achieve something similair. It really depends on what the task is.
class Row_Builder {
protected $default = array();
public function __construct() {
$this->default['field_id'] = null;
$this->default['field_name'] = null;
$this->default['val-string'] = null;
$this->default['val-int'] = null;
$this->default['val-float'] = null;
$this->default['val-image'] = null;
$this->default['val-datetime'] = null;
$this->default['val-boolean'] = false;
return;
}
public function setValues() {
// we only need the fist argument in this case.
$params= func_get_arg(0);
if(isset($params)) {
foreach($params as $key => $value) {
if(array_key_exists($key,$this->default)) {
$this->default[$key] = $value;
}
}
}
}
public function __get($key) {
if(array_key_exists($key, $this->default)) {
return $this->default[$key];
}
}
}
$row = new Row_Builder;
$row->setValues(array('field_id' => 1, 'field_name' => 'some value', 'val-string' => 'here is a str value'));
print $row->field_name;

Categories