how can I autoload my modules' lib folders in my Symfony 1.4 projects? Probably you know that problem:
If I create plugins, I store base-classes for my modules' actions in the lib folder. Each actions-class stored in actions/actions.class.php inherits from that base-class. This allows overriding the plugin-actions at project level:
myModule
actions
actions.class.php
lib
BasemyModuleActions.class.php
But unfortunately, Symfony doesn't autoload BasemyModuleActions and you have to include the respective file manually:
require_once(dirname(__FILE__) .'/lib/BasemyModuleActions.class.php');
class myModuleActions extends BasemyModuleActions
{
}
This works, but it is really annoying. Moreover I want to put more files in the modules' lib folders, e.g. forms.
Is there a way to add those directories to the autoloader?
Storing forms in their related modules would good for me, since I only reuse the same form for different modules in few cases.
Is your solution also compatible with the Doctrine form-generation task? I.e. is Symfony aware of the existing form, or will it be created again if it is moved out of lib/form/doctrine? (No problem, if you can't answer that. But it would be nice if you know a workaround in this case)
Take a look at this page:
http://www.symfony-project.org/reference/1_4/en/14-Other-Configuration-Files
It describes an autoload.yml file, which configures symfony to look for classes in different directories.
Symfony wouldn't autoload my /apps/app_name/lib/*.* classes, but does so after creating /config/autoload.yml file with the following content:
autoload:
# project
project:
name: project
path: %SF_LIB_DIR%
recursive: true
exclude: [model, symfony]
project_model:
name: project model
path: %SF_LIB_DIR%/model
recursive: true
# application
application:
name: application
path: %SF_APP_LIB_DIR%
recursive: true
modules:
name: module
path: %SF_APP_DIR%/modules/*/lib
prefix: 1
recursive: true
Which the above page describes as the default config.
As i understand it this is a chicken and egg issue with the autoloader and main controller flow.
The prefix: 1 in the default autoload.yml indicates that these classes are only available to be autoloaded if 'in' the current module.
The way the current module is determined is by looking at the actionStack.
The module/action is added to the actionStack after checking to see if it exists.
Unfortunately to determine if an action exists symfony loads the actions.class.php
Hence you need to have the explicit, require_once.
If you get rid of the prefix: 1 and your module is part of your application (not loaded from a plugin) you will not need the require once.
If the module is part of a plugin, you would need to mess with sfPluginConfiguration to have it load the appropriate classes without prefix.
Both methods are problematic as there could be clashes between class names in various modules.
Related
I have module created in the basic project of yii2 and now i want to access or use that module another project/application of mine....
How can I achieve this.
please help me out here.
To use module in different apps there are 3 things you need.
The module must not be dependent on classes from core project. For any class that needs to be implemented by core project the module should define interface and depend on that interface instead of class itself.
The module should use different namespace than app and autoloader must know how to load classes from that namespace. (more about that later)
You have to add module in your config in same way you've added it in first project.
The points 1 and 3 are pretty much self-explaining. If are not sure how to add module in config see the yii2 guide.
Now back to the second point. While naive way of copying module over to second project would work it will turn maintaining the module into nightmare because each change would have to be done in each copy of module. So it's better to keep the code of module in one place and make it available for each project. There are multiple ways of doing that.
If you want to, you can turn your module into extension and make it publicly available through packagist as it was suggested by M. Eriksson in comments. After that you would simply add your extension through composer as any other dependency.
Composer also allows you to define and use private repositories if you don't want to publish your module at packagist. See composer documentation for more details.
The most trivial way is to simply put the code into separate folder outside of project. If you do that, you have to make sure that autoloaders in your projects are capable of finding the files locations to load classes. There are two options how to do that. In any case you will want to avoid conflicts with namespaces used by your project, that's why you need to use different namespace.
Let's assume that you've put your module files into folder /path/to/modules/myModule and all classes in your module belongs to namespace modules\myModule. You have to make sure that your webserver can access that folder and that it can run php scripts there.
First option is to use Yii's autoloader. That autoloader uses aliases to look for classes. If you add #modules alias and point it to /path/to/modules folder, the Yii autoloader will try to look for any class from modules\* namespace in /path/to/modules folder. You can add the alias in your config file (web.php, console.php or any other config file you use):
return [
// ...
'aliases' => [
'#modules' => '/path/to/modules',
// ... other aliases ...
],
];
The second option is to use project's composer.json file to set autoloader generated by composer to load your classes.
{
"autoload": {
"psr-4": {
"modules\\": "/path/to/modules"
}
}
}
You can find more info about this in composer's documentation.
Don't forget to run composer dump-autoload after you change autoload settings in your composer.json file to update the generated autoloader.
I did a fresh Symfony installation by using Symfony Flex and the new skeleton belong to the next Symfony 4 directory structure. Next, I'm going to override some resources like templates, translations, etc. from an external bundle.
I've tried to create all these paths for templates (to start) but nothing works:
templates/EasyAdminBundle/views/...
templates/Resources/EasyAdminBundle/views/...
app/Resources/... (just a proof from old structure)
Where should I puts my resources files to override third-party bundle resources?
For all Symfony versions the resources path is %kernel.root_dir%/Resources/ . As the new 4.0 structure puts the Kernel.php into src/ directory, then it is:
# local resources directory
src/Resources/
# still works this path for local templates
src/Resources/views/
# override resources for third-party bundles
src/Resources/AcmeDemoBundle/views/ # legacy convention to override templates
src/Resources/AcmeDemoBundle/translations/ # for override both translations and validations files
src/Resources/AcmeDemoBundle/... # etc.
New conventions to override resources (since Symfony 3.4)
Twig Templates:
Just follow the convention:
templates/bundles/AcmeDemoBundle/path/to/template.html.twig
If you are upgrading to Symfony 3.4 & 4.0 and you want to use the previous templates conventions, configure your own Twig's paths:
# app/config/config.yml (3.3)
twig:
paths:
# Default templates directory, since 3.4+
templates: ~
# Directory convention to override bundle templates, since 3.4+
# make sure to know the actual Twig namespace for each bundle.
# e.g. AcmeDemoBundle -> AcmeDemo:
templates/bundles/AcmeDemoBundle: AcmeDemo
Translations: Similar to templates/ you have the translations/ directory at the root of the project (by default):
translations/bundles/AcmeDemoBundle/messages.en.yml
Note: The /bundles/AcmeDemoBundle/ sub-directory is not mandatory because translations are not related to bundles, but to domains. That means that you can override translations as long as it is in the correct domain.
I'm (almost) new to Symfony and I'm using 2.4 but I got a problem that is giving me lots of headaches. For several days I have not been able to fix this issue.
I use the app/console commands to build my base code; from entities to crud:
doctrine:generate:entity (to build the models), then code relations, etc
doctrine:generate: entities (to generate setters, getters, etc)
doctrine:schema:update --force (to update to the database all the models)
generate:doctrine:crud (to make controllers, forms, etc....)
At last, since I choose to declare the routing via annotations, I import into my bundle's routing.yml file all the controller routes like:
AutocondatECRBundle_controllers:
resource: "#AutocondatECRBundle/Controller"
type: annotation
This, as far as I'm aware, makes available all the routes inside the generated controllers at crud generation. However, no matter what route I try to test, Symfony keeps telling me:
FileLoaderLoadException: Cannot import resource "/var/www/autocondat-ecr/src/Autocondat/ECRBundle/Controller" from "/var/www/autocondat-ecr/src/Autocondat/ECRBundle/Resources/config/routing.yml". (Class Autocondat\ECRBundle\Controller\Clasificacion_EstudioController does not exist)
no mater what controller or route I choose to test, always fails to find the controller class, and believe me; those classes are there.
-There are no typos on names or cases
-Classes are there, controllers are there
-Routes are there and can't be loaded even using :
pattern: /whatever
defaults: { _controller: AutocondatECRBundle:ControllerWhatever:index }
This is driving me crazy.
For anyone able to help me, here is the source of all the project:
Link to the project
NOTES:
-There are several bundles inside my project; the one I'm testing is AutocondatECRBundle.
-Security inside security.yml file has been deactivated in order to test it faster.
-Of course, database can be generated fast with the same console commands.
Thanks -A LOT- for your help!
For your class Autocondat\ECRBundle\Controller\Clasificacion_EstudioController
Symfony will resolve both the namespace seperator \ and the underscore _ to a directory seperator, using PSR-0 autoloading standards for the autoloading of classes.
That means it is expecting your class to be located in the file src/Autocondat/ECRBundle/Controller/Clasificacion/EstudioController.php.
Name you class to ClasificacionEstudioController and the file to ClasificacionEstudioController.php.
I am trying to create a simple bundle inheritance as instructed in here and ran into a problem with routes. I'm using annotations for routing. When I register my child bundle in AppKernel.php all my parent bundles routes are lost.
For what I understand from the documentation Symfony2 should look all files, including routes, first from the child bundle and then from the parent bundle. Now that is not happening, only child bundles controllers seems to be loaded.
In my child bundles Bundle file I have implemented getParent function as instructed, and in my routing.yml I have:
ParentBundle:
resource: "#Parent/Controller/"
type: annotation
prefix: /admin/
which worked fine before the inheritance.
I have tested that the system works fine if in include all controller files separetely in routing.yml but that seems very cumbersome way to make the inheritance to work as I only want to override few parts of the parent bundle ( not all controllers ).
Profiler is showing both of my bundles as active.
I found the right solution for this issue. Today I was also trying to override a parent bundle configured with annotations routing and also found that parent routes were ignored if the anotation routing imported the whole bundle ("#SomeBundle/Controller").
After a little debugging I found that the explanation for this is that if you use "#" as prefix for the controller this will pass to the kernel resolver which will return ONLY the child resource if the parent resource has been overridden. So the solution is to provide the full path of the bundle, considering that the kernel will try to match the resource from app/Resources so you will have to add a relative directory (../../) before the actual path:
# app/config/routing.yml:
some_parent:
resource: "../../src/Application/ParentBundle/Controller"
type: annotation
# ChildBundle implements getParent() method to inherit from ParentBundle
some_child:
resource: "#ChildBundle/Controller"
type: annotation
This will work as expected: all parent routes will be imported and will be overridden by all routes specified in the child bundle.
In addition to previous answer, I also had to change the name of the routing.yml of the child bundle (e.g. to routing_child.yml) to get it working. I assume this is because Symfony totally ignores the parent bundle routing file if the name is identical.
EDIT:
In many cases it's also practical to import parent bundle routes into the child bundle routing file like this:
# routing_child.yml
_parent:
resource: "#MyParentBundle/Resources/config/routing.yml"
The official documentation says that you shall just copy parent routing file to your child bundle:
The easiest way to "override" a bundle's routing is to never import it at all. Instead of importing a third-party bundle's routing, simply copying that routing file into your application, modify it, and import it instead.
Also, you cannot include parent's bundle routing file using symbolic names "#ParentBundle" because this name is resolved to "#ChildBundle".
If you really want to include parent routes file, then you shall use the absolute path to that file or path relative to current directory, i.e.:
# #YourChildBundle/Resources/routing.yml
YourParentBundle:
resource: "/srv/www/example.com/src/Your/ParentBundle/Resources/routing.yml"
or
# #YourChildBundle/Resources/routing.yml
YourParentBundle:
resource: "../../../../../Your/ParentBundle/Resources/routing.yml"
Another workaround is to symlink your parent routing file into your child bundle and include it with shorter path, i.e.:
cd YourChildBunde
ln -s ../../../../../Your/ParentBundle/Resources/routing.yml parent_routes.yml
and then
# #YourChildBundle/Resources/routing.yml
YourParentBundle:
resource: "parent_routing.yml"
P.S. I hope they'll find some better and less uglier way to override and extend routing from parent bundle, but now we have to se some of those ugly workarounds.
With bundle inheritance, you can override the parent bundle's files.
If you create a routing file in the same location as the parents in your bundle (if the routing of the parent file is at ParentBundle/Resources/config/routing.yml, and you create a routing file at ChildBundle/Resources/config/routing.yml), it will override the parent's routing.yml, and symfony will only use the child's routing.yml.
I haven't tried, but if you import the parent bundle's routing.yml in the child bundle's routing.yml, you can solve your problem. As Symfony router will always choose the first matching route it finds, you can override the specific route you want by writing the relevant routing code on top of the import code.
I am trying to auto-load classes from the "lib" directory inside of one specific module directory.
I have tried everything but to no avail...
One of the classes I would like to load is a class called visUser which inherits from myUser I have already made a factory.yml file in myapplication/modules/mymodule/conf but it doesn't load...
I am doing something wrong? or module level configuration files are not suported?
I am using symfony 1.2 with propel.
Factories are an application specific file and cannot be overloaded on the module level. It's a weird idea anyway.
Read the config handlers file to see what files are supported on the modules level configuration (symfony/lib/config/config/config_handlers.yml).