Solved

why did code not enter a class xmlException

Posted on 2014-04-08
11
357 Views
Last Modified: 2014-04-22
from matt zandstra php book


when line 72 is uncommented
Catchable fatal error: Argument 1 passed to XmlException::__construct() must be an instance of LibXMLError, integer given, called in C:\wamp\www\POPP-edition4-code\9781430260318_Chapter_04_Code\listing4.22.php on line 72 and defined in C:\wamp\www\POPP-edition4-code\9781430260318_Chapter_04_Code\listing4.22.php on line 6

I see that error is about libxml type which means an attempt to enter class xmlException

using line 74 or line 75
in this case line 74:
LibXMLError Object ( [level] => 3
 => 76 [column] => 12 [message] => Opening and ending tag mismatch: conf-broked line 2 and conf [file] => file:///C:/wamp/www/POPP-edition4-code/9781430260318_Chapter_04_Code/conf.broken.xml [line] => 6 ) 

code never went to
xmlException::__construct()
line 6









[code]<?php

class XmlException extends Exception {
    private $error;

    function __construct( LibXmlError $error ) {
        $shortfile = basename( $error->file );
	print_r( $error );
        $msg = "[{$shortfile}, line# {$error->line}, col# {$error->column}] {$error->message}";
        $this->error = $error;
        parent::__construct( $msg, $error->code );
    }

    function getLibXmlError() {
        return $this->error;
    }
}

class FileException extends Exception { }
class ConfException extends Exception { }

class Conf {
    private $file;
    private $xml;
    private $lastmatch;

    function __construct( $file ) {
        $this->file = $file;
        if ( ! file_exists( $file ) ) {
            throw new FileException( "file '$file' does not exist" );
        }
        $this->xml = simplexml_load_file($file, null, LIBXML_NOERROR );
        if ( ! is_object( $this->xml ) ) {
            throw new XmlException( libxml_get_last_error() );
        }
        $matches = $this->xml->xpath("/conf");
        if ( ! count( $matches ) ) {
            throw new ConfException( "could not find root element: conf" );
        }
    }    

    function write() {
        if ( ! is_writeable( $this->file ) ) {
            throw new Exception("file '{$this->file}' is not writeable");
        }
        file_put_contents( $this->file, $this->xml->asXML() );
    }

    function get( $str ) {
        $matches = $this->xml->xpath("/conf/item[@name=\"$str\"]");
        if ( count( $matches ) ) {
            $this->lastmatch = $matches[0];
            return (string)$matches[0];
        }
        return null;
    }

    function set( $key, $value ) {
        if ( ! is_null( $this->get( $key ) ) ) {
            $this->lastmatch[0]=$value;
            return;
        }
        $conf = $this->xml->conf;
        $this->xml->addChild('item', $value)->addAttribute( 'name', $key );
    }
}


class Runner {
    static function init() { 
        try {
            //$error_test= new XmlException(1);
            //$conf = new Conf( dirname(__FILE__)."/conf01-edit.xml" );
            $conf = new Conf( dirname(__FILE__)."/conf.broken.xml" );
            //$conf = new Conf( dirname(__FILE__)."/fake.xml" );
            print "user: ".$conf->get('user')."\n";
            print "host: ".$conf->get('host')."\n";
            $conf->set("pass", "newpass");
            $conf->write();
        } catch ( FileException $e ) {
            // permissions issue or non-existent file
            throw $e;
        } catch ( XmlException $e ) {
            // broken xml
        } catch ( ConfException $e ) {
            // wrong kind of XML file
        } catch ( Exception $e ) {
            // backstop: should not be called
        }
    }
}

Runner::init();

?>

Open in new window

0
Comment
Question by:rgb192
  • 6
  • 5
11 Comments
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39987329
This statement means that the class can only be instantiated if it is given an object instance of LibXmlError as its argument.  In effect you're telling PHP to kill the script if you get any data structure other than LibXmlError sent into the constructor.

function __construct( LibXmlError $error ) {

If you try it like this ...

function __construct( $error ) {

... then you will be able to use var_dump($error) to see what the program logic sent to the XMLException class constructor.
0
 

Author Comment

by:rgb192
ID: 39987547
function __construct( LibXmlError $error ) {

If you try it like this ...

function __construct( $error ) {

Okay this is the answer for line 72

but why can line 74,75 not enter the constructor
(there is no $msg echo)


I made error with code block
this is correct code:
<?php

class XmlException extends Exception {
    private $error;

    function __construct( LibXmlError $error ) {
        $shortfile = basename( $error->file );
	print_r( $error );
        $msg = "[{$shortfile}, line# {$error->line}, col# {$error->column}] {$error->message}";
        $this->error = $error;
        parent::__construct( $msg, $error->code );
    }

    function getLibXmlError() {
        return $this->error;
    }
}

class FileException extends Exception { }
class ConfException extends Exception { }

class Conf {
    private $file;
    private $xml;
    private $lastmatch;

    function __construct( $file ) {
        $this->file = $file;
        if ( ! file_exists( $file ) ) {
            throw new FileException( "file '$file' does not exist" );
        }
        $this->xml = simplexml_load_file($file, null, LIBXML_NOERROR );
        if ( ! is_object( $this->xml ) ) {
            throw new XmlException( libxml_get_last_error() );
        }
        $matches = $this->xml->xpath("/conf");
        if ( ! count( $matches ) ) {
            throw new ConfException( "could not find root element: conf" );
        }
    }    

    function write() {
        if ( ! is_writeable( $this->file ) ) {
            throw new Exception("file '{$this->file}' is not writeable");
        }
        file_put_contents( $this->file, $this->xml->asXML() );
    }

    function get( $str ) {
        $matches = $this->xml->xpath("/conf/item[@name=\"$str\"]");
        if ( count( $matches ) ) {
            $this->lastmatch = $matches[0];
            return (string)$matches[0];
        }
        return null;
    }

    function set( $key, $value ) {
        if ( ! is_null( $this->get( $key ) ) ) {
            $this->lastmatch[0]=$value;
            return;
        }
        $conf = $this->xml->conf;
        $this->xml->addChild('item', $value)->addAttribute( 'name', $key );
    }
}


class Runner {
    static function init() { 
        try {
            $error_test= new XmlException(1);
            //$conf = new Conf( dirname(__FILE__)."/conf01-edit.xml" );
            $conf = new Conf( dirname(__FILE__)."/conf.broken.xml" );
            $conf = new Conf( dirname(__FILE__)."/fake.xml" );
            print "user: ".$conf->get('user')."\n";
            print "host: ".$conf->get('host')."\n";
            $conf->set("pass", "newpass");
            $conf->write();
        } catch ( FileException $e ) {
            // permissions issue or non-existent file
            throw $e;
        } catch ( XmlException $e ) {
            // broken xml
        } catch ( ConfException $e ) {
            // wrong kind of XML file
        } catch ( Exception $e ) {
            // backstop: should not be called
        }
    }
}

Runner::init();

?>

Open in new window



and this is the error for
line 74: (line 75 uncommented also does not enter constructor)
LibXMLError Object ( [level] => 3=> 76 [column] => 12 [message] => Opening and ending tag mismatch: conf-broked line 2 and conf [file] => file:///C:/wamp/www/POPP-edition4-code/9781430260318_Chapter_04_Code/conf.broken.xml [line] => 6 )

code never went to
xmlException::__construct()
line 6
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39987571
This line suppresses XML errors...

 $this->xml = simplexml_load_file($file, null, LIBXML_NOERROR );

I don't really know what "suppresses" means in this context.  It may mean that the suppressed error is not available to libxml_get_last_error().  I think I would set up some var_dump() statements to visualize the the contents of these function calls before using their output in another PHP statement.  Example:

Instead of this:

if ( ! is_object( $this->xml ) ) {
    throw new XmlException( libxml_get_last_error() );
}

Something more like this:

if ( ! is_object( $this->xml ) ) {
    // IT IS NOT AN OBJECT, SO WHAT IS IT?
    var_dump($this->xml);
    // WHAT IS IN THE ERROR FUNCTION?
    var_dump( libxml_get_last_error() );
    // NOW TRY TO THROW THE EXCEPTION
    throw new XmlException( libxml_get_last_error() );
}

Refs:
http://php.net/manual/en/libxml.constants.php
http://php.net/manual/en/function.libxml-get-last-error.php
0
 

Author Comment

by:rgb192
ID: 39987595
Warning: simplexml_load_file(): file:///C:/wamp/www/POPP-edition4-code/9781430260318_Chapter_04_Code/conf.broken.xml:6: parser error : Opening and ending tag mismatch: conf-broked line 2 and conf in C:\wamp\www\POPP-edition4-code\9781430260318_Chapter_04_Code\listing4.22b.php on line 32

Warning: simplexml_load_file(): </conf> in C:\wamp\www\POPP-edition4-code\9781430260318_Chapter_04_Code\listing4.22b.php on line 32

Warning: simplexml_load_file(): ^ in C:\wamp\www\POPP-edition4-code\9781430260318_Chapter_04_Code\listing4.22b.php on line 32
bool(false) object(LibXMLError)#2 (6) { ["level"]=> int(3) ["code"]=> int(76) ["column"]=> int(12) ["message"]=> string(61) "Opening and ending tag mismatch: conf-broked line 2 and conf " ["file"]=> string(84) "file:///C:/wamp/www/POPP-edition4-code/9781430260318_Chapter_04_Code/conf.broken.xml" ["line"]=> int(6) } LibXMLError Object ( [level] => 3 [c
ode] => 76 [column] => 12 [message] => Opening and ending tag mismatch: conf-broked line 2 and conf [file] => file:///C:/wamp/www/POPP-edition4-code/9781430260318_Chapter_04_Code/conf.broken.xml [line] => 6 )



<?php

class XmlException extends Exception {
    private $error;

    function __construct( LibXmlError $error ) {
        $shortfile = basename( $error->file );
	print_r( $error );
        $msg = "[{$shortfile}, line# {$error->line}, col# {$error->column}] {$error->message}";
        $this->error = $error;
        parent::__construct( $msg, $error->code );
    }

    function getLibXmlError() {
        return $this->error;
    }
}

class FileException extends Exception { }
class ConfException extends Exception { }

class Conf {
    private $file;
    private $xml;
    private $lastmatch;

    function __construct( $file ) {
        $this->file = $file;
        if ( ! file_exists( $file ) ) {
            throw new FileException( "file '$file' does not exist" );
        }
        $this->xml = simplexml_load_file($file,null,null);
        if ( ! is_object( $this->xml ) ) {
          // IT IS NOT AN OBJECT, SO WHAT IS IT?
          var_dump($this->xml);
          // WHAT IS IN THE ERROR FUNCTION?
          var_dump( libxml_get_last_error() );
          // NOW TRY TO THROW THE EXCEPTION
          throw new XmlException( libxml_get_last_error() );
        }
        $matches = $this->xml->xpath("/conf");
        if ( ! count( $matches ) ) {
            throw new ConfException( "could not find root element: conf" );
        }
    }    

    function write() {
        if ( ! is_writeable( $this->file ) ) {
            throw new Exception("file '{$this->file}' is not writeable");
        }
        file_put_contents( $this->file, $this->xml->asXML() );
    }

    function get( $str ) {
        $matches = $this->xml->xpath("/conf/item[@name=\"$str\"]");
        if ( count( $matches ) ) {
            $this->lastmatch = $matches[0];
            return (string)$matches[0];
        }
        return null;
    }

    function set( $key, $value ) {
        if ( ! is_null( $this->get( $key ) ) ) {
            $this->lastmatch[0]=$value;
            return;
        }
        $conf = $this->xml->conf;
        $this->xml->addChild('item', $value)->addAttribute( 'name', $key );
    }
}


class Runner {
    static function init() { 
        try {
            //$error_test= new XmlException(1);
            //$conf = new Conf( dirname(__FILE__)."/conf01-edit.xml" );
            $conf = new Conf( dirname(__FILE__)."/conf.broken.xml" );
            $conf = new Conf( dirname(__FILE__)."/fake.xml" );
            print "user: ".$conf->get('user')."\n";
            print "host: ".$conf->get('host')."\n";
            $conf->set("pass", "newpass");
            $conf->write();
        } catch ( FileException $e ) {
            // permissions issue or non-existent file
            throw $e;
        } catch ( XmlException $e ) {
            // broken xml
        } catch ( ConfException $e ) {
            // wrong kind of XML file
        } catch ( Exception $e ) {
            // backstop: should not be called
        }
    }
}

Runner::init();

?>

Open in new window





I was not sure how to edit
 $this->xml = simplexml_load_file($file, null, LIBXML_NOERROR );

I tried
 $this->xml = simplexml_load_file($file, null, null );


code did not enter the constructor
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 39987672
OK, so what is the question in this context?
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:rgb192
ID: 39987782
I think line 74,75 when uncommented should enter XmlException::__construct()

and you think the isssue is because
$this->xml = simplexml_load_file($file, null, LIBXML_NOERROR );
suppresses the error
0
 

Author Comment

by:rgb192
ID: 40012806
OK, so what is the question in this context?

I am using a line by line debugger and I do not see code entering the constructor
why?
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 40012857
Could you please set up the SSCCE and post the code and test data here?  I'll be glad to experiment with it and show you what I see, if I know I am starting from a point that makes sense to you.
0
 

Author Comment

by:rgb192
ID: 40013699
http://www.experts-exchange.com/viewCodeSnippet.jsp?refID=39987595&rtid=20&icsi=1


difficult to show test data because there is absence of output



    function __construct( LibXmlError $error ) {
        $shortfile = basename( $error->file );
	print_r( $error );
        $msg = "[{$shortfile}, line# {$error->line}, col# {$error->column}] {$error->message}";
        $this->error = $error;
        parent::__construct( $msg, $error->code );
    }

Open in new window


is never used.
I want to echo $msg
0
 
LVL 108

Accepted Solution

by:
Ray Paseur earned 500 total points
ID: 40014834
As I understand it, here is the full class definition:
class XmlException extends Exception {
    private $error;

    function __construct( LibXmlError $error ) {
        $shortfile = basename( $error->file );
	print_r( $error );
        $msg = "[{$shortfile}, line# {$error->line}, col# {$error->column}] {$error->message}";
        $this->error = $error;
        parent::__construct( $msg, $error->code );
    }

    function getLibXmlError() {
        return $this->error;
    }
}

Open in new window

If the constructor is never entered, it's because nothing threw a new XmlException.  This might be a logic error, or it might be "good news" that something worked correctly and had no need to raise an XMLException.  If you want to see what is in $msg, you might add var_dump($msg) after line 7.  $msg is a local variable so it will not be apparent if you dump the object.  You must dump $msg from within the class definition to see its contents.
0
 

Author Closing Comment

by:rgb192
ID: 40016199
okay nothing threw the xml exception
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Introduction Many web sites contain image galleries; a common design for these galleries includes a page with a collection of thumbnail images.  You can click on each of the thumbnail images to see the larger version of the image.  This is easily i…
Password hashing is better than message digests or encryption, and you should be using it instead of message digests or encryption.  Find out why and how in this article, which supplements the original article on PHP Client Registration, Login, Logo…
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now