【问题标题】:How do I use a Git submodule with a Composer loaded library?如何将 Git 子模块与 Composer 加载的库一起使用?
【发布时间】:2013-08-08 15:42:30
【问题描述】:

我有一个 Zend Framework 2 应用程序。它包含一些包含业务逻辑的库代码和一些其他实用程序,这些实用程序将在以后创建的其他应用程序中通用。

我的目的是使用 Composer 跨项目共享它。问题是,我该如何正确地做到这一点并简化开发?我几乎肯定需要从另一个项目中对库进行更改和添加。

我尝试将vendor/stuff 设置为包含所需包的git 子模块,并在主composer.json 中引用它,就像这样(ref)

"repositories": [
    {
        "type": "git",
        "url": "vendor/stuff"
    }
],
"require": {
    "stuff/library": "master"
},

Composer 无法以这种方式加载它。它抱怨找不到包,大概是因为它忽略了 URL 既是本地的又是相对的事实。从技术上讲,它不需要; vendor/stuff 文件夹是通过 git 子模块命令单独初始化的。

【问题讨论】:

    标签: composer-php


    【解决方案1】:

    不幸的是* Composer 不支持 Git 子模块,因为 Composer 的主要目的是提供类似的项目间依赖功能,尝试在 Composer 中复制子模块毫无意义。

    我遇到了您正在尝试解决的相同问题,即在开发库的同时开发使用该库的应用程序。有几种方法可以仅使用 composer 来解决这个问题。

    为库目录创建符号链接

    这是最快最脏的方法。只需进行 composer update 以在您的供应商目录中为库创建适当的目录,然后将其替换为包含您的库的目录中的符号链接。

    显然这不是很好,因为您可能会意外覆盖您可能通过运行 composer update 编辑过的代码。

    使用 Composer 首选源选项

    Composer 可以选择通过 Git 克隆 (--prefer-src) 下载源代码,而不是默认下载 zipball (--prefer-dist)。这允许您在 vendor 目录中编辑源代码,然后通过 Git 提交。

    例如假设您的项目需要在其他库 symfony/yaml 中修复错误。您可以做的是:

    1. composer update - 这将下载项目的所有依赖项。

    2. composer update symfony/yaml --prefer-source - 现在将仅更新供应商目录中的 symfony/yaml 目录。

    3. 修复bug,然后通过git提交。

    使用 Composer 本地存储库

    我在开发项目时——实际上——过去的工作方式是使用 Composers 的能力来显式设置用于解决依赖关系的存储库。例如如果您的代码在:

    /projects/library/
    /projects/project/
    

    在项目的 composer 文件中添加存储库条目:

    "repositories": [
        {
            "type": "vcs",
            "url": "/projects/library/"
        }
    ]
    

    运行 composer update 现在将查看 /projects/library/ 中的 Git 条目,以优先解决对库的任何依赖项,而不是 Packagist 或其他存储库中列出的那些。

    这确实意味着当您想要测试库代码中的更改时,您需要:

    1. 提交它,使其有一个 Git 条目。

    2. 在项目目录中运行 Composer update 以获取最新版本。

    但是您避免了将提交推送到外部存储库,这很好,因为这意味着您不会推送可能无法工作的代码,这意味着您可以离线工作,因为 Git 提交不需要互联网连接.


    虽然这显然是最好的工作方式,但它仍然有点危险,因为很容易意外签入包含本地目录引用的 composer.json 版本,这显然会破坏其他所有人的项目.

    为了避免这种情况,我制作了几个小脚本,i) 备份我真正的 composer.json 文件,ii) 添加一些本地存储库,iii​​) 运行 composer updateiv) 恢复真正的 composer.json 文件。

    localupdate.sh

    cp -f composer.json composer.json.bak
    php composerLocal.php
    composer update
    cp -f composer.json.bak composer.json
    

    composerLocal.php

    <?php
    
    $srcFile = file_get_contents("composer.json");
    $hackFile = file_get_contents("composer.local");
    $finalString = str_replace('"LOCALHACK",', $hackFile, $srcFile);
    file_put_contents("composer.json", $finalString);
    
    ?>
    

    composer.local

    "LOCALHACK",
    
    "repositories": [
        {
            "type": "vcs",
            "url": "/projects/library1"
        },
        {
            "type": "vcs",
            "url": "/projects/library2"
        }   
    ],
    

    然后将"//": "LOCALHACK", 放置在您的项目composer.json 文件中的某个位置。运行 localupdate.sh 现在可以安全地针对本地存储库执行 composer 更新,而不会提交错误版本的 composer.json。

    用 Git 自己克隆它

    这就是我现在的工作方式:

    i) 项目中的 Composer 更新 ii) 进入 vendor 目录并删除我想要同时开发的库。 iii) 从您正在开发库的任何存储库中将 Git 克隆到相应的供应商目录中。

    Composer 理解 git repos,因此不会覆盖 git 克隆的目录(尽管它似乎对编辑库的 composer.json 感到有些困惑)。

    自己进行 git clone,让您可以完全控制安装的内容,并允许您从 composer 不知道的 repo 或未标记的版本进行安装,而无需在项目中编辑 composer.json .

    这是自己进行 git clone 的关键特性;通过不接触项目的 composer.json,它是完全安全的,不可能签入已修改为使用本地/自定义 repos 的 composer.json。

    • 编辑 - 2014 年 9 月 6 日

    composer.json 文件的验证已加强,文件中不再可能有 "//": "LOCALHACK" 条目。这也是 Composer 人员没有为 Composer 项目进行版本控制的另一个原因。

    * 我实际上认为 Git 子模块是一个愚蠢的、愚蠢的、愚蠢的实现,它以一种只会导致更多问题的方式“解决”一个难题,因此 Composer 不支持它们比“幸运”得多不幸的'。显然其他人确实使用它们,并且对它们感到满意,所以这只是我的意见,伙计,但如果你使用 Composer,你不应该需要子模块。

    【讨论】:

    • 这一点“使用 Composer 首选源选项”消除了我切换到 composer 的困境。感谢您广泛回答问题!
    • +1 到“如果您使用作曲家,则不需要子模块。”
    • 我在编辑 composer 使用 global installation 安装的依赖项时遇到了麻烦,因为它将文件的所有权设置为 root 并且我的 IDE 没有权限。我通过将作曲家移动到 ~/bin/composer 并在我的 PATH 中包含 ~/bin 来解决这个问题。
    • 我最终做了类似于 LOCALHACK 的事情,只不过它是 a script which merges the JSON and triggers composer against a temporary file
    • Just clone it yourself with Git 仍然有效,但如果您使用最新版本运行 compser update,它不会忽略该软件包 - 而是 will warn you if it overwrites files
    【解决方案2】:

    期望的行为:

    • 您有 2 个 Zend 项目:project_Aproject_B
    • 两个项目都使用同一个名为 library_C 的通用库
    • library_Cproject_Aproject_B 通过作曲家需要的
    • library_C 应该可以在 project_Aproject_Bvendor 文件夹中编辑,并且您应该能够推送这些更改李>
    • 你的库的 git URL 是https://github.com/stuff/library_C.git

    怎么做:

    1. 将你的库放在 project_Aproject_Bcomposer.json
    "require": {
        "stuff/library_C": "master"
    },
    

    2.运行作曲家安装。现在您的库位于文件夹 vendor/stuff/library_C

    3.现在,当您想在 project_Aproject_B 中编辑 library_C 中的内容时,请删除文件夹 vendor/stuff/library_C 并运行此命令

    git submodule add -f https://github.com/stuff/library_C.git vendor/stuff/library_C
    

    此命令将重新创建此文件夹 vendor/stuff/library_C,但此文件夹现在是另一个 git repo(子模块)

    4.转到文件夹 vendor/stuff/library_C 更改任何内容并提交并推送,这就是全部!!!

    之后,当您在其他项目中运行 composer update stuff/library_C 时,代码将被更新。

    注意:运行后 git submodule add 您将在一个分支主机上,因此您必须签出到正确的分支或标签并在那里进行更改。

    【讨论】:

      【解决方案3】:

      Composer 具有自动加载映射功能,如果您的库遵循 PSR-x 标准,该功能对于执行您的要求非常有用。也可以按照类似的过程自动加载非 psr-x 库。

      这里参考:https://getcomposer.org/doc/04-schema.md#autoload

      我们举个例子(假设你的库遵循 PSR-4 标准)

      假设您已经克隆了文件夹 lib/your-private-git-repo 中的子模块。

      您所要做的就是添加到您的composer.json 文件自动加载部分:

      {
          "name": "YourNamespace/YourApplicationName",
          "description": "Describe your library",
          "license": "Your licen",
          "keywords": ["some","keywords"],
          "authors": [
              {
                  "name": "Adamo Aerendir Crespi",
                  "email": "hello@aerendir.me"
              }
          ],
          "require": {
              "joomla/framework": "*@stable"
          },
          "require-dev": {
              "phpunit/phpunit": "*@stable"
          },
          "autoload": {
              "psr-4": {
                  "YourNamespace\\YourSubmodule\\": "lib/your-private-git-repo/src"
              }
          }
      }
      

      注意从代码底部算起的第六行

          "autoload": {
              "psr-4": {
                  "YourNamespace\\YourSubmodule\\": "lib/your-private-git-repo/src"
              }
          }
      

      现在更新 Composer

      php composer.phar update
      

      这样,Composer 也会更新包含子模块的自动加载文件。

      全部完成:现在您的子模块由 Composer 自动加载。

      希望这会有所帮助。

      【讨论】:

      • 这不是 OP 的问题。问题是,如果您运行composer install,它不会安装子模块的composer.json 中提到的可能依赖项。
      【解决方案4】:

      如果您有一个包含 git 子模块的项目 A,那么从项目 A 调用 composer install/update.. 将忽略您子模块中的所有作曲家依赖项。

      简而言之,如果 git 子模块包含 composer 依赖项,则不要使用它。

      我宁愿这样做:

      1) 如果它不是官方包(如 fork 或私有存储库),请将存储库添加到 composer.json

      "repositories": [
          {
              "type": "vcs",
              "url": "https://github.com/vendor_name/package_name.git"
          }
      ],
      

      2) 需要--prefere-source的包:

      composer require vendor_name/package_name --prefer-source
      

      注意:如果你将official/mango fork 到你自己的仓库ralf/mango 中,那么你需要在composer.json 中指向ralf/mango,但是调用composer require official/mango ..`你可以阅读@中的详细信息987654321@.

      现在您可以从供应商内部访问文件并推送等。--prefere-source 命令已经在供应商文件中设置了 git 连接。

      如果您想从您的根文件夹(如 package/mango 而不是 vendor/official/mango)访问包,您可以设置一个符号链接。

      【讨论】:

        猜你喜欢
        • 2014-02-24
        • 2019-07-15
        • 2019-04-06
        • 2017-06-29
        • 1970-01-01
        • 2014-10-23
        • 2014-08-29
        • 2021-08-15
        • 2019-06-10
        相关资源
        最近更新 更多