Command created issue - symfony

I have a command which is in production already and I suspect not to be working. The dev who worked on it is not there anymore. So I come here to find some help.
There is 2 things I don't understand.
1- The command name is inside the Controller folder... ApiController but it extends ContainerAwareCommand so I guess this is fine...
2- The command is not find, but might be related to the first point.
When I try: php bin/console app:commandTest
I've got his error in console:
There are no commands defined in the "app" namespace.
class ApiController extends ContainerAwareCommand
{
protected function configure () {
$this->setName('app:commandTest');
$this->setDescription("Some desc");
$this->setHelp("Some help");
}
public function execute(InputInterface $input, OutputInterface $output)
{ // whatever }
}
Peoples told me this code worked when the previous dev was working on it...but I can't see how actually. I hope you can see how to do it or how to make it work.
Thanks.
EDIT: What I tried to add to my services.yaml but it's not working
services:
app.command.api_controller:
class: AppBundle\Controller\ApiController
arguments: ["%command.default_name%"]
tags: - { name: console.command }
config.yaml
imports:
- { resource: services.yml }
But doing this there is an error
The file "/var/www/unitimmo/UniTimmo/app/config/services.yml" does not contain valid YAML

Related

Symfony: redirecting to homepage after encountering an error

I've recently started learning Symfony, and I've been trying to make an app that will redirect user to the homepage after encountering an error (For the sake of the question, it can be error 404) However, I had problems with finding a way to do so.
Before, I used TwigErrorRenderer as described in Symfony documentation to handle my errors, but it only explains how to redirect to new error pages created by myself. Could somebody help me with this issue?
It is generally not a good idea to do this, because you want to tell the user that their request was not processed due to an error, or that they accessed non-existing page.
But if you really want to, you can achieve it with this Event Listener.
// src/EventListener/ExceptionListener.php
<?php
declare(strict_types=1);
namespace App\EventListener;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\Routing\RouterInterface;
final class ExceptionListener
{
private RouterInterface $router;
public function __construct(RouterInterface $router)
{
$this->router = $router;
}
public function onKernelException(ExceptionEvent $event): void
{
// You should log the exception via Logger
// You can access exception object via $event->getThrowable();
$homepageRoute = $this->router->generate('homepage', [], RouterInterface::ABSOLUTE_URL);
$response = new RedirectResponse($homepageRoute);
$event->setResponse($response);
}
}
You also need to register the Event Listener in your services.yaml.
services:
App\EventListener\ExceptionListener:
tags:
- { name: kernel.event_listener, event: kernel.exception }
Please note the following:
The Event Listener assumes that your Homepage route is called homepage;
you really should log the exception or you will lose logs about all of them;
as stated at the top of this answer, this is not a good approach to deal with exceptions.

Invalid upload directory for EasyAdmin ImageField once deployed on Heroku

I work on a Symfony 6.0.9 website with EasyAdmin to handle the administration panel.
I've got an entity User and an entity MediaObject that can be an image for example. The User has a property $profilePicture which is a MediaObject.
In EasyAdmin, I've got a UserCrudController like that :
class UserCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return User::class;
}
public function configureCrud(Crud $crud): Crud
{
...
}
public function configureFields(string $pageName): iterable
{
return [
...
FormField::addPanel('Pictures')->renderCollapsed(),
ImageField::new('profilePicture.filePath')
->setBasePath('/media')
->setUploadDir('public/media')
->setUploadedFileNamePattern('profilePicture.[extension]')
->setLabel('Profile picture')
->setColumns(4),
...
];
}
}
In my app/config/services.yaml file, I've set :
parameters:
app.path.media_object: /media
In my app/config/packages/vich_uploader.yaml file, I've set :
vich_uploader:
db_driver: orm
mappings:
media_object:
uri_prefix: '%app.path.media_object%'
upload_destination: '%kernel.project_dir%/public%app.path.media_object%'
When I'm in my localhost (so in dev env), everything works just fine.
When I build and deploy on Heroku, I works fine. But when I try to edit an user, I've got this error message in Heroku's logs :
[critical] Uncaught PHP Exception Symfony\Component\OptionsResolver\Exception\InvalidArgumentException: "An error has occurred resolving the options of the form "EasyCorp\Bundle\EasyAdminBundle\Form\Type\FileUploadType": Invalid upload directory "/app/public/media/" it does not exist or is not writable." at /app/vendor/symfony/form/ResolvedFormType.php line 93
I don't understand what I've done wrong. Thanks for helping me ! ;)

symfony 4 : How to get "/public" from RootDir

I have an image under the public folder.
How can I get my image directory in symfony4 ?
In symfony 3, it's equivalent is :
$webPath = $this->get('kernel')->getRootDir() . '/../web/';
It is a bad practice to inject the whole container, just to access parameters, if you are not in a controller. Just auto wire the ParameterBagInterface like this,
protected $parameterBag;
public function __construct(ParameterBagInterface $parameterBag)
{
$this->parameterBag = $parameterBag;
}
and then access your parameter like this (in this case the project directory),
$this->parameterBag->get('kernel.project_dir');
Hope someone will find this helpful.
Cheers.
You can use either
$webPath = $this->get('kernel')->getProjectDir() . '/public/';
Or the parameter %kernel.project_dir%
$container->getParameter('kernel.project_dir') . '/public/';
In Controller (also with inheriting AbstractController):
$projectDir = $this->getParameter('kernel.project_dir');
In config/services.yaml:
parameters:
webDir: '%env(DOCUMENT_ROOT)%'
In your controller:
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
...
public function yourFunction(Parameterbag $parameterBag)
{
$webPath = $parameterBag->get('webDir')
}
If you need to access a directory within public, change the last line to the following:
$webPath = $parameterBag->get('webDir') . '/your/path/from/the/public/dir/'
You can inject KernelInterface to the service or whatever and then get the project directory with $kernel->getProjectDir():
<?php
namespace App\Service;
use Symfony\Component\HttpKernel\KernelInterface;
class Foo
{
protected $projectDir;
public function __construct(KernelInterface $kernel)
{
$this->projectDir = $kernel->getProjectDir();
}
public function showProjectDir()
{
echo "This is the project directory: " . $this->projectDir;
}
}
Starting from Symfony 4.3 we can generate absolute (and relative) URLs for a given path by using the two methods getAbsoluteUrl() and getRelativePath() of the new Symfony\Component\HttpFoundation\UrlHelper class.
New in Symfony 4.3: URL Helper
public function someControllerAction(UrlHelper $urlHelper)
{
// ...
return [
'avatar' => $urlHelper->getAbsoluteUrl($user->avatar()->path()),
// ...
];
}
All above answers seems valid, but I think it's simplier if you configure it as parameter in services.yaml
If you need to use it in serveral services, you can bind it like this:
# services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
bind:
$publicDir: "%kernel.project_dir%/public"
# src/Services/MyService.php
class MyService
{
public function __construct(
private string $publicDir,
) {
}
// …
}
This way, this is configured at one place only, and if later you decide to change /public to something else, you will have to change it only in .yaml file.
If you don't need the root directory but a subdirectory, it might be better to define the final target path: This way you will be more flexible if you need later to move only that directory, like $imageDir or $imagePath (depends if you will use the full directory or only the public path).
Note also the default public path is defined in composer.json file, in the extra.public-dir key

In Symfony2 how can I use a Service within a Factory class?

I am trying to setup a Symfony implementation of this PHP library for Chargify https://github.com/johannez/chargify
I'm getting a bit lost working out the best / proper way to set it all up.
I think I need to setup Guzzle as a service, then create a Chargify factory and have that added as a service.
My problem is that in the factory class, when I try and use the Guzzle service I get a fatal error
Fatal error: Using $this when not in object context in /symfony/src/Acme/ChargifyBundle/Factory/ChargifyFactory.php on line 8
This is my Factory class
<?php
namespace Acme\ChargifyBundle\Factory;
class ChargifyFactory implements ChargifyFactoryInterface
{
public static function build($type)
{
$client = $this->get('chargify.guzzle.client');
$className = 'Chargify\\Controller\\' . ucfirst($type);
if (class_exists($className)) {
return new $className($client);
}
else {
throw new Exception("Invalid controller type given.");
}
}
}
If it's useful to see some config, this is my services.yml for the bundle
services:
chargify.guzzle.client.curl_auth:
class: %guzzle.plugin.curl_auth.class%
arguments:
api_key: %chargify_api_key%
chargify.guzzle.client:
class: %guzzle.client.class%
tags:
- { name: guzzle.client }
calls:
- [setBaseUrl, [%chargify_domain%]]
- [addSubscriber, [#chargify.guzzle.client.curl_auth]]
argument: %chargify_domain%
chargify.factory:
class: Acme\ChargifyBundle\Factory\ChargifyFactory
arguments:
- ["type"]
chargify.customer:
class: Acme\ChargifyBundle\Controller\CustomerController
factory_class: Acme\ChargifyBundle\Factory\ChargifyFactory
factory_method: build
arguments:
type: "customer"
How can I use the guzzle client in the Factory with out using
$client = $this->get('chargify.guzzle.client');
EDIT:
I have changed the code as per #alex's answer, but I'm still getting an error. I think this is because the function is static. I've looked though the documents, but I can't see where I can setup a factory without a static function, and when I get rid of static I get a different error.
Runtime Notice: Non-static method Acme\ChargifyBundle\Factory\ChargifyFactory::build() should not be called statically, assuming $this from incompatible context
That is being thrown from some generated code
protected function getChargify_CustomerService()
{
return $this->services['chargify.customer'] = \Acme\ChargifyBundle\Factory\ChargifyFactory::build('customer');
}

Symfony2 Composer post-install-cmd

I need to install an symfony2 bundle over the composer and do some stuff after the install process. So for the "stuff" after the install i add one line to the "post-install-cmd" in the composer.json
ServiceBundle\\Core\\Platform::registerService
and it calls the function, everything fine
public static function registerService(Event $event) {
//some stuff
exit;
}
The command I use:
php composer.phar update serviceplatform/bundles/poll
Now my question:
Is it possible to get the name "serviceplatform/bundles/poll" or pass any arguments to the statement? I need the path from the bundle after the install.
extra node is what you're looking for - https://getcomposer.org/doc/04-schema.md#extra
In your composer.json:
"extra": {
"your-parameter": "serviceplatform/bundles/poll"
}
Then, in your ServiceBundle\Core\Platform::registerService:
public static function registerService(Event $event)
{
$extras = $event->getComposer()->getPackage()->getExtra();
$yourParameter = $extras['your-parameter'];
//do your stuff
}
It should do the trick.

Resources