$composer global require xxx
Changed current directory to /Users/didi/.composer
You are running Composer with SSL/TLS protection disabled.
./composer.json is not readable.
$ cat /usr/local/ssl/cert.pem
<!DOCTYPE HTML PUBLIC “-//IETF//DTD HTML 2.0//EN”>
The document has moved here.
rm -rf /usr/local/ssl/cert.pem
~$composer
Segmentation fault: 11
rm -rf ~/.composer/
正常
https://stackoverflow.com/questions/24675167/ca-certificates-mac-os-x
$brew uninstall –ignore-dependencies openssl
Uninstalling /usr/local/Cellar/openssl@1.1/1.1.1g… (8,052 files, 18.4MB)
Warning: The following openssl@1.1 configuration files have not been removed
https://github.com/Homebrew/homebrew-core/issues/28806
$ composer global require xxx -vvv
Changed current directory to /Users/didi/.composer
Loading config file /Users/didi/.composer/config.json
Loading config file /Users/didi/.composer/auth.json
Reading /Users/didi/.composer/composer.json
Loading config file /Users/didi/.composer/config.json
Loading config file /Users/didi/.composer/auth.json
Loading config file /Users/didi/.composer/composer.json
Loading config file /Users/didi/.composer/auth.json
Reading /Users/didi/.composer/auth.json
Checked CA file /usr/local/ssl/cert.pem: invalid
Segmentation fault: 11
$lldb -c /cores/core.1795
(lldb) target create –core “/cores/core.1795”
warning: (x86_64) /cores/core.1795 load command 113 LC_SEGMENT_64 has a fileoff + filesize (0x28cd0000) that extends beyond the end of the file (0x28ccf000), the segment will be truncated to match
Core file ‘/cores/core.1795’ (x86_64) was loaded.
(lldb) bt
openssl.so was compiled with optimization - stepping may behave oddly; variables may not be available.
zif_openssl_x509_parse [inlined] php_openssl_add_assoc_asn1_string(val=0x000000010f222d90, key=<unavailable>, str=0xffffffffffffffff) at openssl.c:913 [opt]
frame #1: 0x000000010f52c1fe openssl.so
zif_openssl_x509_parse(execute_data=https://unix.stackexchange.com/questions/368355/where-and-how-do-i-obtain-and-install-certificates-to-a-new-installation-of-open
https://superuser.com/questions/437330/how-do-you-add-a-certificate-authority-ca-to-ubuntu
https://github.com/composer/composer/issues/8231
https://github.com/composer/composer/blob/master/README.md
https://curl.haxx.se/docs/caextract.html
curl –remote-name –time-cond cacert.pem https://curl.haxx.se/ca/cacert.pem
ls
cp cacert.pem /usr/local/ssl/cert.pem
cat /usr/local/ssl/cert.pem
1、下载composer代码
2、同级目录创建 composer.json 文件
3、通过php执行composer代码(composer使用php写的)读取composer.json 中的文件并下载指定库 指定版本 到 指定文件夹
php执行composer的命令可以写成 bat脚本(win平台),添加脚本路径到环境变量 path ,命令行可以直接执行 composer 命令来使用composer (添加path 自行google, cmd命令set path 的方式是临时修改 所以务必通过计算机右键 属性 的方式修改)
我们已经知道 composer是php写出来的一个脚本 所以第一步我们要下载composer的php源代码 然后通过 php 来执行composer源代码 就可以使用了
Packagist:
用来管理软件的商店。但是它只是起到了一个链接的作用,实际上软件是从github中下载的。因此,我们还要把github和packagist连接起来。
安装composer
下载安装脚本 - composer-setup.php - 到当前目录
php -r “copy(‘https://getcomposer.org/installer’, ‘composer-setup.php’);”
执行安装过程
php composer-setup.php 。将生成一个composer.phar文件
删除安装脚本
php -r “unlink(‘composer-setup.php’);”
Mac 或 Linux 系统:
将composer.phar 文件移动到 /usr/local/bin/ 目录下面:
sudo mv composer.phar /usr/local/bin/composer
composer 项目的控制台应用依赖于 Symfony 控制台组件
installer 是啥
它是一个 php 脚本文件,执行 php installer 后运行
初始化 installer
function setupEnvironment()
{
ini_set(‘display_errors’, 1);
$installer = ‘Composer Installer’;
//win系统版本号,如果你的系统是win10返回10【本人觉得win系统开发复杂,因为我真的没法调度程序】
if (defined(‘PHP_WINDOWS_VERSION_MAJOR’)) {
if ($version = getenv(‘COMPOSERSETUP’)) {
$installer = sprintf(‘Composer-Setup.exe %s’, $version);
}
}
define(‘COMPOSER_INSTALLER’, $installer);
}
` process
//$argv位置参数,来源于linux运行一个程序时,会把位置参数传递给main入口
process(is_array($argv) ? $argv : array());
function process($argv)
{
//安装选项参数https://getcomposer.org/download/说明
//对于我来说,无用
//运行时可配置安装位置
$installDir = getOptValue(‘–install-dir’, $argv, false);
//可指定版本,不指定就拉取最新的版本
$version = getOptValue(‘–version’, $argv, false);
//默认下载后重命名为composer.phar一般默认
$filename = getOptValue(‘–filename’, $argv, ‘composer.phar’);
$cafile = getOptValue(‘–cafile’, $argv, false);
//$installDir $version $cafile 检查你提供的参数是否有效【就是你在安装的时候是否指定了这些选项,指定了就会检查】
if (!checkParams($installDir, $version, $cafile)) {
exit(1);
}
//检测你的PHP环境如扩展有没有安装好
$ok = checkPlatform($warnings, $quiet, $disableTls, true);
if ($check) {
if ($ok) {
showWarnings($warnings);
showSecurityWarning($disableTls);
}
exit($ok ? 0 : 1);
}
if ($ok || $force) {
//实例化安装器
$installer = new Installer($quiet, $disableTls, $cafile);
//开始安装
//1先从https://getcomposer.org/versions 获取目前官网最新的版本号
//所以你在安装的时候是可以指定版本号的,不然默认就是拉取最新的
//2、从https://getcomposer.org/download/1.10.5/composer.phar 下载此项目
//phar文件是PHP的PHAR扩展打包的php项目【如果你用过PHAR扩展打包过,就知道了】
//非常的简单
if ($installer->run($version, $installDir, $filename, $channel)) {
//装完退出当前进程
exit(0);
}
}
exit(1);
}
安装说明:php composer-setup.php 文件时从 getcomposer.org 网站下载打包好的 composer.phar 项目到本地
#!/usr/bin/env php
Composer 工作原理详说 [源码注解] 并非 PPT 概念扯蛋
入口文件源码【精简提炼了,大堆受不了】
#!/usr/bin/env php env可执行文件它最终会找php解释器如上图
<?php
if (PHP_SAPI !== ‘cli’ && PHP_SAPI !== ‘phpdbg’) {
}
//引入自动【自动加载php类文件】加载文件
require DIR.’/../src/bootstrap.php’;
putenv(‘COMPOSER_BINARY=’.realpath($_SERVER[‘argv’][0]));
// run the command application
//控制台应用依赖于Symfony框架
//具体如何使用本人在laravel5.5LTS版本注解过
//如果你不清楚可以去看看,或是到symfony官方找到控制台应用组件复制粘贴运行一下就懂
//实在懒的看算了 本人不在重复
$application = new Application();
$application->run();
composer.phar 依赖的扩展包
autoload.php composer justinrainbow psr seld symfony
composer 控制台应用 run 流程
加载命令类文件
建议自行去撸一下 symfony 的控制台组件,如果不想撸可以看我这里的大体说明,其它的如加载用户自定义的插件命令,加载 composer 的配置文件,auth 文件,初始化各种如下载管理器,插件管理器等在此不题。
1、$exitCode = $this->doRun($input, $output);
2、$command = $this->find($name);
//添加所有命令
3、$this->init();
private function init()
{
foreach ($this->getDefaultCommands() as $command) {
$this->add($command);
}
}
public function add(Command $command)
{
$command->setApplication($this);
if (!$command->isEnabled()) {
$command->setApplication(null);
return;
}
$this->commands[$command->getName()] = $command;
foreach ($command->getAliases() as $alias) {
$this->commands[$alias] = $command;
}
return $command;
}
protected function getDefaultCommands()
{
$commands = array_merge(parent::getDefaultCommands(), array(
new Command\AboutCommand(),
new Command\ConfigCommand(),
new Command\DependsCommand(),
new Command\ProhibitsCommand(),
new Command\InitCommand(),
new Command\InstallCommand(),
new Command\CreateProjectCommand(),
new Command\UpdateCommand(),
new Command\SearchCommand(),
new Command\ValidateCommand(),
new Command\ShowCommand(),
new Command\SuggestsCommand(),
new Command\RequireCommand(),
new Command\DumpAutoloadCommand(),
new Command\StatusCommand(),
new Command\ArchiveCommand(),
new Command\DiagnoseCommand(),
new Command\RunScriptCommand(),
new Command\LicensesCommand(),
new Command\GlobalCommand(),
new Command\ClearCacheCommand(),
new Command\RemoveCommand(),
new Command\HomeCommand(),
new Command\ExecCommand(),
new Command\OutdatedCommand(),
new Command\CheckPlatformReqsCommand(),
));
if (‘phar:’ === substr(FILE, 0, 5)) {
$commands[] = new Command\SelfUpdateCommand();
}
return $commands;
}
4、$exitCode = $this->doRunCommand($command, $input, $output);
5、return $command->run($input, $output);
//最终运行execute【命令类的方法】
6、$statusCode = $this->execute($input, $output);
Composer 对象构建流程
Composer 项目的关键配置文件目录结构
Composer 对象构建源码
1、实例化NUllIO类
Composer\IO\NullIO extends BaseIO 类
$this->io = new NullIO();
2、工厂Composer\Factory类
Composer\Factory
public static function create(IOInterface $io, $config = null, $disablePlugins = false)
{
$factory = new static();
return $factory->createComposer($io, $config, $disablePlugins);
}
$this->composer = Factory::create($this->io, null, $disablePlugins);
3、createComposer
public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, $cwd = null, $fullLoad = true)
{
$cwd = $cwd ?: getcwd();//当前进程运行的目录
if (null === $localConfig) {
//获取当前项目根目录下的composer.json文件
$localConfig = static::getComposerFile();
}
if (is_string($localConfig)) {
$composerFile = $localConfig;
$file = new JsonFile($localConfig, null, $io);
$file->validateSchema(JsonFile::LAX_SCHEMA);
//读取composer.json的内容
$localConfig = $file->read();
}
//得到配置类Composer/config实例并且合并了.composer目录下的配置文件 config.json auth.json
$config = static::createConfig($io, $cwd);
//合并项目根目录下的composer.json配置文件
$config->merge($localConfig);
$config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
//vendor目录
$vendorDir = $config->get(‘vendor-dir’);
//composer工厂类
$composer = new Composer();
//1、给Composer实例添加【配置实例】
$composer->setConfig($config);
//给baseIo实例添加config实例
$io->loadConfiguration($config);
//工厂类构建Composer\Util\RemoteFileSystem实例
$rfs = self::createRemoteFilesystem($io, $config);
//2、给composer实例添加【事件调度器实例】
$dispatcher = new EventDispatcher($composer, $io);
$composer->setEventDispatcher($dispatcher);
//调用源码仓库工厂构建仓库管理器实例Composer\Repository\RepositoryManager
$rm = RepositoryFactory::manager($io, $config, $dispatcher, $rfs);
//3、给composer实例添加【仓库管理器实例】
$composer->setRepositoryManager($rm);
//给RespositoryManager添加new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.’/composer/installed.json’, null, $io))本地仓库实例对象
//仓库管理器添加了svn,git,github,vsc,composer等仓库管理类实例
$this->addLocalRepository($io, $rm, $vendorDir);
// force-set the version of the global package if not defined as
// guessing it adds no value and only takes time if (!$fullLoad && !isset($localConfig[‘version’])) {
$localConfig[‘version’] = ‘1.0.0’;
}
// 加载扩展包实例
$parser = new VersionParser;
$guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
$loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser, $io);
//4、读取项目根目录下的composer.json配置数据,并保存在Composer\Package\BasePackage 扩展包实例中
//同时根据config.json的配置【镜像类型一般有svn,git,github,composer,vcs等】一般为composer配置了Composer\Repository\ComposerRepository composer仓库实例
$package = $loader->load($localConfig, ‘Composer\Package\RootPackage’, $cwd);
$composer->setPackage($package);
// initialize installation manager
//5、给composer实例添加Installer\InstallationManager() 【安装管理器】
$im = $this->createInstallationManager();
$composer->setInstallationManager($im);
if ($fullLoad) {
// initialize download manager
//6、给composer实例添加Downloader\DownloadManager 【下载管理器】
$dm = $this->createDownloadManager($io, $config, $dispatcher, $rfs);
$composer->setDownloadManager($dm);
//7、给composer实例添加【自动加载生成器实例】
$generator = new AutoloadGenerator($dispatcher, $io);
$composer->setAutoloadGenerator($generator);
// 8、给composer实例添加压缩【ZIP,PHAR打包】归档管理器
$am = $this->createArchiveManager($config, $dm);
$composer->setArchiveManager($am);
}
//给安装管理器添加一些安装器【如pear,package,plugin,library】
$this->createDefaultInstallers($im, $composer, $io);
if ($fullLoad) {
$globalComposer = null;
if (realpath($config->get(‘home’)) !== $cwd) {
$globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins);
}
//return new Plugin\PluginManager($io, $composer, $globalComposer, $disablePlugins);
//9、给composer实例添加【插件管理器实例】
$pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins);
$composer->setPluginManager($pm);
//运行用户在composer.json配置的插件类或是composer-installer安装器
$pm->loadInstalledPlugins();
}
public static $defaultRepositories = array(
‘packagist.org’ => array(
‘type’ => ‘composer’,
‘url’ => ‘https?://repo.packagist.org’,//镜像地址,通过composer config便可以修改,比如我上面列出的config.json配置文件
‘allow_ssl_downgrade’ => true,
),
);
public function __construct($useEnvironment = true, $baseDir = null)
{
// load defaults
$this->config = static::$defaultConfig;
$this->repositories = static::$defaultRepositories;
$this->useEnvironment = (bool) $useEnvironment;
$this->baseDir = $baseDir;
}
Composer 类
namespace Composer;
use Composer\Package\RootPackageInterface;
use Composer\Package\Locker;
use Composer\Repository\RepositoryManager;
use Composer\Installer\InstallationManager;
use Composer\Plugin\PluginManager;
use Composer\Downloader\DownloadManager;
use Composer\EventDispatcher\EventDispatcher;
use Composer\Autoload\AutoloadGenerator;
use Composer\Package\Archiver\ArchiveManager;
class Composer
{
const VERSION = ‘@package_version@’;
const BRANCH_ALIAS_VERSION = ‘@package_branch_alias_version@’;
const RELEASE_DATE = ‘@release_date@’;
const SOURCE_VERSION = ‘1.10-dev+source’;
public static function getVersion()
{
return self::VERSION;
}
/**
* @var Package\RootPackageInterface
*/
private $package;
/**
* @var Locker
*/
private $locker;
/**
* @var Repository\RepositoryManager
*/
private $repositoryManager;
/**
* @var Downloader\DownloadManager
*/
private $downloadManager;
/**
* @var Installer\InstallationManager
*/
private $installationManager;
/**
* @var Plugin\PluginManager
*/
private $pluginManager;
/**
* @var Config
*/
private $config;
/**
* @var EventDispatcher
*/
private $eventDispatcher;
/**
* @var Autoload\AutoloadGenerator
*/
private $autoloadGenerator;
/**
* @var ArchiveManager
*/
private $archiveManager;
/**
* @param Package\RootPackageInterface $package
* @return void
*/
public function setPackage(RootPackageInterface $package)
{
$this->package = $package;
}
/**
* @return Package\RootPackageInterface
*/
public function getPackage()
{
return $this->package;
}
/**Composer/Config 实例
* @param Config $config
*/
public function setConfig(Config $config)
{
$this->config = $config;
}
/**Composer/Config 实例
* @return Config
*/
public function getConfig()
{
return $this->config;
}
/**
* @param Package\Locker $locker
*/
public function setLocker(Locker $locker)
{
$this->locker = $locker;
}
/**
* @return Package\Locker
*/
public function getLocker()
{
return $this->locker;
}
/**
* @param Repository\RepositoryManager $manager
*/
public function setRepositoryManager(RepositoryManager $manager)
{
$this->repositoryManager = $manager;
}
/**
* @return Repository\RepositoryManager
*/
public function getRepositoryManager()
{
return $this->repositoryManager;
}
/**
* @param Downloader\DownloadManager $manager
*/
public function setDownloadManager(DownloadManager $manager)
{
$this->downloadManager = $manager;
}
/**
* @return Downloader\DownloadManager
*/
public function getDownloadManager()
{
return $this->downloadManager;
}
/**
* @param ArchiveManager $manager
*/
public function setArchiveManager(ArchiveManager $manager)
{
$this->archiveManager = $manager;
}
/**
* @return ArchiveManager
*/
public function getArchiveManager()
{
return $this->archiveManager;
}
/**
* @param Installer\InstallationManager $manager
*/
public function setInstallationManager(InstallationManager $manager)
{
$this->installationManager = $manager;
}
/**
* @return Installer\InstallationManager
*/
public function getInstallationManager()
{
return $this->installationManager;
}
/**
* @param Plugin\PluginManager $manager
*/
public function setPluginManager(PluginManager $manager)
{
$this->pluginManager = $manager;
}
/**
* @return Plugin\PluginManager
*/
public function getPluginManager()
{
return $this->pluginManager;
}
/**Composer\EventDispatcher 实例
* @param EventDispatcher $eventDispatcher
*/
public function setEventDispatcher(EventDispatcher $eventDispatcher)
{
$this->eventDispatcher = $eventDispatcher;
}
/**
* @return EventDispatcher
*/
public function getEventDispatcher()
{
return $this->eventDispatcher;
}
/**
* @param Autoload\AutoloadGenerator $autoloadGenerator
*/
public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
{
$this->autoloadGenerator = $autoloadGenerator;
}
/**
* @return Autoload\AutoloadGenerator
*/
public function getAutoloadGenerator()
{
return $this->autoloadGenerator;
} } composer 扩展包类结构
Composer 工作原理 [源码分析]
composer 重要命令运行流程说明
composer require 命令
require 命令类结构【继承】图
Composer 工作原理 [源码分析]
//测试composer require nicmart/tree
//$input封装了运行composer脚本时传递的位置参数
//$output对象
RequireCommand->execute(InputInterface $input, OutputInterface $output)
RequireCommand->doUpdate($input, $output, $io, $requirements);
//安装器
Composer\Installer->run();
Composer\Installer->doInstall($localRepo, $installedRepo, $platformRepo, $aliases);
Composer\Installer\InstallationManager->installationManager->execute($localRepo, $operation);
//包安装器
Composer\Installer\LibraryInstaller->install(InstalledRepositoryInterface $repo, PackageInterface $package);
Composer\Installer\LibraryInstaller->installCode(PackageInterface $package)
//下载管理器
Composer\Downloader->download(PackageInterface $package, $targetDir, $preferSource = null);
//git下载管理器
Composer\Downloader\GitDownloader extends VcsDownloader->doDownload(PackageInterface $package, $path, $url);
//git 命令
$command = ‘git clone –no-checkout %url% %path% && cd ‘.$flag.’%path% && git remote add composer %url% && git fetch composer && git remote set-url origin %sanitizedUrl% && git remote set-url composer %sanitizedUrl%’;
Composer\Util\Git->runCommand($commandCallable, $url, $cwd, $initialClone = false);
// 低层源码执行情况【如何跟踪 linux 源码运行情况可以参考本人在 larave 社区写过的 nginx 低层数据交互原理】:
1、execve(“/usr/local/bin/php”, [“php”, “/bin/composer”, “require”, “nicmart/tree”], [/* 26 vars */]) = 0
连接自己配置的镜像
连接国外的镜像网站
2、execve(“/bin/git”, [“git”, “clone”, “–no-checkout”, “https://github.com/nicmart/Tree.”…, “/home/worker/vendor/nicmart/tree”], [/* 29 vars */]) = 0
https://blog.csdn.net/qq_35383263/article/details/105798510
https://github.com/composer/installers
https://getcomposer.org/doc/faqs/how-do-i-install-a-package-to-a-custom-path-for-my-framework.md
https://github.com/composer/composer
https://www.cntofu.com/book/107/PHP%20Composer-%E2%80%94%E2%80%94-%E6%B3%A8%E5%86%8C%E4%B8%8E%E8%BF%90%E8%A1%8C%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90.md
https://www.codenong.com/cs105798510/
https://segmentfault.com/a/1190000014948542
PHP Composer—— 初始化源码分析
https://www.bookstack.cn/read/laravel-source-analysis/PHP%20Composer%E2%80%94%E2%80%94%20%E5%88%9D%E5%A7%8B%E5%8C%96%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90.md
https://zhuanlan.zhihu.com/p/30785203
https://learnku.com/docs/the-laravel-way/5.6/Tao-3-1/2928