Open 4n70w4 opened 4 years ago
My point of view is that you can generate the packages in the same directory with the same main namespace then namespace each microservice under the main namespace such as:
|_ src/
|__ MyMicroServices/
|___ MicroService1/
|____ StructType/
|____ ServiceType
|_____ Call.php
|_____ Get.php
|_____ etc.
|____ ClassMap.php
|___ MicroService2/
|____ StructType/
|____ ServiceType
|_____ Set.php
|_____ Do.php
|_____ Set.php
|_____ Update.php
|_____ etc.
|____ ClassMap.php
|___ etc.
|_ vendor/
|_ composer.json
Would it match your needs?
In this case, I have to run the generate:package
command 20 times with a different set of parameters. And also run 20 commands when updating services. This can be solved through bash scripts or ansible.
And also manually edit composer.json
when adding or removing microservices. But I have no ideas how to automate it.
In this case, I have to run the
generate:package
command 20 times with a different set of parameters. And also run 20 commands when updating services. This can be solved through bash scripts or ansible.And also manually edit
composer.json
when adding or removing microservices. But I have no ideas how to automate it.
Indeed, this can seem overaded but this is the way as it is now.
You composer.json file does not have to change for each update as only the main namespace, MyMicroServices, has to be defined within it as every package should be a sub namespace MyMicroServices\MicroService1, MyMicroServices\MicroService2, etc...
I still do not understand with what parameters the generator should be called to get such a structure.
My usercase. I generate packages via wsdltophp
and publish them as is in my selfhosted bitbucket server
.
Next I require those packages in projects via composer
.
With a bunch of microservices, the problem of creating many small repositories, generating packages, publishing, and require. Too much fuss.
It would be very convenient to be able to generate one large package with several such microservices.
From my point of view, you would need to create one git project containing all the generated package under the same namespace and then require this unique dependency from your other project.
I currently do this soort of thing using a PHP script (also possible with a command line script):
$rootDir = dirname(__DIR__).'/public_html';
require_once $rootDir.'/vendor/autoload.php';
use WsdlToPhp\PackageGenerator\ConfigurationReader\GeneratorOptions;
use WsdlToPhp\PackageGenerator\Generator\Generator;
// define all my WSDL and their package destination
$wsdls = [
$rootDir.'/wsdl/provider1/service1/service.wsdl' => [
'src' => $rootDir.'/src/ProviderService/Provider1/Service1/',
'ns' => 'ProviderService\Provider\Service1',
],
$rootDir.'/wsdl/provider1/service2/service.wsdl' => [
'src' => $rootDir.'/src/ProviderService/Provider1/Service2/',
'ns' => 'ProviderService\Provider\Service2',
],
$rootDir.'/wsdl/provider1/service3/service.wsdl' => [
'src' => $rootDir.'/src/ProviderService/Provider1/Service3/',
'ns' => 'ProviderService\Provider\Service3',
],
$rootDir.'/wsdl/provider2/service1/service.wsdl' => [
'src' => $rootDir.'/src/ProviderService/Provider2/Service1/',
'ns' => 'ProviderService\Provider2\Service1',
],
// etc.
];
// clean existing files, avoid having not useful files anymore
exec('rm -rf '.$rootDir.'/src/ProviderService/Provider1/Service1/');
exec('rm -rf '.$rootDir.'/src/ProviderService/Provider1/Service2/');
exec('rm -rf '.$rootDir.'/src/ProviderService/Provider1/Service3/');
exec('rm -rf '.$rootDir.'/src/ProviderService/Provider2/Service1/');
// loop over each WSDL and generate its package
foreach ($wsdls as $wsdl => $settings) {
// Options definition: the configuration file parameter is optional
$options = GeneratorOptions::instance();
$options
->setOrigin($wsdl)
->setDestination($settings['src'])
->setNamespace($settings['ns'])
// ->setSoapClientClass(SoapClientBase::class)
->setStandalone(false) // no composer.json needed
->setGenerateTutorialFile(false) // no tutorial.php filke needed
->setSrcDirname(''); // no src folder needed for the generated package
// Generator instanciation
$generator = new Generator($options);
// Package generation
$generator->generatePackage();
fwrite(STDERR, PHP_EOL.$settings['src'].' / '.$settings['ns']);
}
Within the composer.json file, I put:
"autoload": {
"psr-4": {
"ProviderService\\": "src/ProviderService"
}
},
I then use any service from the ProviderService
namespace.
@mikaelcom thank! This way looks good.
I made my own fully automated solution to generate the final composer package, ready to commit, without any manual corrections. Hope this will help to someone:
<?php
require __DIR__ . '/vendor/autoload.php';
use WsdlToPhp\PackageGenerator\ConfigurationReader\GeneratorOptions;
use WsdlToPhp\PackageGenerator\Generator\Generator;
$destination = __DIR__ . '/../your-company-wsdl'; // replace it with the directory of generated package
$namespace = 'Your\Company\Wsdl'; // replace it with your namespace
$package = 'username/your-company-wsdl'; // replace it with the Composer package name
$services = [ // Replace it with your list of service names and WSDL URLs
'Inventory2' => 'https://********.com/wsdl/inventory2.0.0RC4/InventoryService.wsdl',
'Invoice' => 'https://********.com/wsdl/InvoiceService.wsdl',
'PurchaseOrder' => 'https://********.com/wsdl/POService.wsdl',
'OrderShipmentNotification' => 'https://********.com/wsdl/OrderShipmentNotificationService.wsdl',
'OrderStatus' => 'https://********.com/wsdl/OrderStatusService.wsdl',
'PricingAndConfiguration' => 'https://********.com/wsdl/PricingAndConfiguration.wsdl',
'ProductData' => 'https://********.com/wsdl/ProductDataService.wsdl',
];
$options = GeneratorOptions::instance();
$options->setDestination($destination)
->setOptionValue(GeneratorOptions::COMPOSER_SETTINGS, [
'description' => 'Your Company WSDL Client',
'require' => [ // replace it with PHP version you need or add some dependencies if your package contains manually created classes
'php' => '>=8.0',
],
])
->setNamespaceDictatesDirectories(false)
->setComposerName($package)
->setGenerateTutorialFile(false);
$composer = [];
foreach ($services as $serviceName => $wsdlUrl) {
echo "\nGenerate {$serviceName}\n\n";
$options->setOrigin($wsdlUrl)
->setSrcDirname("src/{$serviceName}")
->setNamespace($namespace . '\\' . $serviceName);
$generator = new Generator($options);
$generator->generatePackage();
$composer = array_replace_recursive($composer, json_decode(file_get_contents($destination . '/composer.json'), true));
}
echo "\nFixing autoload in composer.json\n\n";
$composer['autoload']['psr-4'] = [
$namespace . '\\' => "src/",
];
file_put_contents($destination . '/composer.json', json_encode($composer, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n");
echo "Well done!\n";
It will produce the structure like:
src
Inventory2
...
Invoice
...
OrderShipmentNotification
...
OrderStatus
...
PricingAndConfiguration
...
ProductData
...
PurchaseOrder
...
vendor
composer.json
composer.lock
The composer.json file will look like:
{
"name": "username/your-company-wsdl",
"description": "Your Company WSDL Client",
"require": {
"php": ">=8.0",
"ext-dom": "*",
"ext-mbstring": "*",
"ext-soap": "*",
"wsdltophp/packagebase": "~5.0"
},
"autoload": {
"psr-4": {
"Your\\Company\\Wsdl\\": "src/"
}
}
}
Please tell me what do you think about my solution. I'm looking forward to comments.
I reworked my previous solution for automatic generation of the Composer package with a multiple WSDL services. It works exactly the same and makes the same folder and namespace structure. But now the generation script is a part of this package. It makes easier to regenerate the code if something changed in the future, because no need to search the script that generated this package maybe several years ago.
You start creating Composer package with running this command in an empty folder of new Composer package:
composer require --dev wsdltophp/packagegenerator
It will make a simplest composer.json
and install necessary vendor packages. Then place this PHP script in the root of this Composer package and execute:
<?php
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\Console\Input\ArrayInput;
use WsdlToPhp\PackageGenerator\ConfigurationReader\GeneratorOptions;
use WsdlToPhp\PackageGenerator\Generator\Generator;
$destination = __DIR__;
$packageName = 'username/your-company-wsdl';
$packageDescription = 'Your Company WSDL Client';
$namespace = 'Your\Company\Wsdl';
// List of WSDL services in result Composer package [ 'Source-SubFolder' => 'WSDL-URL', ... ]
$services = [
'Inventory2' => 'https://********.com/wsdl/inventory2.0.0RC4/InventoryService.wsdl',
'Invoice' => 'https://********.com/wsdl/InvoiceService.wsdl',
'PurchaseOrder' => 'https://********.com/wsdl/POService.wsdl',
'OrderShipmentNotification' => 'https://********.com/wsdl/OrderShipmentNotificationService.wsdl',
'OrderStatus' => 'https://********.com/wsdl/OrderStatusService.wsdl',
'PricingAndConfiguration' => 'https://********.com/wsdl/PricingAndConfiguration.wsdl',
'ProductData' => 'https://********.com/wsdl/ProductDataService.wsdl',
];
$options = (GeneratorOptions::instance())
->setDestination($destination)
->setNamespaceDictatesDirectories(false)
->setGenerateTutorialFile(false)
->setStandalone(false);
foreach ($services as $serviceName => $wsdlUrl) {
echo "Generate {$serviceName}\n";
$options->setOrigin($wsdlUrl)
->setSrcDirname("src/{$serviceName}")
->setNamespace($namespace . '\\' . $serviceName);
$generator = new Generator($options);
$generator->generatePackage();
}
echo "Write composer.json\n";
$composer = [
'name' => $packageName,
'description' => $packageDescription,
'require' => [ // replace it with PHP version you need or add some dependencies if your package contains manually created classes
'php' => '>=8.0',
'ext-dom' => '*',
'ext-mbstring' => '*',
'ext-soap' => '*',
'ext-ctype' => '*',
'wsdltophp/packagebase' => '~5.0',
],
'require-dev' => [
'wsdltophp/packagegenerator' => '^4.1',
],
'autoload' => [
'psr-4' => [
$namespace . '\\' => 'src/',
],
],
];
file_put_contents($destination . '/composer.json', json_encode($composer, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR) . "\n");
echo "Execute \"composer update\"\n";
$composer = new \Composer\Console\Application();
$composer->setAutoExit(false);
$composer->run(new ArrayInput([
'command' => 'update',
'--optimize-autoloader' => true,
'--working-dir' => $destination,
]));
echo "Well done!\n";
Now your package is ready to commit and publish. Later you can run this script again to make sure all is up-to-date.
Hi! One vendor provides its services as microservices. Approximately 20 microservices with 1-2 methods. Separate wsdl for each service.
It doesn't seem like a good idea to generate 20 packages for each service and include 20 dependencies.
I would like to be able to generate 1 package from an unlimited number of wsdl.