Composer

Разместил несколько наиболее применяемых и полезных команд, которые нужны каждому Composer-новичку.

Установка пакета

Добавление гит-пакета heartcode/CanvasLoader, который не размещен на сайте packagist.org

1. нужно в файл composer.json добавить:

    "repositories":[
        ... тут могут быть уже существующие репозитории, а ниже прописываем новый
        {
            "type":"package",
            "package":{
                "name":"heartcode/CanvasLoader",
                "version":"1.2.3",
                "source":{
                    "type":"git",
                    "url":"http://github.com/heartcode/CanvasLoader",
                    "reference":"master"
                }
            }
        }
    ],

заметка: в reference можно указать имя ветки, коммит или даже тэг

Теперь пакет Composer будет думать, что пакет heartcode/CanvasLoader зарегистрирован на сайте packagist.org

Но, кроме этого пакет нужно добавить в require:

2. Добавление composer-пакета: 

    "require": {
        ...тут могут быть прописаны др. пакеты
        "heartcode/CanvasLoader": "1.*"
    },

а теперь в консоле выполните команду:

$ composer update heartcode/CanvasLoader

эта команда установит только heartcode/CanvasLoader, а все остальные пакеты обновлены не будут, это очень важно.

Добавление пакета в директории рядом

"repositories": [
    {
        "name": "my/package",
        "type": "path",
        "url": "libs/my_lib",
        "options": {
            "symlink": true
        }
    }
},
"require": {
    "my/package": "^1.0"
}

и конечно в файле libs/my_lib/composer.json нужно прописать версию пакета, пример:

{
    "name": "my/package",
    "version": "1.0",
    "require": {
        "php": "7.4.*"
    },
    "autoload": {
        "psr-4": {
            "My\\Space\\": "src/"
        }
    }
}

И, после команды composer update my/package в директории vendor будет создан симлинк на директорию libs/my_lib.

Удаление пакета

Удалите выше добавленные в файл composer.json упоминания о пакете и в консоле выполните команду:

$ composer update heartcode/CanvasLoader

и Composer удалит директорию из папки vendor, удачки.

Конфликт

Если композер говорит:

Your requirements could not be resolved to an installable set of packages.

например:

# composer update monolog/monolog --prefer-source
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for theorchard/monolog-cascade ^0.2.0 -> satisfiable by theorchard/monolog-cascade[0.2.0].
    - Conclusion: remove symfony/yaml v2.6.4
    - Conclusion: don't install symfony/yaml v2.6.4
    - theorchard/monolog-cascade 0.2.0 requires symfony/yaml ~2.7.0 -> satisfiable by symfony/yaml[v2.7.0, v2.7.1, v2.7.2, v2.7.3, v2.7.4].
    - Can only install one of: symfony/yaml[v2.7.0, v2.6.4].
    - Can only install one of: symfony/yaml[v2.7.1, v2.6.4].
    - Can only install one of: symfony/yaml[v2.7.2, v2.6.4].
    - Can only install one of: symfony/yaml[v2.7.3, v2.6.4].
    - Can only install one of: symfony/yaml[v2.7.4, v2.6.4].
    - Installation request for symfony/yaml == 2.6.4.0 -> satisfiable by symfony/yaml[v2.6.4].

т.е. нужно обновить так же symfony/yaml, а значит пишем:

composer update monolog/monolog symfony/yaml

и теперь все пойдет как по маслу (а если нет, то следом указывайте др. необходимые к обновлению компоненты).

Конфликт 2

Если Вы добавляете в проект свой пакет, например:

$ composer update yapro/debug
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

Problem 1
- The requested package datravel/php-debug could not be found in any version, there may be a typo in the package name.

Potential causes:
- A typo in the package name
- The package is not available in a stable-enough version according to your minimum-stability setting
see <https://groups.google.com/d/topic/composer-dev/_g3ASeIFlrc/discussion> for more details.

Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.

то обратите внимание, возможно Вы в файле composer.json неправильно прописали минимально возможную версию, которую кстати можно узнать на сайте https://packagist.org/packages/yapro/debug (в настоящий момент версия пишется  слева, сразу ниже названия пакета и по-умолчанию dev-master. Например у меня было:

    "require": {
        "yapro/debug": "*"
    },

а стало:

    "require": {
        "yapro/debug": "dev-master"
    },

Конфликт 3

Кода у Вас vendor под git-ом, то Ваши вендоры могут не содержать директории .git и composer update скажет Вам:

[RuntimeException]
The .git directory is missing from /var/www/site/vendor/yapro/debug, see https://getcomposer.org/commit-deps for more information

самый простой способ решить данную проблему - установить зависимость заново:

rm -rf vendor/yapro/debug/

composer update yapro/debug

готово.

Оптимизация

p.s. не забывайте перед выкладкой на продакшен выполнять команду:

composer install -o
composer dump-autoload --optimize

и при сборке билда в докере:

composer install -o --no-scripts

Хитрость

Если Вы форкнули проект на гитхабе, создали ветку, сделали коммит в этой ветке и заслали PR, то не ждать же пока PR дойдет до вендора! Поэтому, в файл composer.json добавляем форк в виде репозитория с указанием своей ветки my-branch:

    "repositories":[
        ...
        {
            "type":"vcs",
            "url":"http://github.com/yapro/some-project"
        }
        ...
    ],
    ...
    "require": {
        ...
        "some-company/some-project": "my-branch",
        ...
    },

и выполняем команду обновления чужого проекта

composer update some-company/some-project

благодаря такой хитрости, composer сначала поищет ветку my-branch в репозитории http://github.com/yapro/some-project

Хитрость с BitBucket

Выглядит так же, как и выше описанный пример, однако, обратите внимание, чтобы composer не задавал нам вопросы авторизации в BitBucket, а использовал ssh-ключ доступа, мы укажим путь к репозиторию в виде git-ссылки:

    "repositories":[
        ...
        {
            "type":"vcs",
            "url":"git@bitbucket.org:lebnik/test-for-composer.git"
        }
        ...
    ],
    ...
    "require": {
        ...
        "lebnik/test-for-composer": "dev-master",
        ...
    },

При этом не забудьте в корень BitBucket-проекта положить файл composer.json с приблизительно таким содержимым:

{
  "name":        "lebnik/test-for-composer",
  "description": "Common classes",
  "version":     "0.0.7",
  "type":        "library",
  "keywords":    ["php", "common", "classes"],
  "homepage":    "https://bitbucket.org/lebnik/test-for-composer",
  "license":     "MIT",

  "autoload": {
    "psr-4": {
      "TestForComposer\\": "src/"
    }
  },

  "target-dir": ""
}

Минимальный конфиг:

{
  "name":        "mol/queue",
  "type":        "library",
  "autoload": {
    "psr-0": {
      "Queues" : "src"
    }
  }
}

И далее, как и раньше подключаем зависимость:

       {
           "type":"vcs",
           "url":"ssh://git@stash.combany.ru:5555/mol/queue.git"
       }

и внимание: если подключаемая ветка названа feature/SUPPORT-61, то указываем версию зависимости с префиксом dev-:

   "require": {
       "mol/queue": "dev-feature/SUPPORT-61",

Проблема с форком

Я форкнул репозиторий, который имеется в packagist.org, и воспользовался инструкцией:

{
    "name": "my.name/test",
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/yapro/php-barcode-generator"
        }
    ],
    "require": {
        "yapro/php-barcode-generator": "v0.2.2"
    }
}

Однако, при выполнении команды composer update yapro/php-barcode-generator, я постоянно получал ошибку:

Your requirements could not be resolved to an installable set of packages.

  Problem 1

    - The requested package gemotest/php-barcode-generator could not be found in any version, there may be a typo in the package name.

Potential causes:

 - A typo in the package name

 - The package is not available in a stable-enough version according to your minimum-stability setting

   see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.

Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.

И быть может, я неправильно прописал, но настройки минимально стабильной версии никак не помогли мне:

    "minimum-stability": "dev",
    "prefer-stable" : true,
    "require": {
        "yapro/php-barcode-generator": "v0.2.2*@dev"
    }

В итоге, пришлось отказаться от инструкции "type": "vcs", и воспользоваться "type":"package".

Проблема неправильного именования классов

Если в проекте случайно 2 класса назвали одинаковым именем (включая неймспейс) и пока что ничего не поломалось, то Вам повезло, срочно переименовывайте неправильно названный класс. Потому, что в зависимости от файловой системы, composer может прочитать и составить маппинг по-разному, наглядный пример файла autoload_classmap.php на тестовом сервере:

Composer : полезные команды

а теперь пример этого же файла autoload_classmap.php на своей локальной машине:

Composer : полезные команды

Возможно разное поведение вызвано немного разными версиями PHP или разными файловыми системами, н в итоге, проблема автору известная и сейчас в таких случаях composer выдает предупреждения:

Composer : полезные команды

Мне кажется всего лишь показывать "Warning: Ambiguous class resolution" плохое решение, я бы сразу завершал работу composer-а с ошибкой, потому что из-за такой мелочи лично я на тестовом стенде убил 4 часа, а представляете что такое возникло на проде, нее, так нельзя. Казалось бы, откуда 4 часа трудозатрат, а оттуда, что все работает корректно, потому, что даже методы в данных классах называются одинаково (get_list) отличается только результат, в одном случае это список заказов, в др. случае это пустой список.

Игнорирование проблем с зависимостями

Иногда, пакет может работать например с более новой версией php, но разработчик пакета не тестировал свой пакет и поэтому указал там версию php, которую сам использует, обойти это можно с помощью флага "ignore-platform-reqs", например:

composer require zircote/swagger-php --ignore-platform-reqs

Указываем путь установки пакета в composer

Чтобы не использовать "post-install-cmd" и "post-update-cmd", с помощью которых некоторые советую перемещать пакет (суб-репозиторий), считаю можно использовать симлинки, ведь это проще.

К примеру мы добавили некий пакет (гит-проект) "usmanhalalit/charisma" - форк от "twbs/bootstrap", и по сути проект с готовыми JS и CSS-решениями.

{
    "name": "symfony/framework-standard-edition",
    "license": "MIT",
    "type": "project",
    ...
    "repositories":[
        {
            "type":"package",
            "package":{
                "name":"usmanhalalit/charisma",
                "version":"1.2.3",
                "source":{
                    "type":"git",
                    "url":"http://github.com/usmanhalalit/charisma",
                    "reference":"master"
                }
            }
        }
    ],
    "require": {
        "php": ">=5.3.3",
        "usmanhalalit/charisma": "1.*"
    },
    ...
}

Т.к. мы используем Symfony, "usmanhalalit/charisma" нам нужен в папке web/assets

Поэтому, заходим в web/assets и делаем симлинк:

# ln -s ../../../vendor/usmanhalalit/charisma/ charisma

вуаля, и пакет у нас лежит в папке vendors и теперь доступ к нему есть посетителям сайта.

p.s. добавлять в .gitignore папку web/assets/charisma не нужно, и не беспокойтесь, когда будете коммитить, гит увидит что симлинк это не папка и закоммитит симлинк.

Подмена класса

Если возникла необходимость подменить класс, то сделать это с помощью autoload classmap не выйдет: 

{
    "autoload": {
        "classmap": ["src/", "lib/", "Something.php"]
    }
}

Вы просто получите ошибку: ... redefine class because the name is already in use in ...

Но, переопределить класс все таки можно с помощью кода, например создав такой файл config/autoload.php

<?php
declare(strict_types=1);
$composer = require __DIR__.'/../vendor/autoload.php';
$composer->addClassMap(["Symfony\Component\ErrorHandler\ErrorHandler" => "/app/config/MyErrorHandler/ErrorHandler.php"]);

а затем этот файл можно указать в нужных Вам местах, например в bin/console:

<?php
use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
   throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".');
}
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
require_once __DIR__.'/../config/autoload.php';
...

и в public/index.php:

<?php
use App\Kernel;
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
require_once __DIR__.'/../config/autoload.php';
return function (array $context) {
    return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
};

не забывайте, очень важен порядок указания файлов, см. require_once __DIR__.'/../config/autoload.php';

p.s. может быть подобного эффекта можно добиться с помощью добавления в composer.json вызова своего скрипта:

    "scripts": {
        "auto-scripts": {
            "My\\ScriptHandler::myBuild"
        },
        "post-install-cmd": [
            "@auto-scripts"
        ],
        "post-update-cmd": [
            "@auto-scripts"
        ]
    },

а свой скрипт будет выглядеть как-то так:

public static function myBuild(Event $event)
{
    list($installPath, $vendorPath) = self::prepareBaseDirectories($event);
    ...
}

Gold standard 

В Symfony документации сказано использовать для production:

composer dump-autoload --optimize --no-dev --classmap-authoritative

  • --optimize Dumps every PSR-0 and PSR-4 compatible class used in your application.
  • --no-dev Excludes the classes that are only needed in the development environment (e.g. tests).
  • --classmap-authoritative Prevents Composer from scanning the file system for classes that are not found in the class map - отключение механизма обнаружения PSR-0/4 (так что любой класс, не представленный в карте классов, не будет найден, без проверки файловой системы для этого).

If you have APCu installed, you can use --apcu

Еще

  1. Плагины композера: 1 - 2
  2. Фичи 2-ой версии: 1
  3. Возможности командной строки: 1
  4. События композера: 1

Источник: 1 - 2


27.11.2013 12:19

Комментарии

в удалении пакетов ошибка... должно быть remove а не update
Гость | 05.05.2017 04:36