Impatti dell'uso di class_alias () per mantenere la retrocompatibilità in PHP

4

Scenario: un progetto PHP open source che esiste da diversi anni ha troppe classi nello spazio dei nomi principale che vogliamo refactoring alcune di loro in un altro spazio dei nomi, ma abbiamo un API plugin ampiamente utilizzato e divergente, e refactoring potrebbe causare un'incompatibilità all'indietro. Questa API plugin sta fondamentalmente caricando file PHP esterni che interagiscono con le classi e le funzioni nel codice base.

Questo progetto non è un progetto di Composer (non chiedere perché), e usa una libreria di autoloading di classe gestita da noi stessi.

Recentemente ho scoperto la funzione class_alias , che potrebbe aiutare con questo problema.

Sto prendendo in considerazione il refactoring delle classi nel namespace principale in un sottospazio dei nomi e l'aggiornamento dei riferimenti ad esse nel progetto. Per i file PHP che in origine contenevano le classi refactored (ora sono stati spostati), voglio mettere qualcosa del genere:

<?php
class_alias(NewClassName::class, OldClassName::class);

Questo verrà caricato dalla libreria di autoloading quando un plugin richiede l'uso di OldClassName. Ho testato questo metodo e i test primari mostrano che funziona bene.

Il passo successivo è ripulire la directory dello spazio dei nomi principale per soddisfare il vero motivo del nostro refactoring: ci sono troppi file nella directory dello spazio dei nomi principale. Quindi sto creando una nuova directory accanto alla directory di origine chiamata als (alias directory) e creando als una cartella di origine secondaria in cui si trovano i file di classe alias.

Prima il progetto assomigliava a questo:

src/
    src/Foo/Bar.php

Ora il progetto ha il seguente aspetto:

src/
    src/Foo/Bar/Bar.php

als/
    als/Foo/Bar.php

I test mostrano che questo metodo sta funzionando bene finora.

Tuttavia, ci sono possibili effetti collaterali, dal punto di vista tecnico / prestazionale, prospettiva della documentazione o prospettiva della struttura del codice? Non abbiamo mai provato a fare qualcosa del genere e non ho mai visto nessuno farlo. Molti sviluppatori stanno guardando il repository come riferimento dell'API, quindi vogliamo essere più attenti prima di provare queste modifiche.

    
posta SOFe 07.01.2017 - 18:50
fonte

1 risposta

4

L'ho fatto ed è possibile, anche se ci sono alcune trappole intorno all'autoloading da considerare. Ho descritto l'approccio in un post sul blog:

PHP: Using class_alias to maintain BC while moving/renaming classes

Sommario:

  • Non inserire il codice class_alias() nel file di classe originale

    The problem is that type hints do not trigger the autoloader. Similar to the ::class constant, type hints are resolved to a class name which is compared to the class name of the passed object, without actually looking for the type hinted class! That’s why it is important to have the alias in place as soon as the real class is loaded.

    Otherwise passing a NewClass instance to the following function would fail because "NewClass" != "OldClass" and the alias is not defined yet:

    function oldFunction(OldClass $old)
    
  • Se non usi il compositore o un singolo file di bootstrap che viene sempre caricato, il modo migliore che ho trovato è mettere class_alias() nel nuovo file di classe:

    \class_alias(NewClass::class, OldClass::class)
    

    Quindi devi assicurarti che la nuova classe con l'alias sia caricata anche se qualcuno tenta di creare un'istanza della classe vecchia (o usa proprietà, metodi o costanti statici). Per fare questo, faccio scattare il caricatore automatico nel vecchio file di classe:

    \class_exists(NewClass::class);
    
risposta data 11.01.2017 - 21:12
fonte