31

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

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

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

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

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

4

4 回答 4

51

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

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

为库目录创建符号链接

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

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

使用 Composer 首选源选项

Composer 可以选择通过 Git 克隆 ( --prefer-src) 下载源代码,而不是默认下载 zipball ( --prefer-dist)。这允许您编辑供应商目录中的源代码,然后通过 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/"
    }
]

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

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

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

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

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


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

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

本地更新.sh

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

作曲家Local.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);

?>

作曲家.local

"LOCALHACK",

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

然后放置在您的项目文件"//": "LOCALHACK",中的某个位置。composer.json现在安全运行localupdate.sh会针对本地存储库进行作曲家更新,而不会提交错误版本的 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,你不应该需要子模块。

于 2013-08-08T15:44:08.080 回答
2

期望的行为:

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

怎么做:

  1. 将您的库放在project_Aproject_B的composer.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后, 您将位于分支主节点上,因此您必须签出到正确的分支或标签并在那里进行更改。

于 2020-11-11T21:40:57.120 回答
1

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"
        }
    }

现在更新作曲家

php composer.phar update

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

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

希望这会有所帮助。

于 2015-01-21T23:30:32.463 回答
0

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

简而言之,如果 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

注意:如果你 forkofficial/mango到你自己的存储库ralf/mango,那么你需要指向ralf/mangoin composer.json,但是调用 composer require official/mango ..`你可以阅读文档中的详细信息。

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

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

于 2019-12-08T12:37:43.167 回答