DevDonkey
DevDonkey

Reputation: 4880

override symfony 3rd party bundle resource

Symfony 2.7.5

Problem

I'm trying to override a class file in a 3rd party vendor file so that I can extend the functionality a little. This file isn't part of a service, or a controller.

Rather confusingly (I'm not sure why this worked), I've over-ridden part of FOSUserBundle by creating the directory structure as follows:

 src
    │   
    │
    └───FOS
        │   
        │
        ├───Model
            │   User.php
            │   Group.php
            │   ...

This has allowed me to change the visibility of some of the FOS user class members. And it allowed me to do with this without any other config. Not even a child-class set-up.

Tried so far

I've read this, but it only talks about basic resources.

I've also read this, but it seems to only work for controllers or anything in the Resources folder.

Ive tried setting up a child bundle, similar to the above link but to no avail.

I cant think of a way of successfully using inheritance in this instance to accomplish what I need to do. As the file in question isn't referred to outside of the vendor bundle itself.

Question(edited)

Is there a way that I could extend/override a bundle class file that lays in a directory structure such as this? I don't need to touch much of the bundle, but I really need to get at this file. This is an extract from APYDataGridBundle.

 vendor
    │   
    │
    └───APY
        │   
        │
        ├───datagrid-bundle
            │   
            │   
            ├───Grid
                |
                | .. grid.php <-- this file

Upvotes: 0

Views: 1246

Answers (2)

Carlos Granados
Carlos Granados

Reputation: 11351

In general, you will only be able to override a class in a bundle in one of two cases:

  • If symfony has defined a generalized way to look for these classes so that you can override them just by putting a new class in a directory. This happens with controllers, for example.
  • If the bundle loads this class by using a parameter in its service definition. In this case you can override it by setting this parameter in your config file

In your case you are lucky and this bundle loads this class through a parameter defined in its services.xml file, so you can provide your own class by overriding this parameter in your config.yml file:

# app/config/config.yml
parameters:
    grid.class: your own class, for example AppBundle/Grid/Grid

If in the future you find that you need to override a class and it cannot be done through one of these methods, you can always create your own fork of the bundle, though this is a pain and hard to maintain, so I would only recommend it if you find no other alternative

Upvotes: 1

hanzi
hanzi

Reputation: 2987

You can do this by using Composer’s autoload feature.

Composer, as you might already know, will automatically load the PHP file containing a class whenever you first call that class. So you don’t have to use require statements all the time.

To achieve what you’re looking for, you can “trick” the autoloader into loading a different file whenever APY\DataGridBundle\Grid\Grid is called.

How to do that

In your composer.json there should be a section like this:

"autoload": {
    "psr-4": {
        "": "src/"
    }
},

This will tell Composer that your classes are in the src/ directory. But since APYDataGridBundle already defined a more specific namespace path in their composer.json, the autoloader will never look at your files.

If you change the block like this:

"autoload": {
    "psr-4": {
        "": "src/"
    },
    "classmap": ["src/APY/DataGridBundle/Grid/Grid.php"]
},

Composer will analyze the file Grid.php and look for classes inside it. It will then create a class map so that whenever the class inside it is called, it will know which file to load before even checking the PSR-0 or PSR-4 namespace paths.

So basically, you’re telling it the path to the file at a higher priority so it gets loaded first.

Of course, you don’t even have to match the namespace with your directory structure, you could also do something like src/replacements/grid.php if that’s better for you. Just make sure that the namespace declaration inside the file is the right one.

Edit: After changing composer.json you have to execute composer dump-autoload so the new autoload files get generated based on the new config.

Upvotes: 2

Related Questions