如何使用 Composer 中的 replace 属性?
本文详细阐述和解释 composer.json 文件中简单但非常重要的属性 replace 属性。
Composer 网站上的 官方 解释很简短,并没有真正解释它的用法。
让我们试着把它分解成一个个细节,这样我们就能深入的了解。官方文件说:
列出被此包替换的包。这样,您就可以派生一个包,并使用其自己的版本号以不同的名称发布它,而需要原始包的包可以继续使用您的派生,因为它会替换原始包。
注意「this」 这个词。这意味着在库中定义它时,该包将替换您在其上指定的任何包。如果您已经 fork 了一个库并且想要始终使用 fork,这可能会很有用。为了更好地理解这一点。让我们举个例子
- 我有一个名为 「My App」的应用程序
- 「My App」 需要两个软件包作为依赖,即 「original/library」 和 「other/package」
- 「other/package」 依赖于「original/library」
- 「original/library」的维护者不再更新它,并且上面有很多错误。
- 您想解决 「original/library」上的问题,但他们不接受您的请求请求
- 您在名为 「yourfork/library」的包中 fork 了「original/library」
- 您在「My App」 项目中指定使用「yourfork/library」
如下图所示
现在的问题是,「other/package」 依赖于「original/library」。结果导致你的应用中加载了两个副本!这并不好,因为有 bug 的包(「original/library」)仍处于加载状态,并且可能会对您的应用程序造成严重破坏。
需要做一些事情,以便每当需要使用「original/library」时,Composer 都知道应该用你的 fork 「yourfork/library」来「替换」它。
输入替换属性
要解决此问题,您需要在 「yourfork/library」中指定 replace 属性, 以便 Composer 知道,无论何时需要该软件包,它都可以替代 「original/library」。
现在。即使您没有直接「告诉」「other/package」 停止使用「original/library」,Composer 也不会再加载「original/library」,因为你告诉他可以将其替换为「yourfork/library」。
明白了吗?
另一个角度:
这对于包含子包的包也很有用,例如,主 symfony/symfony 包包含所有 Symfony 组件,这些组件也可以作为单独的包使用。如果您需要主包,它将自动满足单个组件之一的要求,因为它将替换它们。
方案示例:
- 我有一个名为「My App」的应用程序
- 「vendor/framework」 是一个很酷但很大的的框架
- 您可以在项目中需要整个「vendor/framework」,或者只是你需要的单个组件
- 在初始阶段,「My App」仅需要「vendor/component1」,因为我们说项目只需要这个功能
- 后来,您决定使用完整框架
- 现在,您的「My App」需要两个软件包作为依赖项,即「vendor/framework」和「vendor/component1」
- 但是「vendor/component1」类已经存在于「vendor/framework」中
- 这似乎是一个冗余的代码,容易发生冲突!
下图描述了这种情况:
乍一想,你可能会认为您只需将我的「My App」删除对「vendor/component1」的依赖即可。但是问题是,在大多数情况下,用户不知道哪个组件已经存在于哪个软件包中!
即使你知道,每个软件包都有成千上万的依赖关系,手工跟踪它也是一场噩梦。
因此,必须有一种方法让 Composer 知道,以便当「vendor/component1」已经「包含」在「vendor/framework」包中时,它应该告诉你「vendor/component1」不再需要单独存在了。
这可以通过在「vendor/framework」中放置替换属性来实现
安全注意事项
不过,这种行为显然有不必要的副作用。因为如果你需要一个不存在的包,而替换程序用自己的Fork(Fork 上有恶意代码)替换它,那么你就注定要失败。
该问题的解释超出了本文的范围,但是 你必须对这一问题进行自我教育,这样才能防止有人在你的代码库中「注入」恶意代码。
你可以检查以下线程以更好地了解此安全隐患:
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
学习了 :+1: :+1: