I want to install the "Google APIs Client Library" in my symfony 3 project, but I don't know how to use it.
I install the library from "https://github.com/googleapis/google-api-php-client#download-the-release" with this command:
composer require google/apiclient:"^2.0"
Next, I try adding namespace in AppKernel.php file, "bundles" array, but I dont know what namespace is or where can I find the namespace. Then I receive this error every time:
Attempted to load class "Google_Client" from namespace "AppBundle\Controller".
This is my small function:
/**
* #Route("/api/oAuth/login", name="api_oauth_login")
*/
public function oAuthLoginAction(Request $request)
{
$client = new Google_Client();
$client->setApplicationName("My Application");
$client->setDeveloperKey("MY_SIMPLE_API_KEY");
}
Can anyone help me with this library integration?
The library don't use a namespace so you should refer to the class with a trailing slash before the classname as example:
$client = new \Google_Client();
Related
A so far working bundle now needs its own configuration file inside the projects using the bundle, to manage bundle settings individually.
However, no matter which approach I use (the old one before Symfony 6.1 nor the new one extending AbstractBundle) there is - at no time - any new .yaml-File created inside the projects ./config/packages/ directory.
This is my code (the old style, prior to Symfony 6.1, extending Bundle):
Bundle Class
mycorpforms/src/MyCorpFormsBundle.php
<?php
namespace MyCorp\FormsBundle;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class MyCorpFormsBundle extends Bundle
{
// empty
}
Configuration
mycorpforms/src/DependencyInjection/Configuration.php
<?php
namespace MyCorp\FormsBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
class Configuration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('mycorp_forms');
$treeBuilder->getRootNode()
->children()
->booleanNode('favorite_submenu_enabled')->defaultFalse()->end()
->end()
;
return $treeBuilder;
}
}
Extension
mycorpforms/src/DependencyInjection/MyCorpFormsExtension.php
<?php
namespace MyCorp\FormsBundle\DependencyInjection;
use Knp\Bundle\SnappyBundle\DependencyInjection\Configuration;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
class MyCorpFormsExtension extends Extension
{
public function load(array $configs, ContainerBuilder $containerBuilder)
{
$loader = new YamlFileLoader(
$containerBuilder,
new FileLocator(__DIR__.'/../../config/packages')
);
$loader->load('mycorp_forms.yaml');
$configuration = new Configuration();
$processor = new Processor();
$config = $processor->processConfiguration($configuration, $configs);
$containerBuilder->setParameter('mycorp_forms.favorite_submenu_enabled', $config['favorite_submenu_enabled']);
}
}
Yaml
Additionally I added the desired mycorp_forms.yaml inside the bundles ./config/packages/ dir.
This is the actual file required in the projects:
mycorpforms/config/packages/mycorp_forms.yaml
mycorp_forms:
# Enable Favorite-Sub-Menu (Requires Knp-Snappy-Bundle !)
favorite_submenu_enabled: false
The bundle installs flawlessly in any of my projects, however no mycorp_forms.yaml file is created. Obviously this requires symfony/flex which is so far required by the bundle itself.
Q: What do I miss here?
Q: How can this yaml-file automatically be added when the bundle is installed?
I read the documentation up and down numerous times, but to be honest, I get more confused every time.
Thank you very much for any help or explanation!
This requires Symfony Flex
To have a .yaml config file being generated/updated automatically, there is 2 possible ways:
public bundle: register it in the public recipe repository
private bundle: set up your own private flex recipe repository
I am trying to add Symfony 5.4 to my legacy project. There is a pretty nice documentation on how to do this, but there's a big problem - the documentation assumes "normal" Symfony, but each time I try to install Symfony using their recommended way of composer create-project, I get a Symfony version with symfony/runtime - the big problem here, is that this version has a completely different index.php:
<?php
use App\Kernel;
require_once dirname(_DIR_).'/vendor/autoload_runtime.php';
return function (array $context) {
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
};
The documentation found here is based on a completely different index file.
I did find that I can remove the runtime package, and just copy old index, and it works for the most part, but then you also have problems with console.php and I worry that if I go this route there will be more and more problems caused by my installation expecting symfony/runtime and me manually removing it's
I tried installing Symfony 5.3 as well as different patches of 5.4, all came with this installed, even though I did work on some 5.3 / 5.4 projects and had the old school index.php file.
Does anyone know how to currently install Symfony with the "old" index.php, console.php etc.?
Thanks!
So the task is to migrate from a non-Symfony legacy app to a Symfony app. The basic idea is to allow the Symfony app to process a request and then hand it off to the legacy app if necessary. The Symfony docs show how to do this but but relies on the older style index.php file. The newer runtime based approach is a bit different.
But in the end all it really takes is a couple of fairly simple classes. A runner class takes care of creating a request object and turning it into a response. This is where you can add the bridge to your legacy app. It's a clone of Symfony's HttpKernelRunner class:
namespace App\Legacy;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\TerminableInterface;
use Symfony\Component\Runtime\RunnerInterface;
class LegacyRunner implements RunnerInterface
{
private $kernel;
private $request;
public function __construct(HttpKernelInterface $kernel, Request $request)
{
$this->kernel = $kernel;
$this->request = $request;
}
public function run(): int
{
$response = $this->kernel->handle($this->request);
// check the response to see if it should be handed off to legacy app
dd('Response Code ' . $response->getStatusCode());
$response->send();
if ($this->kernel instanceof TerminableInterface) {
$this->kernel->terminate($this->request, $response);
}
return 0;
}
}
Next you need to wire up runner by extending the SymfonyRuntime::getRunner method:
namespace App\Legacy;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Runtime\RunnerInterface;
use Symfony\Component\Runtime\SymfonyRuntime;
class LegacyRuntime extends SymfonyRuntime
{
public function getRunner(?object $application): RunnerInterface
{
if ($application instanceof HttpKernelInterface) {
return new LegacyRunner($application, Request::createFromGlobals());
}
return parent::getRunner($application);
}
}
Finally, update composer.json to use your legacy runtime class:
"extra": {
...
"runtime": {
"class": "App\\Legacy\\LegacyRuntime"
}
}
After updating composer.json do a composer update for the changes to take effect and start your server. Navigate to a route and you should hit the dd statement.
I am a newbie in Symfony but I know how to use OOP in PHP.
I try (with frustration) to couple custom parameters with Symfony configs by using Doctrine entities.
To solve the problem I used for e.g. the answer from Michael Sivolobov: https://stackoverflow.com/a/28726681/2114615 and other sources.
My solution:
Step 1: Create new package in config folder
-> config
-> packages
-> project
-> services.yaml
-> project
-> src
-> ParameterLoaderBundle.php
-> DependencyInjection
-> Compiler
-> ParameterLoaderPass.php
Step 2: Import the new resource
# config/services.yaml
...
imports:
- { resource: 'packages/project/config/services.yaml' }
...
Step 3: Package coding
# packages/project/config/services.yaml
services:
Project\:
resource: "../src"
<?php
namespace Project;
use Project\DependencyInjection\Compiler\ParameterLoaderPass;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class ParameterLoaderBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new ParameterLoaderPass(), PassConfig::TYPE_AFTER_REMOVING);
}
}
<?php
namespace Project\DependencyInjection\Compiler;
use App\Entity\SettingCategory;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class ParameterLoaderPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$em = $container->get('doctrine.orm.default_entity_manager');
$setting = $em->getRepository(SettingCategory::class)->findAll();
$container->setParameter('test', $setting);
}
}
After at all I test the new Parameter in my API controller:
$this->getParameter('Test');
But the following error message appears:
The parameter \"test\" must be defined.
Couple of things going on here. First off, loading config from a database is very unusual in Symfony so it is not surprising that you are having difficulty. Secondly, your process code is never getting called. Part of debugging is making sure that code that you expect to be called is in fact being called. Third, you really got off on a tangent with attempting to add a bundle under config. Way back in Symfony 2 there used to be more bundle related stuff under app/config and it may be that you discovered some old articles and misunderstood them.
But, the big problem here is that Symfony has what is known as a 'compile' phase which basically processes all the configuration and caches it. Hence the CompilerPassInterface. Unfortunately, services themselves are not available during the compile phase. They simply don't exist yet so no entity manager. You need to open your own database connection if you really want to load config from a database. You will want to use just a database connection object and not the entity manager since part of the compile phase is to process the entities themselves.
So get rid of all your code and just adjust your Kernel class:
# src/Kernel.php
class Kernel extends BaseKernel implements CompilerPassInterface
{
use MicroKernelTrait;
public function process(ContainerBuilder $container)
{
$url = $_ENV['DATABASE_URL'];
$conn = DriverManager::getConnection(['url' => $url]);
$settings = $conn->executeQuery('SELECT * FROM settings')->fetchAllAssociative();
$container->setParameter('test',$settings);
}
And be aware that even if you get all this working, you will need to manually rebuild the Symfony cache after updating your settings table. It is not going to be automatic. You really might consider taking a completely different approach.
I installed the following library from GitHub: https://github.com/rosell-dk/webp-convert
The location of the main class that I need to is (from project root) :
\vendor\rosell-dk\webp-convert\src\WebPConvert.php
Here is how the WebPConvert.php class starts out:
namespace WebPConvert;
use WebPConvert\Converters\ConverterHelper;
use WebPConvert\ServeExistingOrConvert;
use WebPConvert\Serve\ServeExistingOrHandOver;
class WebPConvert
{
In the repository class where I use it, here is how I tried to do my dependency injection:
use WebPConvert\WebPConvert;
class PhotoRepository extends ServiceEntityRepository
{
/**
* #var WebPConvert
*/
protected $webPConverter;
public function __construct(WebPConvert $webPConverter)
{
$this->webPConverter = $webPConverter;
}
I followed the instructions from https://symfony.com/doc/current/service_container.html
But I still get this message:
Cannot autowire service "App\Repository\PhotoRepository": argument "$webPConverter" of method "__construct()" references class "WebPConvert\WebPConvert" but no such service exists.
I have even tried putting this in my services.yaml and it doesn't work:
App\Repository\PhotoRepository:
arguments:
- WebPConvert\WebPConvert
Is there an extra step I am missing?
This is Cerad's answer which worked:
WebPConvert is not a Symfony bundle so it won't have any services defined. You will have to define them manually. Actually, from the readme file, it looks like WebPConvert::convert is a static method so there is nothing to inject. Just follow the example.
I am attempting to integrate PHPCR-ODM with an existing Symfony project, and am having trouble getting it to (presumably) detect my mapped Document class. Specifically, I get an error like this when attempting to persist a Document of my class MyDocument:
[Doctrine\Common\Persistence\Mapping\MappingException]
The class 'Example\Common\ORM\Document\MyDocument' was not found in the chain configured namespaces Doctrine\ODM\PHPCR\Document
My class is in a potentially strange namespace because this project uses Doctrine ORM as well, and thus far I've just added a new space for mapped Documents off of that, but I can't imagine the choice of namespace name affects the functionality.
Per the docs, I have added to my app/autoload.php:
AnnotationRegistry::registerFile(__DIR__.'/../vendor/doctrine/phpcr-odm/lib/Doctrine/ODM/PHPCR/Mapping/Annotations/DoctrineAnnotations.php');
My app/config/config.yml includes the following (with parameters set in parameters.yml):
doctrine_phpcr:
session:
backend:
type: jackrabbit
url: %jackrabbit_url%
workspace: %jackrabbit_workspace%
username: %jackrabbit_user%
password: %jackrabbit_password%
odm:
auto_mapping: true
My document class lives in src/Example/Common/ORM/Document/MyDocument.php and looks like:
<?php
namespace Example\Common\ORM\Document;
use Doctrine\ODM\PHPCR\Mapping\Annotations as PHPCRODM;
/**
* #PHPCRODM\Document
*/
class MyDocument
{
/**
* #PHPCRODM\Id
*/
private $id;
/**
* #PHPCRODM\ParentDocument
*/
private $parent;
/**
* #PHPCRODM\Nodename
*/
private $name;
// .. etc
Finally, the code I am using to test the integration is inside a simple console command, and looks like:
use Example\Common\ORM\Document\MyDocument;
// ...
$documentManager = $this->container->get('doctrine_phpcr.odm.default_document_manager');
$document = new MyDocument();
$document->setParent($documentManager->find(null, '/'));
$document->setName('ExampleName');
$documentManager->persist($document);
$documentManager->flush();
I have verified that my MyDocument class is being correctly loaded, but it seems that the annotations are not being processed in a way that is making the DocumentManager aware that it is a mapped Document class.
My guess is that I have overlooked some simple configuration step, but from looking repeatedly and thoroughly at the docs for PHPCR, PHPCR-ODM, and even Symfony CMF, I can't seem to find anything. Most of the examples out there involve using PHPCR via Symfony CMF, and I wasn't able to find many (any?) real world examples of PHPCR-ODM being integrated in a regular Symfony project.
edit: The Eventual Solution
I followed the advice that #WouterJ gave below and it fixed my problem, and I further followed his suggestion of adding a compiler pass to my Symfony bundle to make this work with a non-standard namespace (i.e., something other than YourBundle\Document). In my case, this is going into a library that will be re-used elsewhere rather than a bundle, so it was appropriate.
To do this, I added a method to the src/Example/Bundle/ExampleBundle/ExampleBundle.php file like so:
<?php
namespace Example\Bundle\ExampleBundle;
use Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class ExampleBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$mappedDirectories = array(
realpath(__DIR__ . '/../../Common/ODM/Document')
);
$mappedNamespaces = array(
'Example\Common\ODM\Document'
);
$phpcrCompilerClass = 'Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass';
if (class_exists($phpcrCompilerClass)) {
$container->addCompilerPass(
DoctrinePhpcrMappingsPass::createAnnotationMappingDriver(
$mappedNamespaces,
$mappedDirectories
));
}
}
}
That code allows any mapped document classes to be placed in the Example\Common\ODM\Document namespace and it will pick them up. This example uses annotations but the same pattern can be used for XML or YAML mappings (see the Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass class for method signatures).
I found that I also needed to define the doctrine_phpcr.odm.metadata.annotation_reader service for this to work, which I did in app/config.yml:
services:
doctrine_phpcr.odm.metadata.annotation_reader:
class: Doctrine\Common\Annotations\AnnotationReader
There may be a better way to do that, but that was enough to make it work for me.
The document should be placed in the Document namespace of the bundle, not the ORM\Document namespace.
If you really want to put it in the ORM\Document namespace (which is very strange, because we are talking about an ODM not an ORM), you can use the doctrine mapping compiler pass: http://symfony.com/doc/current/cookbook/doctrine/mapping_model_classes.html