Check a php variable contains a SimpleXMLObject - php

I need to check that the $model variable contains an object of type SimpleXMLObject.
$model = convertToSimpleXml($fileName, $filePath);
This is the end of the convertToSimpleXml method where the object is returned using simplexml_load_file
$simpleXml = simplexml_load_file($path);
return $simpleXml;
I've tried checking it as an array or something similar but no luck with that, have looked around for examples but can't find any clear cut answer to the question. Can anyone help?

You can simply check the class of your $simpleXml:
$simpleXml = simplexml_load_file($path);
if($simpleXml instanceof SimpleXMLElement) {
return $simpleXml;
} else {
return false;
}

Related

Creating default object from empty value- Code igniter

Hello I work on codeigniter and I try to eliminate warnings on my website, I block on:
$groups = array();
if ($bannished_groups) {
foreach ($bannished_groups as $k => $bannished_group) {
$groups[$k] = $this->group_model->GetGroupByID($bannished_group->groupid);
$groups[$k]->db = $bannished_group;
}
}
I have the error:
Creating default object from empty value
I tried to declare:
$groups[$k]->db = new stdClass();
but it does not work and i read the other answers but it does not help me ..
It seems like the method $this->group_model->GetGroupByID($bannished_group->groupid); don't always return an object, even if you think it does :-)
If it returns null, an empty string or false, you will get that error.
Just check it before you try and use it:
foreach ($bannished_groups as $k => $bannished_group) {
// Get the object
$obj = $this->group_model->GetGroupByID($bannished_group->groupid);
if (!is_object($obj)) {
// It's not an object, skip it and move on to the next
continue;
}
$groups[$k] = $obj;
$groups[$k]->db = $bannished_group;
}
This will make sure that your $groups-array only contains objects. If you still want to add it to the array regardless, just store the object directly in $groups[$k] instead of in the $obj-variable. The logic is the same, though.

PHP include external method and class

I'm new to PHP and I have an issue I can't seem to fix or find a solution to.
I'm trying to create a helper function that will return an 'object' filled with information pulled from an XML file. This helper function, named functions.php contains a getter method which returns a 'class' object filled with data from an SVN log.xml file.
Whenever I try to import this file using include 'functions.php'; none of the code after that line runs the calling function's page is blank.
What am I doing wrong?
Here is what the functions.php helper method and class declaration looks like:
<?php
$list_xml=simplexml_load_file("svn_list.xml");
$log_xml=simplexml_load_file("svn_log.xml");
class Entry{
var $revision;
var $date;
}
function getEntry($date){
$ret = new Entry;
foreach ($log_xml->logentry as $logentry){
if ($logentry->date == $date){
$ret->date = $logentry->date;
$ret->author = $logentry->author;
}
}
return $ret;
}
I'm not sure what the point of having a separate helper function from the class is, personally I'd combine the two. Something like this
other-file.php
require './Entry.php';
$oLogEntry = Entry::create($date, 'svn_log.xml');
echo $oLogEntry->date;
echo $oLogEntry->revision;
Entry.php
class Entry
{
public $revision;
public $date;
public $author;
public static function create($date, $file) {
$ret = new Entry;
$xml = simplexml_load_file($file);
foreach($xml->logentry as $logentry) {
if($logentry->date == $date) {
$ret->date = $logentry->date;
$ret->author = $logentry->author;
$ret->revision = $logentry->revision;
}
}
return $ret;
}
}
EDIT
In light of the fact OP is new to PHP, I'll revise my suggestion completely. How about ditching the class altogether here? There's hardly any reason to use a class I can see at this point; let's take a look at using an array instead.
I might still move the simplexml_load_file into the helper function though. Would need to see other operations to merit keeping it broken out.
entry-helper.php
function getEntry($date, $file) {
$log_xml = simplexml_load_file($file);
$entry = array();
foreach($log_xml->logentry as $logentry) {
if($logentry->date == $date) {
$entry['date'] = $logentry->date;
$entry['author'] = $logentry->author;
$entry['revision'] = $logentry->revision;
}
}
return $entry;
}
other-file.php
require './entry.php';
$aLogEntry = Entry::create($date, 'svn_log.xml');
echo $aLogEntry['date'];
echo $aLogEntry['revision'];
EDIT
One final thought.. Since you're seemingly searching for a point of interest in the log, then copying out portions of that node, why not just search for the match and return that node? Here's what I mean (a return of false indicates there was no log from that date)
function getEntry($date, $file) {
$log_xml = simplexml_load_file($file);
foreach($log_xml->logentry as $logentry) {
if($logentry->date == $date) {
return $logentry;
return false;
}
Also, what happens if you have multiple log entries from the same date? This will only return a single entry for a given date.
I would suggest using XPATH. There you can throw a single, concise XPATH expression at this log XML and get back an array of objects for all the entries from a given date. What you're working on is a good starting point, but once you have the basics, I'd move to XPATH for a clean final solution.

Check if an xml is loaded with simplexml_load_string

I am querying an xml file with php like this :
public function trackOrderAction()
{
$request = Mage::getResourceModel( 'order/request' );
$request->setOrder($this->getRequest()->getParam('increment_id'));
$response = $request->submit(true);
$xml = simplexml_load_string($response);
$items = count($xml->OrderItems->OrderItem);
}
The xml is not ready immediately so if people try to use the function before it is ready there is an error because it is trying to get the property of a non-object. My question is what is the proper way to check the xml response to see if there is anything and stop the function if there is not?
I tried something simple like
if (empty($xml)){
die();
} else {
$items = count($xml->OrderItems->OrderItem);
}
But this does not help. Any ideas on how to check to see if the xml loaded?
From http://us.php.net/manual/en/function.simplexml-load-string.php
Returns an object of class SimpleXMLElement with properties containing
the data held within the xml document. On errors, it will return
FALSE.
public function trackOrderAction()
{
$request = Mage::getResourceModel( 'order/request' );
$request->setOrder($this->getRequest()->getParam('increment_id'));
$response = $request->submit(true);
$xml = simplexml_load_string($response);
if ( !$xml ) {
return false;
}
$items = count($xml->OrderItems->OrderItem);
}
It will return false if there was an error. So fail right away if simplexml_load_string fails and return false. Otherwise continue on with the rest of the function. Never die() in a function.

Weird problem with dynamic method invocation

this time, I'm facing a really weird problem. I've the following code:
$xml = simplexml_load_file($this->interception_file);
foreach($xml->children() as $class) {
$path = str_replace('__CLASS_DIR__',CLASS_DIR,$class['path']);
if(!is_file($path)) {
throw new Exception('Bad configuration: file '.$path.' not found');
}
$className = pathinfo($path,PATHINFO_FILENAME);
foreach($class as $method) {
$method_name = $method['name'];
$obj = new $className();
var_dump(in_array($method_name,get_class_methods($className)));exit;
echo $obj->$method_name();### not a method ???
}
}
As you can see, I get the class name and method name from an XML file.
I can create an instance of the class without any problem. The var_dump at the end returns true, that means $method_name (which has 2 optional parameters) is a method of $className.
BUT, and I am pretty sure the syntax is correct, when I try: $obj->$method_name() I get:
Fatal error: Method name must be a string
If you have any ideas, pleaaaaase tell me :)
Thanks in advance,
Rolf
The issue you are having is probably that $method_name is not a string, but it contains a method to convert it to a string (__toString()).
As in_array by default don't do strict type comparisons you will find that $method_name is probably coveted to a string and then compared with the method names, which would explain why the var_dump outputs true.
You should be able to confirm this by checking the type of $method_name
echo gettype($method_name);
If it isn't a string the solution is to case the variable to a string and then use that to call the function.
$obj->{(string)$method_name}();
It's better to use the call_user_func function instead of $obj->$method_name() to call the method.
echo call_user_func(array($className, $method_name));

Php wrapper class for XML

I'm working on a new class to wrap XML handling. I want my class to use simplexml if it's installed, and the built in XML functions if it's not. Can anyone give me some suggestions on a skeleton class to do this? It seems "wrong" to litter each method with a bunch of if statements, and that also seems like it would make it nearly impossible to correctly test.
Any upfront suggestions would be great!
EDIT: I'm talking about these built-in xml functions.
Which built-in xml functions are you referring to? SimpleXml is a standard extension, which uses libxml underneath - just as the dom extension does. So if the dom extension is installed, chances are that so is SimpleXml.
I've made a class which wraps SimpleXml functionality... take what you may from it...
bXml.class.inc
There is one weird thing... it's that SimpleXml doesn't allow its constructor to be overloaded, so you can't do things at initiation ... like override the input value (i.e. so you can accept XML as in input). I got around that limitation by using an ArrayObject class to wrap the new SimpleXml class.
I use something like this for doing xml translations and content:
Assuming xml structure something like this (important to use a regular structure, means you can pull off some nice agile tricks!):
<word name="nameofitem">
<en>value</en>
<pt>valor</pt>
<de>value_de</de>
</word>
and then a class to handle the xml:
class translations
{
public $xml = null;
private $file = null;
private $dom = null;
function __construct($file="translations") {
// get xml
$this->file = $file;
$this->haschanges = false;
$this->xml = file_get_contents($_SERVER['DOCUMENT_ROOT']."/xml/".$file.".xml");
$this->dom = new DOMdocument();
$this->dom->loadXML($this->xml);
}
function updateNode($toupdate, $newvalue, $lang="pt",$rootnode="word"){
$this->haschanges = true;
$nodes = $this->dom->getElementsByTagName($rootnode);
foreach ($nodes as $key => $value) {
if ($value->getAttribute("name")==$toupdate) {
$nodes->item($key)->getElementsByTagName($lang)->item(0)->nodeValue = htmlspecialchars($newvalue,ENT_QUOTES,'UTF-8');
}
}
}
function saveUpdated(){
$toSave = $this->dom->saveXML();
if ($this->haschanges === true) {
file_put_contents($_SERVER['DOCUMENT_ROOT']."/xml/".$this->file.".xml", $toSave);
return true;
}
else {
return false;
}
}
}
I took out a few of the methods I have, for brevity, but I extend this with things to handle file and image uploads etc too.
Once you have all this you can do:
$xml = new translations();
// loop through all the language posts
foreach ($_POST["xml"]["en"] as $key => $value) {
$xml->updateNode($key, stripslashes($value), "en");
}
Or something ;) hope this gives you some ideas!

Categories