Strategy to override a class in a library installed with Composer

前端 未结 4 1888
抹茶落季
抹茶落季 2020-12-13 00:50

I am using Codeigniter and Composer. One of the requirements is PHPExcel. Now I need to change a function in one of the classes. What should be the best strategy to do it? S

相关标签:
4条回答
  • 2020-12-13 01:18

    In composer.json, under ["autoload"]["psr-4"], add an entry with namespace as the key and path as the value:

    {
         "autoload": {
    
             "psr-4": {
    
                 "BuggyVendor\\Namespace\\": "myfixes/BuggyVendor/Namespace"
             }
         }
    }
    

    Copy files you want to override under that path (keeping sub-namespace directory structure) and edit them there. They will be picked in preference to the library package's original "classpath". It would seem that namespace->path mappings added to composer.json in this manner are considered before those added by required packages. Note: I just tried it and it worked, though I don't know if it is an intended feature or what possible gotchas are.

    EDIT: found a gotcha. Sometimes when you subsequently require another package with composer require vendor/package, you will "lose" the override. If this happens, you must issue composer dump-autoload manually. This will restore the correct autoload order honoring your override.

    0 讨论(0)
  • 2020-12-13 01:19

    Adding these last 2 lines to the autoload section of my composer.json is what worked for me when I wanted to override just one file within the vendors directory:

    "autoload": {        
        "classmap": [
            "database"
        ],
        "psr-4": {
            "App\\": "app/"
        },
        "exclude-from-classmap": ["vendor/somepackagehere/blah/Something.php"],
        "files": ["app/Overrides/Something.php"]
    },
    

    Remember that the namespace within app/Overrides/Something.php needs to match whatever the original was in vendor/somepackagehere/blah/Something.php.

    Remember to run composer dump-autoload after editing the composer.json.

    Docs: https://getcomposer.org/doc/04-schema.md#files

    0 讨论(0)
  • 2020-12-13 01:19

    Changing an existing class is against OOP and SOLID principles (Open to extension/Closed for modification principle specificaly). So the solution here is not to change the code directly, but to extend the code to add your functionnality.

    In an ideal world you should never change a piece of code that you don't own. In fact, with composer you can't because your change will be overrided when updating dependencies.

    A solution in your case is to create a class at the application level, and extend the class you want to change (which is at the library level) to override with your code. Please look at extending a class in PHP if you don't know how.

    Then typically, you load your class instead of their class, this way, you add your functionnality on top of their functionnality, and in case of an update, nothing break (in case of a non breaking update).

    0 讨论(0)
  • 2020-12-13 01:26

    There is one more option. In case you need to rewrite the only class you can use files in composer.json like this

     "autoload": {
         "files": ["path/to/rewritten/Class.php"]
      }
    

    So if you want to rewrite class Some\Namespace\MyClass put it like this

    #path/to/rewritten/Class.php
    
    namespace Some\Namespace;
    
    class MyClass {
      #do whatever you want here
    }
    

    Upon each request composer will load that file into memory, so when it comes to use Some\Namespace\MyClass - implementation from path/to/rewritten/Class.php will be used.

    0 讨论(0)
提交回复
热议问题