Is there any way to use multiple yml file with nelmio_api_doc in symfony 3 with NelmioApiDocBundle?

Viewed 2541

NelmioApiDocBundle is allowing only single configuration file as .yml as.

nelmio_api_doc:
  routes:
    path_patterns: # an array of regexps
      - ^/api
  documentation:
    paths:
      /api/login_check:
      ...
      /api/refresh_token:
      ...

But I have more then 200 URL to use and all for different Bundles. it would working properly but hard to handle all in same file.

So if anyone has solution to divide "paths" as different separate files.

4 Answers

Problem solved! :-)

One of Mine friend has a great idea to resolve this problem. actually, this is not the proper solution, but I this is the only way to solve this problem.

We create "api_index.yaml"

export_path: '/config/packages/api_doc.yaml'

import_paths:
  - "@DomCoreBundle/Resources/config/api_doc/api_base_doc.yaml"
  - "@DomCmsBundle/Resources/config/api_doc/static_page_path_doc.yaml"
  - "@DomEntityBundle/Resources/config/api_doc/category_path_doc.yaml"
  - "@DomCmsBundle/Resources/config/api_doc/carousel_path_doc.yaml"
  - "@DomQuickLinkBundle/Resources/config/api_doc/quick_link_path_doc.yaml"
  - "@DomUserBundle/Resources/config/api_doc/user_path_doc.yaml"
  - "@DomUserBundle/Resources/config/api_doc/dealer_path_doc.yaml"
  ...

Then we create a Symfony command(script) which read each "import_paths" file and append content in "export_path" file.

$this->io = new SymfonyStyle($input, $output);
$path = $this->kernel->locateResource('@FaCoreBundle/Resources/config/api_index.yaml');
$paths = Yaml::parse(file_get_contents($path));

if (array_key_exists('import_paths', $paths)) {
    $contentLength = $this->loadFilesByPath($input, $output, $paths);
    if ($input->getOption('watch')) {
        $contentLengthNew = [];
        while (true) {
            foreach ($paths['import_paths'] as $path) {
                $ymlPath = $this->kernel->locateResource($path);
                $contentLengthNew[$ymlPath] = md5((file_get_contents($ymlPath)));
            }

            if (!empty(array_diff($contentLength, $contentLengthNew)) || count($contentLength) != count($contentLengthNew)) {
                $diff = array_diff($contentLengthNew, $contentLength);
                if (!empty($diff)) {
                    $this->io->writeln(sprintf('<comment>%s</comment> <info>[file+]</info> %s', date('H:i:s'), current(array_keys($diff))));
                }

                $contentLength = $this->loadFilesByPath($input, $output, $paths);
            }

            sleep($input->getOption('period'));
        }
    }
}

A simply way is to read yaml files from a not autoload area, merge the content and write a single file that will be loaded.

SF 4.x

/config
    /NELMIOApiDocDefinitions // out of autowire
        /one.yaml
        /two.yaml
    /packages
        /_NELMIOApiDocDefinitions.yaml // file_put_content()

one.yaml

nelmio_api_doc:
    areas:
        path_patterns:
            - /one
    documentation:
        tags:
            - { name: One, description: '...' }
        paths:
            /onepath/:
                ...

Kernel.php

protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
{
    $this->mergeNELMIOApiDocYamlDefinitions();
    ...
}

private function mergeNELMIOApiDocYamlDefinitions()
{
    // dev, prod, ...
    $kernelEnvironnement = $this->getEnvironment();

    // No need to rebuild definitions in production
    if ($kernelEnvironnement == 'prod')
        return;

    // Path to the configuration directory
    $confDir = $this->getProjectDir() . '/config';

    // Path to the documentations files to merge
    $yamlDefinitionsDirectory = $confDir . '/NELMIOApiDocDefinitions';

    // Get the files to merge (without dots directories)
    $yamlDefinitionsFiles = array_diff(scandir($yamlDefinitionsDirectory), ['.', '..']);

    // Read definitions files and merge key with theirs values
    $mergedDefinitions = [];
    foreach ($yamlDefinitionsFiles as $yamlDefinitionFile) {
        $yamlFileContent = Yaml::parseFile($yamlDefinitionsDirectory . '/' . $yamlDefinitionFile);
        $mergedDefinitions = array_merge_recursive($mergedDefinitions, $yamlFileContent);
    }

    // Build the YAML
    $yaml = Yaml::dump($mergedDefinitions);

    // Write the YAML into a single file to be loaded by Symfony
    file_put_contents($confDir . '/packages/_NELMIOApiDocDefinitions.yaml', $yaml);
}

Problem solved with

config/packages/nelmio.yaml

imports:
 - {resource: '../nelmio/default.yaml'}
 - {resource: '../nelmio/v1.yaml'}

config/nelmio/default.yaml

nelmio_api_doc:
    areas:
        default:
            path_patterns: [ ^/default/ ]
            documentation:
                info:
                    title: Default

config/nelmio/v1.yaml

nelmio_api_doc:
    areas:
        default:
            path_patterns: [ ^/v1/ ]
            documentation:
                info:
                    title: V1
Related