__PHP_Incomplete_Class Object question

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

victorsk
Forum Commoner
Posts: 43
Joined: Thu Apr 19, 2007 6:55 pm

__PHP_Incomplete_Class Object question

Post by victorsk »

Hello folks,

I have a serious problem trying to get a complete object. What I have is:

file class_foo.php

Code: Select all

class foo
{
     require_once "SOAP/Client.php"; 
    public $client;
     public $resp;
     function __construct($parameters)
     {
                  //split $parameters into variables to pass into SOAP request
                  $this->client->callSOAPMethod();
                  $this->client->callAnotherSOAPMethod();
                  $this->resp = $this->client->callSomeMoreSOAPMethods();
     }
 
     function getResponse()
     {
            return $this->resp;
     }

     function getClient()
     {
            return $this->client;
     }
}

file1.php
{
 include 'class_foo.php';
          session_start();
          $obj = new foo($parameters_from_html);
          $_SESSION['sobject'] = $obj;
        
        //THIS WORKS FINE
         processObject($obj->getResponse());
}

file2.php
{
    include 'class_foo.php';
   session_start();
    $obj = $_SESSION['sobject'];

    //THIS CREATES __PHP_Incomplete_Class Object
   print_r($obj->getClient());

   //THIS DOES *NOT* CREATE Incomplete_Class Object and works fine

  print_r($obj->getResponse());
}
Please, help me, I have no idea why I am getting Incomplete_Class Object for one function call and not the other. I tried serialize/unserialize - didn't work. I am not familiar with all the PHP incricacies. Please help me.

Thank you,
Victor.
User avatar
aaronhall
DevNet Resident
Posts: 1040
Joined: Tue Aug 13, 2002 5:10 pm
Location: Back in Phoenix, missing the microbrews
Contact:

Post by aaronhall »

Code: Select all

require_once "SOAP/Client.php";
should either be outside of the class or inside the class's __construct method. Your files aren't wrapped in curly brackets, are they?
victorsk
Forum Commoner
Posts: 43
Joined: Thu Apr 19, 2007 6:55 pm

Post by victorsk »

Hi, it is outside of my class in the original code, sorry for putting it there in the example.
User avatar
aaronhall
DevNet Resident
Posts: 1040
Joined: Tue Aug 13, 2002 5:10 pm
Location: Back in Phoenix, missing the microbrews
Contact:

Post by aaronhall »

foo::client isn't being set before it's referenced... it looks like you're expecting it to be a soap object.
victorsk
Forum Commoner
Posts: 43
Joined: Thu Apr 19, 2007 6:55 pm

Post by victorsk »

Hi,

Thank you so much for replying. When I do the follwing in my file1.php:

Code: Select all

$obj = new foo($html_parameters);
        $_SESSION['sobject'] = $obj;    
        echo '<pre>';
        print_r($_SESSION['sobject']->getClient());
        echo '</pre>';
I get the right printout:

Code: Select all

WebService_WebService_WebServiceSoap Object
(
    [_endpoint] => http://cws.globaltsg.com/TSGWebServices/WebService.asmx
    [_portName] => 0
    [_endpointType] => 
    [xml] => 2007-05-23T15:00:55.5625-04:002007-05-23T15:00:57.375-04:006321334170ConquestVacationsCVYVRCUN2007-07-22T00:00:002007-07-29T00:00:007YVRCUNDOSDOS PLAYAS CUN   ROOM   AI2007-07-22T07:00:002007-07-22T14:35:00TS7002007-07-29T16:05:002007-07-29T20:20:00TS701AllInclusiveDoubleUserDefinedUndefinedHotel Room10000trueHotel Dos PlayasCUNSet in tropical gardens, this quiet beachside resort offers a casual, relaxed atmosphere and great value.

Location:
Directly on the beach in the hotel zone, minutes from the Isla Mujeres dock for the ferry. 15 minutes from downtown, walking distance to Cancun's popular bar Fat Tuesday's, and 35 minutes from the airportOffrant tranquilité et relaxation ainsi qu'une excellente valeur, Dos Playas est assuré de plaire aux personnes qui ont le coeur jeune.2.5BeachFrontHoneymoonSuiteScubaDivingTennishttp://images.globaltsg.com/Images/SuperDef/313/313_00.jpgTourProviderInformationhttp://www.conquestvacations.com/hotels/DSOP.htmlEnglishfalse11581158CADCADUnknown273.9273.9CADCADUnknownTotal1431.91431.9CADCADUnknowntrue1Adult1ConquestVacationsCVYVRCUN2007-07-22T00:00:002007-07-29T00:00:007YVRCUNETSEL TUKAN CONDOTL STDRM  AI2007-07-22T07:00:002007-07-22T14:35:00TS7002007-07-29T16:05:002007-07-29T20:20:00TS701AllInclusiveDoubleUserDefinedUndefinedStandard Room10000trueEl Tukan Condotel VillasCUNThis hotel is set around a huge lush garden with a pool, winding flagstone paths, and a cenote - or natural underground pool.Cet hôtel est à l'entour d'un immense jardin luxuriant avec piscine, ainsi qu'une piscine naturelle intérieure.3BeachFrontHoneymoonSuiteKitchenetteScubaDivingWeddinghttp://images.globaltsg.com/Images/SuperDef/218/218_00.jpgTourProviderInformationhttp://www.conquestvacations.com/hotels/ETUK.htmlEnglishfalse11881188CADCADUnknown273.9273.9CADCADUnknownTotal1461.91461.9CADCADUnknowntrue1Adult
    [wire] => 
    [_last_request] => 
    [_last_response] => 
    [_options] => Array
        (
            [trace] => 
            [input] => parse
            [result] => parse
            [parameters] => 
            [namespace] => http://ws.globaltsg.com/TSGWebServices
            [soapaction] => http://ws.globaltsg.com/TSGWebServices/SearchTourPackages
            [style] => document
            [use] => literal
        )

    [_encoding] => UTF-8
    [headersIn] => Array
        (
            [StatusHeader] => stdClass Object
                (
                    [serverRequestStartTime] => 2007-05-23T15:00:55.5625-04:00
                    [serverRequestEndTime] => 2007-05-23T15:00:57.375-04:00
                    [serverVersion] => 6321
                    [internalRequestId] => 33417
                )

        )

    [_proxy_params] => Array
        (
            [timeout] => 360
        )

    [_soap_transport] => SOAP_Transport_HTTP Object

...
But, in file2.php I get an Incomplete Object error :-(

I don't understand why file1.php is different from file2.php in that it gets return of the right $client but not file2.php. How can I make $client work in file2.php also?

Thank you,
Victor.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

Works without errors,warning,etc :

Code: Select all

<?php // class_foo.php
require_once 'SOAP/Client.php';

class foo {
	public $client;
	public $resp;
	
	function __construct($parameters)	{
		$this->client = new SOAP_Client('http://www.compkarori.com/wsdl/discordian.wsdl');
		$this->client->setOpt('trace', 'true');
		$this->resp = $this->client->call('Discordian', $parameters);
	}
}

Code: Select all

<?php // test.php
error_reporting(E_ALL);
ini_set('display_errors', true);
require 'class_foo.php';
session_start();

$_SESSION['sobject'] = new foo(array('year'=>2007, 'month'=>5, 'day'=>24));
?>
<html>
	<head><title>session test #1</title></head>
	<body>
		<pre>resp: <?php print_r($_SESSION['sobject']->resp); ?></pre>
		<pre>session-id: <?php echo session_id(); ?></pre>
		<a href="test2.php">test2</a>
	</body>
</html>

Code: Select all

<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
require 'class_foo.php';
session_start();
?>
<html>
	<head><title>session test #2</title></head>
	<body>
		<pre>resp: <?php print_r($_SESSION['sobject']->resp); ?></pre>
		<pre>class: <?php echo get_class($_SESSION['sobject']->client); ?></pre>
		<pre>session-id: <?php echo session_id(); ?></pre>
		<a href="test2.php">test2</a>
	</body>
</html>
victorsk
Forum Commoner
Posts: 43
Joined: Thu Apr 19, 2007 6:55 pm

Post by victorsk »

Hi Volka,

I am deeply grateful for your assistance. I tried your example and it works. The sad thing is that my situation requires a user to use SOAP lLogin method which sends a session cookie with which other API calls are possible. I am not sure if there is a way to do this using

Code: Select all

$this->client = new Soap_Client("http://cws.globaltsg.com/TSGWebServices/WebService.asmx?WSDL");
Because I am using getProxy() call like this:

Code: Select all

<?php // class_foo.php
require_once 'SOAP/Client.php';

class foo {
        public $client;
        public $resp;
        public $conn;

        function __construct($parameters)
        {
                $wsdl = 'http://cws.globaltsg.com/TSGWebServices/WebService.asmx?WSDL';
                $this->conn = new SOAP_Wsdl($wsdl, array("timeout" => 360));
                $params = Array(
                                 'agencyId'=> new Soap_Value( 'agencyId', 'string', "XXX" ),
                                 'userName'=> new Soap_Value( 'userName', 'string', 'XXXXXXX'),
                                 'userPassword'=> new Soap_Value( 'userPassword', 'string', 'XXXXXXXXX')
                               );

                $soapheader1 = new Soap_Header("StatusHeader", "object",
                                  array(
                                        "clientHostAddress" => new Soap_Value( "clientHostAddress", "string", "127.0.0.1" ),
                                        "serverRequestStartTime" => new Soap_Value("serverRequestStartTime", "string","2007-05-21T10:35:00"),
                                        "serverRequestEndTime" => new Soap_Value("serverRequestEndTime", "string","2007-05-21T10:35:00"),
                                        "serverVersion" => new Soap_Value("serverVersion", "string","0"),
                                        "internalRequestId" => new Soap_Value("internalRequestId", "int", 0)
                                       ), 1, '');

                $this->client = $this->conn->getProxy();    
                $this->client->setDefaultNamespace("http://ws.globaltsg.com/TSGWebServices" );
                $this->client->addHeader($soapheader1);

                $this->client->Login( new SOAP_Value( 'request', "object", $params ) );        
                $this->resp = $this->client->GetAgencyFunctionalities();
        }
}
To fully test it I'd need to give out user id, agency id, and password publicly which I am reluctant to do. Would you allow me to send it to you in private. I really need this to be solved because this is for work.

Again, the problem I get with this is that I don't think that $client variable gets fully created as an object but this is the only way I know how to use calls to getProxy() to get session cookie and make API calls. But then if you just plug in this code into the class_foo.php file then it will say that session class in Incomplete_Object.

Please, help me with this.

Thank you,
Victor.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

If you still have an __PHP_Incomplete_Class in _SESSION, the class foo or the class SOAP_Client wasn't present when session_start() has been called.
You need to check the include/session_start order again. First include or require, then session_start.
victorsk
Forum Commoner
Posts: 43
Joined: Thu Apr 19, 2007 6:55 pm

Post by victorsk »

volka wrote:If you still have an __PHP_Incomplete_Class in _SESSION, the class foo or the class SOAP_Client wasn't present when session_start() has been called.
You need to check the include/session_start order again. First include or require, then session_start.
Hi Volka,

Yes, exactly, class SOAP_Client is not in my class_foo.php, I am using SOAP_Wsdl() instead then using its object to call getProxy() and create $client session object like this:

Code: Select all

$wsdl = 'http://cws.globaltsg.com/TSGWebServices/WebService.asmx?WSDL';
$this->conn = new SOAP_Wsdl($wsdl, array("timeout" => 360)); //INSTEAD OF SOAP_Client()
$this->client = $this->conn->getProxy();
I need to use a call to getProxy() to get Session Id and other information necessary for subsequent API calls. Do you know how I can use getProxy() with Soap_Client()? That will solve my problem I think.

Thank you for helping me out on this one.

Victor.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

I have no idea how PEAR::SOAP works. And it doesn't matter. If you get an __PHP_Incomplete_Class the definition for this class wasn't present when session_start has been called, no matter which class.
Clear your session directory (in case of doubt echo ini_get('session_save_path'); tells you which directory) to get rid of all session data.
Then replace session_start() by

Code: Select all

error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('unserialize_callback_func', 'mycallback');
function mycallback($classname)
{
	echo 'undefined class: ', $classname, "<br />\n";
	if ( function_exists('debug_print_backtrace') ) {
		echo '<pre>backtrace: '; debug_print_backtrace(); echo "</pre>\n";
	}
	echo '<pre>included: '; get_included_files(); echo "</pre>\n";
}
session_start();
in both main script files and try again.


and replace $this->client = $this->conn->getProxy(); by

Code: Select all

$this->client = $this->conn->getProxy();
echo '<div> Debug, client class: ', get_class($this->client), "</div>\n";
victorsk
Forum Commoner
Posts: 43
Joined: Thu Apr 19, 2007 6:55 pm

Post by victorsk »

Hi,

I've add all the suggestions and I've got these messages:

Code: Select all

undefined class: WebService_WebService_WebServiceSoap

backtrace: #0  mycallback(WebService_WebService_WebServiceSoap)
#1  session_start() called at [/var/www/html/test/checkTourAvailability.php]

included:
Any Ideas?
Thank you,
Victor.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

Looks like getProxy() creates a new, specialized class from the wsdl.
I have no idea how you can make this class definition persistent. You can re-create the class by creating a new (dummy) SOAP_WSDL from same wsdl and calling getProxy() prior to session_start().
Have you tried SOAP_Client instead?
victorsk
Forum Commoner
Posts: 43
Joined: Thu Apr 19, 2007 6:55 pm

Post by victorsk »

volka wrote:Looks like getProxy() creates a new, specialized class from the wsdl.
I have no idea how you can make this class definition persistent. You can re-create the class by creating a new (dummy) SOAP_WSDL from same wsdl and calling getProxy() prior to session_start().
Have you tried SOAP_Client instead?
Yes, I did, but trouble is that I wasn't able to use getProxy() then. I have another idea. In file1.php I can, in fact, get the complete object definition of WSDL $client *BUT* it has to be in file2.php which it doesn't work. So my idea is this:

1. Get value of $client from file1 using:

Code: Select all

$obj = new class_foo($parameters_from_html);
$client = $obj->getClient();
2. Store the value of existing $client object in the database with sessionId as key and $client object's value as text:

Code: Select all

mysql_query('insert into client values("'.print_r($obj->getClient()).'")'); or
mysql_query('insert into client values("'.var_dump($obj->getClient()).'")');
3. Make file2.php get the object's values using commonly-shared sessionId() which I saw they have as key

My question: will this implementation work?

Thank you,
Victor.
victorsk
Forum Commoner
Posts: 43
Joined: Thu Apr 19, 2007 6:55 pm

Post by victorsk »

Alright, I just tried placing print_r or var_dump results into database but all I got was object's printout on a screen and value 1 in the table. Is it possible to store PHP object in a database and then retrieve it with PHP?

Thank you,
Victor.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

victorsk wrote:Yes, I did, but trouble is that I wasn't able to use getProxy() then.
Why do you need getProxy() ?
victorsk wrote:Is it possible to store PHP object in a database and then retrieve it with PHP?
The exact same problem as with the session data, the class definintion must be present when the object is restored.
Post Reply