如何将Git子模块与Composer加载的库一起使用?

时间:2013-08-07 10:01:52

标签: composer-php

我有一个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 submodule命令单独初始化的。

4 个答案:

答案 0 :(得分:42)

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

我有同样的问题,你试图解决,开发一个库,同时开发使用该库的应用程序。有几种方法可以使用composer来解决这个问题。

为库目录

创建符号链接

这是最快捷,最脏的方式。只需做一个作曲家更新,为vendor目录中的库创建适当的目录,然后用包含库的目录中的符号链接替换它。

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

使用Composer首选源选项

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

e.g。假设您有其他库symfony/yaml需要修复错误的项目。您可以做的是:

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

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

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

  4. 使用Composer本地存储库

    我实际上用来工作的方式 - 当我开发一个项目及其需求时,就是使用Composers的能力设置显式设置一个存储库来用来解决依赖。例如如果你的代码在:

    /projects/library/
    /projects/project/
    

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

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

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

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

    1. 提交它,以便它有一个Git条目。

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

    3. 但是你不必将提交推送到外部存储库,这很好,因为这意味着你不会推送可能不起作用的代码,这意味着你可以脱机工作,因为Git承诺不要需要互联网连接。


      虽然这显然是最好的工作方式,但它仍然有点危险,因为它很容易意外地检入你的composer.json版本,它引用了本地目录,这显然会打破适合所有人的项目。

      为了避免这种情况,我制作了几个小脚本,i)备份我的真实composer.json文件,ii)添加一些本地存储库,iii​​)运行composer update iv)恢复真正的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.json。

      使用Git

      自己克隆它

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

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

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

      自己进行git克隆,让您完全控制安装的内容,并允许您从作曲家不知道的repo或无标记版本进行安装,而无需编辑composer.json in该项目。

      这是自己做git克隆的关键特性;通过不触及项目的composer.json,它是完全安全的,不可能检入已经修改为使用本地/自定义存储库的composer.json。

      • 编辑 - 2014年9月6日

      对composer.json文件的验证已经收紧,并且不再可能在文件中有"//": "LOCALHACK"条目。这也是为什么Composer人员没有为Composer项目进行版本控制的另一个原因。

      *我实际上认为Git Submodules是一个愚蠢,愚蠢,愚蠢的实现,以解决问题。一个困难的问题,只会导致更多的问题,所以作曲家不支持他们是更幸运的&#39;比不幸的#39;显然其他人确实使用它们,并对它们感到满意,所以这只是我的意见,伙计,但是如果您使用Composer,那么您就不需要子模块。

答案 1 :(得分:2)

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自动加载。

希望这会有所帮助。

答案 2 :(得分:0)

如果您的项目A包含git子模块,则从项目A调用composer install/update..将忽略子模块中的所有composer依赖项。

简而言之,如果git子模块包含作曲者依赖性,则不要使用它。

这就是我宁愿这样做的方式:

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派生到自己的存储库ralf/mango中,则需要指向ralf/mango中的composer.json,但致电作曲家需要Official / mango。 `您可以在docs中阅读详细信息。

现在您可以从供应商内部访问文件并进行推拉操作。--prefere-source命令已经在供应商文件内部设置了git连接。

如果您想通过package/mango之类的根文件夹(而不是vendor/official/mango)访问该软件包,则可以设置符号链接。

答案 3 :(得分:0)

所需行为:

  • 您有2个Zend项目: project_A project_B
  • 两个项目都使用名为 library_C
  • 的相同公共库 通过作曲家的 project_A project_B 需要
  • library_C
  • library_C 应该可在 project_A project_B 供应商文件夹中进行编辑,并且您应该能够推送这些内容变化
  • 您的库的git URL为https://github.com/stuff/library_C.git

操作方法:

  1. 将您的库放在 project_A project_B
  2. composer.json
"require": {
    "stuff/library_C": "master"
},

2.run composer install 。现在您的图书馆位于文件夹 vendor / stuff / library_C

3。现在,当您要在 project_A project_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子模块后添加 您将在分支机构主管上,因此必须签出到正确的分支机构或标签并在此处进行更改。