Martialdelastic / google-api-adwords-php

Automatically exported from code.google.com/p/google-api-adwords-php
Apache License 2.0
0 stars 0 forks source link

When using a class loader library mixes different versions of class files #11

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. Use a class loader that e.g. uses the class name, appends .php and
traverses a set of directories to find the class definition and loads it.
2. Add the src directory of the Google Adwords PHP client lib to the search
path of the class loader.
3. Request e.g. CampaignService for version v200909.
4. The actual class you'd load is v200906 because it's found first by the
class loader.
5. As a result you'll call the v200909 version of the API with a v200906
service object.

What version of the product are you using? On what operating system?
Using v200909 on Linux, any installation of the library that includes more
than one version of the lib will have that problem.

Please provide any additional information below.

I tried to create a few dummy campaigns in my sandbox and got the
following error:

Fatal error: Uncaught SoapFault exception: [soap:Server] Unmarshalling
Error: Unable to create an instance of
com.google.ads.api.services.campaignmgmt.campaign.v200909.jaxbgen.BiddingStrateg
y
in /adwords_client/src/Google/Api/Ads/Common/Lib/AdsSoapClient.php:
160

However the examples that come with the client distribution actually
worked fine out of the original unzipped directory. When digging
deeper into this I noticed that I was actually using the v200906
CampaignService in my app, although I requested v200909 from the
factory. The namespace inside the XML request document was correctly
set to https://adwords.google.com/api/adwords/cm/v200909 though. And I
found the code was including the v200909 version of
CampaignService.php but still instantiating v200906.

It turned out that the class loader was to blame. I was running this
application inside Symfony, but any other class loader that works in a
similar way would cause the same problem. CampaignService.php actually
defines a bunch of classes needed for the service's operation. In
order to avoid duplicate class names the code checks first, if a class
with that name already exists before running the class defintion which
looks like this:

if (!class_exists("DateRange")) {
   // definition of DateRange class
}

However this triggers the class loader to try and load that class,
which in my case found the v200906 version CampaignService.php,
included it and ran all the definitions inside the file. After that
all subsequent definitions in the v200909 version of
CampaignService.php where ignored.

I'd suggest to change all the tests for existence of classes to
include the second parameter of class_exists and prevent the class
loader from being used; for the above example that would just require
a small change:

if (!class_exists("DateRange",false)) {
   // definition of DateRange class
}

Unless there is actually a reason why the code would want to load a
different class with that name of course. But from what I understand
that should only make sure the definition is not run twice.

I know I can avoid that problem by just moving the client lib out of
the range of the class loader, which I did and everything worked as
planned. But I thought that little change could make the library a
little more robust. Depending on the efficiency of the class loader
that would also result in a tiny performance gain. 

Original issue reported on code.google.com by volker.k...@gmail.com on 19 Jan 2010 at 7:27

GoogleCodeExporter commented 8 years ago

Original comment by api.ekol...@gmail.com on 19 Jan 2010 at 8:58

GoogleCodeExporter commented 8 years ago

Original comment by api.ekol...@gmail.com on 19 Jan 2010 at 9:28

GoogleCodeExporter commented 8 years ago
This was fixed in version 1.2.2.

Original comment by api.ekol...@gmail.com on 20 Jan 2010 at 4:26