When I generate a WSDL file with ./symfony webservice:generate-wsdl (where is 'frontend', is 'soap' and is 'http://localhost ') I get a nice soap.wsdl file which works like it should. Except, the methods are not named 'justAMethod' but 'soapService_justAMethod' (where soapService is the module which holds the SOAP methods). How do I omit the module name in the SOAP method names? I know this is possible since the previous release of the software had no module name in the SOAP method names.
Found it: the option '-h' on './symfony webservice:generate-wsdl' creates a custom soapHandler, effectively omitting the module name in the SOAP methods. This is not in the documentation however.
Related
I create a service inside my module with the name of an existing core service (prestashop.adapter.data_provider.product). It successfully replaces it as seen in php ./bin/console debug:container output.
In yaml:
prestashop.adapter.data_provider.product:
class: PrestaShop\Module\MyModule\Adapter\Product\ProductDataProvider
The problem now is that I have 500 errors in some pages in BO. These errors are type errors like:
Type error: Argument 4 passed to
PrestaShopBundle\Model\Product\AdminModelAdapter::__construct() must
be an instance of
PrestaShop\PrestaShop\Adapter\Product\ProductDataProvider, instance of
PrestaShop\Module\MyModule\Adapter\Product\ProductDataProvider given,
called in....
I understand now that, whenever a constructor has an argument of type ProductDataProvider, the app tries to load my service but find a differentuse statement in the class (i.e in PrestaShopBundle\Model\Product\AdminModelAdapter)
These errors can be fixed by replacing the use statement in each file containing the problem, but as you may know, touching core files must be avoided.
Is there a way of overriding an existing service, but also make the override work all across the app "bypassing the use statements of the old service".
My website is with a hosting provider that has the MessageFormatter class available on the server (Linux, PHP 7.0.27) but it is an old ICU version (4.2.1) that doesn't support my message {number,plural,=0{# available} =1{# available} other{# available}} and gives the error:
Message pattern is invalid: Constructor failed
msgfmt_create: message formatter creation failed: U_ILLEGAL_CHARACTER
...because of the =1 and =2 notation.
I'm not able to make changes to the server so how can I force using the fallback method provided by Yii2 which works just fine?
There is this hacky way you can try.
Copy the yii\i18n\MessageFormatter code to a new file. Name it MessageFormatter.php and place somewhere in your application (but not in vendor folder).
In this new file change the format() method to:
public function format($pattern, $params, $language)
{
$this->_errorCode = 0;
$this->_errorMessage = '';
if ($params === []) {
return $pattern;
}
return $this->fallbackFormat($pattern, $params, $language);
}
Don't change anything else (including namespace).
Now let's use Yii mapping.
Find a place in your application when you can put code that will be run every time in bootstrapping phase. Good place for this is common/config/bootstrap.php if you are using "Advanced Template"-like project.
Add there this line:
Yii::$classMap['yii\i18n\MessageFormatter'] = 'path/to/your/MessageFormatter.php';
Obviously change the path to the one you've chosen. Now Yii autoloader will load this class from your file instead of the original Yii vendor folder (as mentioned in Class Autoloading section of the Guide).
In the modified file MessageFormatter method presence of intl library is never checked so fallback is used as default.
The downside of this trick is that you need to update manually your file every time original Yii file is changed (so almost every time you upgrade Yii version).
Another approach is to configure I18N component in your application to use your custom MessageFormatter where you can extend the original file and just override format() method inside without modifying class map.
I have a WSDL located somewhere similar to this:
https://provider.web-service.domain/path/ServiceName?wsdl
It has a line like this:
<wsdl:import namespace="http://name/space/service/" location="ServiceName.wsdl"></wsdl:import>
ie. It is trying to import another wsdl at the location:
https://provider.web-service.domain/path/ServiceName.wsdl
So when initialising the SoapClient, I get the following error:
PHP Fatal error: SOAP-ERROR: Parsing WSDL:
Couldn't load from 'https://provider.web-service.domain/path/ServiceName.wsdl' :
failed to load external entity "https://provider.web-service.domain/path/ServiceName.wsdl"
I'm trying to resolve this issue with my WSDL provider at the moment, but is there a workaround for this issue?
I'm guessing the only resolution is for them to provide a path that actually points to an accessible resource. And that in fact there isn't much I can do about it.
Your thoughts.
Related:
php SoapClient fails when passed a wsdl with relative path schemas
https://issues.apache.org/jira/browse/AXIS2-484
UPDATE
Provider says PHP SOAP Client SUX (Essentially).
Changed title from:
php SoapClient: Couldn't Load from external entity; to
php SoapClient: Couldn't Load from external entity (Where endpoint resolves to another location)
So PHP SoapClient doesn't know that the url to the wsdl is resolving to another location so it tries to import the file from the original location.
Since the resource does not exist at the original location it throws an error.
As a workaround, they have provided the WSDL so we can put on our server.
But this problem needs a better resolution.
UPDATE 2
I would like to reword the question for clarity:
I've been asked to use the following WSDL URL:
[1] https://provider.web-service.domain/path/ServiceName?wsdl
There are two WSDLs at the following location
[2] https://provider.web-service.domain/path/ServiceName/another/diff/path/prefix_ServiceName.wsdl
[3] https://provider.web-service.domain/path/ServiceName/another/diff/path/ServiceName.wsdl
[1] resolves to [2]; Then
[2] imports [3]
When passing [1] into SoapClient(), it FATALs (as described earlier)
When passing [2] into SoapClient(), it works.
What I've had to do in the passed, and what you COULD do if you really wanted to spend your time on it is: make a wrapper class for the soapclient and pre-process the wsdls. e.g.
class SoapClientCompatibility extends SoapClient{
public function __construct($wsdl, $options){
// do things here, like:
// download the wsdl using curl
// modify/check it, then hand it over as the $wsdl to parent::__construct
}
}
I need to add custom context classesDirectory in applicationDirectory section to the .zfproject.xml.
I have created a context class, that extends Zend_Tool_Project_Context_Filesystem_Directory but the issue is that all contexts loading necessary to parse .zfproject.xml are hardcoded in Zend_Tool_Project_Provider_Abstract class as:
$contextRegistry->addContextsFromDirectory(
dirname(dirname(__FILE__)) . '/Context/Zf/', 'Zend_Tool_Project_Context_Zf_'
);
$contextRegistry->addContextsFromDirectory(
dirname(dirname(__FILE__)) . '/Context/Filesystem/', 'Zend_Tool_Project_Context_Filesystem_'
);
So I don't see any way to load my context without patching zend sources (or adding custom files to Zend library directories).
Is it even possible?
I don't believe it is possible without changing the ZF source code. You could try creating an issue on http://framework.zend.com/issues along with a patch. Please make this generic though.
Alternatively, what are you trying to do that requires a custom context? Maybe there's another way to solve it?
I'm writing a SOAP API in PHP and I've run into a small problem. The API uses a functions file which contains a function called "GetChallenges()". I'd like my API to have a method with the same name, but since I'm including the functions file, it causes an error saying that I can't redefine that function. I'd really rather not rename the function in the functions file since i'd have to go all through my existing code and change the references. Is there a way to have the name of the function in PHP be something like"GetChallengesApi()" and yet have SOAP be able to run it as just GetChallenges()?