I have a Symfony2 project, where I have a Bundle that is generic (GenericBundle) accross multiple projects, and a site-specific Bundle (SpecificBundle) that is a child-bundle of GenericBundle.
When I am developing I want the GenericBundle to be loaded locally, from a specific directory, but when deployed I want it to behave as a normal VendorBundle.
I have setup my main composer.json in my Symfony2 project with this setting which makes it load the GenericBundle from my directory when developing:
"autoload-dev": {
"psr-0": { "": "../genericBundleDirectory/" }
},
This works fine, but how do I get the GenericBundle to load like a VendorBundle only in production-environment?
Normally you would have an src/ directory to accomodate your AppBundle and/or other bundles related to your application.
"autoload-dev": {
"psr-0": { "": "src/" }
},
Related
I'm trying to create a Bundle to share some services and utility classes between my different projects.
I already did this while using Symfony 5.4. But now I want to migrate to PHP 8.1 using Symfony 6.2.
I don't know what I'm doing wrong, but my web projects just don't see the services I'm creating in my Bundle.
Step by step:
I created my web project that will use the Bundle with:
symfony new my-webapp --version="6.2.*" --webapp
I created the project for the Bundle using composer.json like this:
{
"name": "carlospauluk/my-bundle",
"type": "project",
"license": "proprietary",
"require": {
"php": ">=8.1"
},
"require-dev": {
"symfony/http-kernel": "6.2.*"
},
"autoload": {
"psr-4": {
"MyBundleNamespace\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"MyBundleNamespace\\Tests\\": "tests/"
}
}
}
Inside config/services.yaml, I changed it to:
parameters:
services:
_defaults:
autowire: true
autoconfigure: true
MyBundleNamespace\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
So I created my service in src/Service:
<?php
namespace MyBundleNamespace\Service;
class NumberGeneratorService
{
public function generate(int $max) {
return random_int(0, $max);
}
}
Apparently my service is correctly configured in the Bundle, right?
After that, in my my-webapp, in composer.json I added the local repository of my my-bundle folder:
,
"repositories": [
{
"type": "path",
"url": "../my-bundle"
}
]
and then...
composer require "carlospauluk/my-bundle #dev"
Okay, I was hoping that everything was already working, and that my NumberGeneratorService service was already available in my-webapp. But not. When I run:
php bin/console debug:container MyBundleNamespace
It returns:
No services found that match "MyBundleNamespace".
What could be missing?
When I set up my bundles in my projects using Symfony 5.4, I don't remember doing anything much different than this.
Could you help me please?
Both codes are here:
https://github.com/carlospauluk/my-bundle
https://github.com/carlospauluk/my-webapp
Thanks
Finally, after almost 3 days of trying, I figured out how it should be done.
I needed to implement the loadExtension method inside the /src/MyBundle.php
<?php
namespace MyBundleNamespace;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
class MyBundle extends AbstractBundle
{
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
{
$container->import(__DIR__ . '/Resources/config/services.xml');
}
}
And also had to create the /src/Resources/config/services.xml file
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="my_bundle_namespace.service.number_generator_service"
class="MyBundleNamespace\Service\NumberGeneratorService">
</service>
<service id="MyBundleNamespace\Service\NumberGeneratorService" public="true"
alias="my_bundle_namespace.service.number_generator_service"/>
</services>
</container>
Without this, it doesn't work.
The Symfony Framework is excellent, but it's unfortunate that its documentation is so weak and confusing in places.
For example, at https://symfony.com/doc/current/bundles.html about the they say "This empty class is the only piece you need to create the new bundle.", which we clearly see is not true. Without implementing the loadExtension method we cannot access any services inside the bundle. If they said that clearly, it would be much easier.
Symfony's documentation is too compreehnsive, despite being very shalow at some points.
When I create a new project using a custom Visual Studio template the launchSettings.json file isn't picked up automatically by Visual Studio and the same goes for all the rules which it is trying to impose, they aren't imposed.
To attach the launchSettings file one has to right click on the docker-compose.yml file and click on Manage Docker Compose Launch Settings then wait for the launchSettings file to load and click save.
This is how the docker-compose.yml file looks :
services:
services:
splunk:
image: splunk/splunk:latest
pgadmin:
image: dpage/pgadmin4
This is how the launchSettings.json file looks
{
"profiles": {
"First Profile": {
"commandName": "DockerCompose",
"commandVersion": "1.0",
"serviceActions": {
"pgadmin": "StartWithoutDebugging",
"splunk": "DoNotStart"
}
},
"Second Profile": {
"commandName": "DockerCompose",
"commandVersion": "1.0",
"serviceActions": {
"pgadmin": "StartWithoutDebugging",
"splunk": "StartWithoutDebugging",
}
}
}
}
Please advise how can the launchSettings.json file automatically picked up by the Visual Studio on the first launch without having to click on Manage Docker Compose Launch Settings.
I’m having trouble setting up the fixture listener for a CakePHP 4.1 project, using PHPUnit 9.4.
I’ve added the xml in phpunit.xml.dist:
<!-- Setup a listener for fixtures -->
<listeners>
<listener class="Cake\TestSuite\Fixture\FixtureInjector">
<arguments>
<object class="Cake\TestSuite\Fixture\FixtureManager"/>
</arguments>
</listener>
</listeners>
My composer.json contains the following rows:
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"App\\Test\\": "tests/",
"Cake\\Test\\": "vendor/cakephp/cakephp/tests/"
}
},
But when I run ‘phpunit.bat tests’ from the cli, it gives me the following error:
Class ‘Cake\TestSuite\Fixture\FixtureManager’ not found
Anyone knows why?
I solved it by executing the tests with the framework’s phpunit.bat, instead of the one from my local web server (xampp):
vendor/bin/phpunit.bat tests
I'm working on plugin that uses autoloader from composer. But for some reason, when I'm creating new object, PHP loads different autoloader from different plugin, and all my work is not accessible. So here is composer.json:
{
"autoload": {
"psr-4": {
"CustomizableProduct\\": "inc"
}
},
"config": {
"vendor-dir": "lib"
}
}
That's how I'm trying to load base plugin class in my_plugin.php file:
define('MY_PLUGIN_PATH', plugin_dir_path(__FILE__));
add_action('init', function () {
require_once MY_PLUGIN_PATH . "/lib/autoload.php";
new \CustomizableProduct\CustomizableProduct();
});
Every time PHP shows me error that class was not found. BUT when I'm dumping autoload with optimize-autoloader param, suddenly it works great.
Ok, I can live with that optimized autoloader, but I need to load Woocommerce classes to create custom product type. Unfortunately, changing composer.json to
"autoload": {
"psr-4": {
"CustomizableProduct\\": "inc",
"Woocommerce\\": "../woocommerce"
}
},
or with simpler, global version
"autoload": {
"psr-4": {
"CustomizableProduct\\": "inc",
"\\": "../"
}
},
not working, even with dumping autoloader with optimization param.
I have no idea what to do. Am I doing something wrong? I'm thinking about setting my own autoloader, or eventually just to create file only with include_once, including all my classes.
Just a quick question as to why I'm getting this
The autoloader expected class "App\Controller\Admin\AdminUnitController" to be defined in file "/home/glen/public_html/businessdirectory.glendev.local/vendor/composer/../../src/Controller/Admin/AdminUnitController.php". The file was found but the class was not in it, the class name or namespace probably has a typo in /home/glen/public_html/businessdirectory.glendev.local/config/services.yaml (which is loaded in resource "/home/glen/public_html/businessdirectory.glendev.local/config/services.yaml").
I have AdminUnitController.php with class name AdminUnitController. All was well until I decided I want the admin controllers in their own sub folder like this:
Controller\Admin\AdminUnitController.php
From the autoloader message, your issue is quite clear, your file is indeed where it should be but your class or namespace is wrong.
I would guess you changed the file structure but did not adapt your namespace.
Given the file src\Controller\Admin\AdminUnitController.php
Your class should look like this (pay specific attention at the namespace):
<?php
namespace App\Controller\Admin;
class AdminUnitController
{
// some code here
}
That is actually not a Symfony behavior you are facing here, but one of composer, that serves Symfony with the autoloader and that uses PSR-4 class autoloading convention.
For Reference
1) see your composer.json that have those lines:
{
// some definitions here
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"App\\Tests\\": "tests/"
}
},
// some more definitions here
}
2) see the PSR-4 naming convention: and especially the examples in their documentation: https://www.php-fig.org/psr/psr-4/#3-examples