How to Install Swagger on Symfony 4? - symfony

I started to install like this:
https://symfony.com/doc/4.x/bundles/NelmioApiDocBundle/index.html
Step 1.
`composer require nelmio/api-doc-bundle` - Thats OK
Step 2.
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = [
new Nelmio\ApiDocBundle\NelmioApiDocBundle(),
];
}
}
But I have no AppKernel extends Kernel. I **just have Kernel** with
`$contents = require $this->getProjectDir().'/config/bundles.php';`
So I added into **/config/bundles.php**
Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true],
Step 3.
I added into config/routes.yaml
# config/routes.yaml
app.swagger_ui:
path: /api/doc
methods: GET
defaults: { _controller: nelmio_api_doc.controller.swagger_ui }
Step 4.
I created config/packages/nelmio_api_doc.yaml with
nelmio_api_doc:
areas:
path_patterns: # an array of regexps
- ^/api(?!/doc$)
host_patterns:
- ^api\.
After that I should see Swagger's page at mysite/api/doc
But i see only white page with link 'NelmioApiDocBundle' at github
What I did wrong?

I ran:
bin/console assets:install --symlink
and it's now working.

You need to specify areas in your nelmio_api_doc
nelmio_api_doc:
documentation:
info:
title: My App
description: This is an awesome app!
version: 1.0.0
areas: # to filter documented areas
path_patterns:
- ^/api(?!/doc$) # Accepts routes under /api except /api/doc
- ^/secured/project(?!/doc$) # Accepts routes under /api except /api/doc

Related

Symfony League CommonMarkdown customize ExternalLinksExtension

How is the correct way to customize the ExternalLinksExtension in the services.yml on Symfony 4/5/6.1?
according to official documentation ExternalLinksExtension it is assumed that the configuration parameters must be passed to the Enviroment. However, the Enviroment is not a service and is not instantiated as a service, even if it is declared as such. It is instantiated directly from the function that initializes the CommonMarkdown bundle, where empty arguments are passed on to it.
By making a custom extension there is also no way to modify the configuration of the current environment. Inheriting from ExtensionInterface does not give you such access.
The current way I do it is to copy all the content of the native extension ExternalLinksExtension and in the configureSchema method merge the configuration of the current environment with custom arguments.
class ExternalLinksExtension implements ConfigurableExtensionInterface
{
public function configureSchema(ConfigurationBuilderInterface $builder): void
{
$applyOptions = [
ExternalLinkProcessor::APPLY_NONE,
ExternalLinkProcessor::APPLY_ALL,
ExternalLinkProcessor::APPLY_INTERNAL,
ExternalLinkProcessor::APPLY_EXTERNAL,
];
$builder->addSchema('external_link', Expect::structure([
'internal_hosts' => Expect::type('string|string[]'),
'open_in_new_window' => Expect::bool(false),
'html_class' => Expect::string()->default(''),
'nofollow' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_NONE),
'noopener' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_EXTERNAL),
'noreferrer' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_EXTERNAL),
]));
//this is where I pass custom arfuments
$builder->merge([
'external_link' => [
'internal_hosts' => ["localhost"],
'open_in_new_window' => true,
'html_class' => 'external-link',
'nofollow' => '',
'noopener' => 'external',
'noreferrer' => 'external',
]
]);
}
public function register(EnvironmentBuilderInterface $environment): void
{
$environment->addEventListener(DocumentParsedEvent::class, new ExternalLinkProcessor($environment->getConfiguration()), -50);
}
}
This way it works for me, but I believe that it is not convenient to have to be copying all the extensions that you want to customize or that you must make this type of hacks, there should be another more direct method of configuration.
In my service.yml file
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller/'
tags: ['controller.service_arguments']
League\CommonMark\Environment\Environment:
public: true
arguments:
-
external_link:
-
internal_hosts: [ "localhost" ]
open_in_new_window: true
html_class: "external-link"
nofollow: ""
noopener: "external"
noreferrer: "external"
League\CommonMark\Extension\Table\TableExtension:
tags:
- { name: twig.markdown.league_extension }
League\CommonMark\Extension\Autolink\AutolinkExtension:
tags:
- { name: twig.markdown.league_extension }
League\CommonMark\Extension\Strikethrough\StrikethroughExtension:
tags:
- { name: twig.markdown.league_extension }
App\Service\League\CommonMark\ExternalLinksExtension:
arguments: ... ##arguments here also doesnt work with the native extension
tags:
- { name: twig.markdown.league_extension }
the twig docs, mentions that the extensions must go with the tag twig.markdown.league_extension
According to this discussion and the PR that followed, since Twig 3.3.5, the Twig/Extra-Bundle contains a factory that simply relies on declaring the desired extensions in services.yaml, with the specific tag twig.markdown.league_extension:
# services.yaml
services:
League\CommonMark\Extension\Table\ExternalLinksExtension:
tags: [ 'twig.markdown.league_extension' ]
This worked for me, with TableExtension and my twig/extra-bundle v3.3.8.

Behat test error after upgrade to Behat 3.3.1 - Too few arguments to function FeatureContext

I'm upgrading my Drupal 8 site to 8.4.8 which automatically upgrade behat to 3.3.1
I just found out my Behat test is no longer work and stuck on the following errors.
Here's the error
ArgumentCountError: Too few arguments to function Drupal\FeatureContext::__construct(), 0 passed and exactly 1 expected in /var/www/mywebsite/tests/behat/features/bootstrap/Drupal/FeatureContext.php
Here's my constructor in FeatureContext.php file
/**
* FeatureContext class defines custom step definitions for Behat.
*/
class FeatureContext extends PageObjectContext implements SnippetAcceptingContext {
private $fourZeroFour;
public function __construct(FourZeroFour $fourZeroFour) {
$this->fourZeroFour = $fourZeroFour;
}
Here's my behat.yml
imports:
- behat.yml
local:
suites:
default:
paths:
# Set features to repo root so that .feature files belonging to contrib
# modules, themes, and profiles can be discovered.
features: /var/www/mywebsite
bootstrap: /var/www/mywebsite/tests/behat/features/bootstrap
contexts:
- Drupal\FeatureContext:
parameters:
environment:
# absolute path to local directory to store screenshots - do not include trailing slash
screenshot_dir: /var/www/mywebsite/reports
- Drupal\DrupalExtension\Context\DrupalContext
- Drupal\DrupalExtension\Context\MinkContext
- Drupal\DrupalExtension\Context\MessageContext
- Drupal\DrupalExtension\Context\DrushContext
It turned out, a part of my configuration was missing from behat.yml file.
The part was missing:
SensioLabs\Behat\PageObjectExtension:
namespaces:
page: Page
element: Page\Element

How to disable Nelmio UI in production?

Is there a way to turn off all of the Nelmio Swagger UI docs? In production I want the outside world to see nothing at the following URLs, but in dev they should display useful docs & sandbox as normal:
http://ourserver.com/api/doc
http://ourserver.com/api-docs
http://ourserver.com/api-docs/*
Seems like there should be an easy switch for this in the Nelmio config, but I haven't found it. My company is using the Nelmio API Doc bundle in Symfony to develop APIs for a non-public API. The API server is exposed to the public, but we're not interested in publishing its usage to the world.
#gp_sflover's comment got me on the right track, but there's more to it than just disabling NelmioApiDocBundle on prod in AppKernel.php. Configs & routes that refer to Nelmio will generate errors until you move them into dev-specific files. The following change in app/AppKernel.php was the first step:
public function registerBundles()
{
$bundles = [
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
...
// new Nelmio\ApiDocBundle\NelmioApiDocBundle(), // <-- REMOVED FROM HERE
new Nelmio\CorsBundle\NelmioCorsBundle(),
new AppBundle\AppBundle(),
];
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
$bundles[] = new Nelmio\ApiDocBundle\NelmioApiDocBundle(); // <-- ADDED HERE
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle();
...
To eliminate the config errors, I had to move the following stuff out of app/config/config.yml and into config_dev.yml:
# nelmio Configuration
nelmio_api_doc:
sandbox:
enabled: true
name: 'DLAP API Bridge'
swagger:
...
cache:
enabled: false
Likewise, the following stuff came out of app/config/routing.yml and moved to routing_dev.yml:
NelmioApiDocBundle:
resource: "#NelmioApiDocBundle/Resources/config/routing.yml"
prefix: /api/doc
nelmio_api_swagger:
resource: "#NelmioApiDocBundle/Resources/config/swagger_routing.yml"
resource: null
prefix: /api-docs
Now with symfony4 and flex you can install the bundle normally
composer require nelmio/api-doc-bundle
(So it won't be set as a require-dev depandency in your composer.json)
Now you change the setting in the project/config/bundles.php to:
Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['dev' => true]
So you don't get errors (eg from annotations), but it wont be loaded from Kernel.php
For disabling the Nelmio api-doc-bundle on specific environment, after some investigation, I ended up doing the following:
only enable the bundle on your target environment, i.e. on project/config/bundles.php have:
Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['dev' => true]
put the config annotation on env specific (put nelmio_api_doc.yaml inside ./config/packages/dev/)
put the route file nelmio_api_doc.yaml inside ./config/routes/dev (instead of being in the ./config/routes), otherwise, if you call the route for another environment which doens't have the bundle loaded, instead of 404, you will see 500)
not loading the bundle in config/bundles.php throws an exception in Symfony 4.3 with NelmioApiDocBundle Version 3:
There is no extension able to load the configuration for "nelmio_api_doc"
I ended up disabling the route for the api docs with a redirect in the environment, which needed to be disabled (prod):
#config/routes/prod/nelmio_api_doc.yaml
app.swagger:
path: /api/doc.json
methods: GET
defaults:
_controller: FrameworkBundle:Redirect:urlRedirect
path: /
permanent: true
app.swagger_ui:
path: /api/doc
methods: GET
defaults:
_controller: FrameworkBundle:Redirect:urlRedirect
path: /
permanent: true

Symfony - Cache (Memcache) in a controller

How do you using caching directly in a controller without queries (orm cache drivers)?
http://symfony.com/doc/current/reference/configuration/doctrine.html#caching-drivers
The documents only mention caching with doctrine but there are times it's needed without doctrine. They don't appear to mention anything on this or is it one of the view things Symfony doesn't have a wrapper for?
Install and use DoctrineCacheBundle:
Add this bundle to your project as a composer dependency:
composer require doctrine/doctrine-cache-bundle
Add this bundle in your application kernel:
// app/AppKernel.php
public function registerBundles()
{
// ...
$bundles[] = new \Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle();
return $bundles;
}
Configure it:
# app/config/config.yml
doctrine_cache:
providers:
my_apc_metadata_cache:
type: apc
namespace: metadata_cache_ns
my_apc_query_cache:
namespace: query_cache_ns
apc: ~
memcache:
servers:
memcache01: 11211
Use it:
$apcCache = $this->container->get('doctrine_cache.providers.my_apc_cache');
$memcacheCache = $this->container->get('doctrine_cache.providers.memcache');
Read more: https://symfony.com/doc/current/bundles/DoctrineCacheBundle/usage.html
Full providers reference: http://symfony.com/doc/current/bundles/DoctrineCacheBundle/reference.html

symfony2 Unable to find controller

I am trying to start on Symfony2 but ran into a problem right away following the Symfony 2 "the book" part "Creating pages in Symfony 2":
I did this:
Created the bundle
php app/console init:bundle "Acme\StudyBundle" src
*Added the namespace in app/autoload.php *
$loader->registerNamespaces(array(
'Acme' => __DIR__.'/../src',
));
Initialized the bundle
// app/AppKernel.php
public function registerBundles()
{
$bundles = array(
// ...
new Acme\StudyBundle\AcmeStudyBundle(),
);
// ...
return $bundles;
}
Created the routes in app/config.routing.yml and src/Acme/StudyBundle/Resources/config/routing.yml
# app/config/routing.yml
homepage:
pattern: /
defaults: { _controller: FrameworkBundle:Default:index }
hello:
resource: "#AcmeStudyBundle/Resources/config/routing.yml"
# src/Acme/StudyBundle/Resources/config/routing.yml
hello:
pattern: /hello/{name}
defaults: { _controller: AcmeStudyBundle:Hello:index }
Created the controller
// src/Acme/StudyBundle/Controller/HelloController.php
namespace Acme\StudyBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
class HelloController
{
public function indexAction($name)
{
return new Response('<html><body>Hello '.$name.'!</body></html>');
}
}
When I load the page: http://localhost/app_dev.php/hello/Ryan Symfony gives me an exception:
Unable to find controller "AcmeStudyBundle:Hello" - class "Acme\StudyBundle\Controller\HelloController" does not exist.
I got over the code several times but cannot find anything wrong.
just add
<?php
in the beginning of your controller file : src/Acme/StudyBundle/Controller/HelloController.php
it's solved the problem to me.
Afaik there is a discussion going on within the Symfony 2.0 dev guys in what places they should keep the "Bundles" extension.
I've just grabbed the latest version of Symfony via Git and followed your code 1:1.
I got various error messages too but when I changed...
in src/Acme/StudyBundle/Resources/config/routing.yml
defaults: { _controller: AcmeStudyBundle:Hello:index }
to
defaults: { _controller: AcmeStudy:Hello:index }
app/config/routing.xml
resource: "#AcmeStudyBundle/Resources/config/routing.yml"
to
resource: "#AcmeStudy/Resources/config/routing.yml"
...i got a pretty "Hello Ryan" in the browser.
Hope this helps!
You are probably running PR9. Update to PR11(latest), and I would bet this gets resolved. Symfony devs removed the 'Bundle' suffix in PR9, but added it back again shortly there after.
Also, Symfony devs keep an Update log that I find extremely helpful.

Resources