DEV Community

How to deprecate a type in php

Grégoire Paris on December 29, 2018

So you have this class or interface you want to rename to something else, because you need to move that type to another package, or you have new co...
Collapse
 
aleksikauppila profile image
Aleksi Kauppila

It seems that you're trying to create a technical solution for a non-technical issue. Use semantic versioning and annotate the type deprecated in next minor version. Remove type in next major version.

Collapse
 
fredbouchery profile image
Frédéric Bouchery

How lucky you are. You've never had the pleasure of dealing with huge legacy applications ;)
An application so outdated that SemVer did not exist.

Collapse
 
greg0ire profile image
Grégoire Paris

This will not be enough, sadly. I need to make the new type usable everywhere the legacy type is.

Collapse
 
david_j_eddy profile image
David J Eddy • Edited

I'm with Aleksi on this one. Semantic version out the old name, then remove in following version release. Any logic that has to be carried over from the old to the new should be moved and tests created to validate functionality.

    1.0.0 = Added SomeClass
    2.0.0 = SomeClass deprecated, use NewClass
    3.0.0 = SomeClass removed use NewClass

As a production system maintainer I always lock my dependencies to major release version. (If a library does not use SemVer, I don't use that package.)

Thread Thread
 
greg0ire profile image
Grégoire Paris

Not sure I understand. Please show me how you would implement a Foo class that would pass the following tests:
github.com/greg0ire/type_deprecati...

Thread Thread
 
aleksikauppila profile image
Aleksi Kauppila • Edited

It's not an implementation issue imo. This is from Semantic versioning homepage:

How should I handle deprecating functionality?

Deprecating existing functionality is a normal part of software development and is often required to make forward progress. When you deprecate part of your public API, you should do two things: (1) update your documentation to let users know about the change, (2) issue a new minor release with the deprecation in place. Before you completely remove the functionality in a new major release there should be at least one minor release that contains the deprecation so that users can smoothly transition to the new API.

Thread Thread
 
greg0ire profile image
Grégoire Paris

Maybe that was unclear (I wrote this in a rush), but this blog post is about how you can implement that part of SemVer (deprecating part of your public API) for php types. Not sure what "It" is referring to in "It's not an implementation issue IMO" or why you two attempt to teach me the basics of SemVer when I'm trying to show how to put it in practice for a specific part of a PHP API.

Thread Thread
 
aleksikauppila profile image
Aleksi Kauppila

Ah, with "it" i mean deprecating a type in php. As far as i'm concerned this is enough:

<?php

// LegacyFoo.php

/**
 * @deprecated please use ShinyNewFoo instead!
 */
interface LegacyFoo
{
    //...
}

But i also accept the fact that i may have missed some point in this article...

Thread Thread
 
greg0ire profile image
Grégoire Paris

This solution is enough in some situations. In others, you will need inheritance, and in some more complicated situations, you will have to resort to class aliases. That's what I failed to make perfectly clear in my article.

Collapse
 
dykyiroman profile image
Roman • Edited

I should do a lot of job for make the class deprecated. A modern IDE helps you to check deprecated class or not using annotation @deprecated. Its always help me. Maybe your approach have a good solution for this case, but your example is not from real life I think

Collapse
 
greg0ire profile image
Grégoire Paris

Sorry for the very late response, but it absolutely is from real life: I applied it on a very widely used library with 200 million installs. Is that real life enough for you sir?

Collapse
 
lvo profile image
Laurent VOULLEMIER

Interesting post ! Sadly I don't think it is possible to trigger a deprecation in a straightforward way in the case you present. Furthermore I'm not sure this chunk of code will work in all cases:

<?php

if (!class_exists(ShinyNewFoo::class, false)) {
    @trigger_error(
        'LegacyFoo is deprecated!',
        E_USER_DEPRECATED
    );
}
Enter fullscreen mode Exit fullscreen mode

If ShinyNewFoo is used in your user's code before LegacyFoo, I'm not sure that the deprecation will be triggered.

Collapse
 
greg0ire profile image
Grégoire Paris

You're correct, that's why I labelled this a best effort, it's really not ideal, but I'm afraid it's all we have.

Collapse
 
ostrolucky profile image
Gabriel Ostrolucký • Edited

Is there a GH issue for composer workaround? Composer should fix this instead of encouraging ecosystem to keep on doing this hack.

Collapse
 
greg0ire profile image
Grégoire Paris

There even was a pull request, but… github.com/composer/composer/pull/...