PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Friday, January 7, 2022

[FIXED] How do I make Composer automatically install all dependencies of a package from my local repository?

 January 07, 2022     composer-php, dependency-management, php     No comments   

Issue

I'm using Composer 1.6.3 on Ubuntu and have the following global ~/.config/composer/config.json file:

{
    "config": {},
    "repositories": {
        "packagist": false,
        "codifier": {
          "type": "composer",
          "url": "file:///usr/local/codifier/library/PHP/Codifier"
        }
    }
}

In other words, I disable Packagist and point to my own repository on my local machine. This local repository has a packages.json defining all available local packages:

{
  "packages": {
    "codifier/cache": {
      "dev-master": {
        "name": "codifier/cache",
        "version": "dev-master",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Cache",
          "type": "git",
          "reference": "master"
        }
      },
      "1.0.0": {
        "name": "codifier/cache",
        "version": "1.0.0",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Cache",
          "type": "git",
          "reference": "v1.0.0"
        }
      }
    },
    "codifier/environment": {
      "dev-master": {
        "name": "codifier/environment",
        "version": "dev-master",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Environment",
          "type": "git",
          "reference": "master"
        }
      },
      "1.0.0": {
        "name": "codifier/environment",
        "version": "1.0.0",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Environment",
          "type": "git",
          "reference": "v1.0.0"
        }
      }
    },
    "codifier/event": {
      "dev-master": {
        "name": "codifier/event",
        "version": "dev-master",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Event",
          "type": "git",
          "reference": "master"
        }
      },
      "1.0.0": {
        "name": "codifier/event",
        "version": "1.0.0",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Event",
          "type": "git",
          "reference": "v1.0.0"
        }
      }
    },
    "codifier/mime": {
      "dev-master": {
        "name": "codifier/mime",
        "version": "dev-master",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Mime",
          "type": "git",
          "reference": "master"
        }
      },
      "1.0.0": {
        "name": "codifier/mime",
        "version": "1.0.0",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Mime",
          "type": "git",
          "reference": "v1.0.0"
        }
      }
    },
    "codifier/net": {
      "dev-master": {
        "name": "codifier/net",
        "version": "dev-master",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Net",
          "type": "git",
          "reference": "master"
        }
      },
      "1.0.0": {
        "name": "codifier/net",
        "version": "1.0.0",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Net",
          "type": "git",
          "reference": "v1.0.0"
        }
      }
    },
    "codifier/number": {
      "dev-master": {
        "name": "codifier/number",
        "version": "dev-master",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Number",
          "type": "git",
          "reference": "master"
        }
      },
      "1.0.0": {
        "name": "codifier/number",
        "version": "1.0.0",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Number",
          "type": "git",
          "reference": "v1.0.0"
        }
      }
    },
    "codifier/persistence": {
      "dev-master": {
        "name": "codifier/persistence",
        "version": "dev-master",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Persistence",
          "type": "git",
          "reference": "master"
        }
      },
      "0.1.0": {
        "name": "codifier/persistence",
        "version": "0.1.0",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Persistence",
          "type": "git",
          "reference": "v0.1.0"
        }
      }
    },
    "codifier/process": {
      "dev-master": {
        "name": "codifier/process",
        "version": "dev-master",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Process",
          "type": "git",
          "reference": "master"
        }
      },
      "1.0.0": {
        "name": "codifier/process",
        "version": "1.0.0",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Process",
          "type": "git",
          "reference": "v1.0.0"
        }
      }
    },
    "codifier/socket": {
      "dev-master": {
        "name": "codifier/socket",
        "version": "dev-master",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Socket",
          "type": "git",
          "reference": "master"
        }
      },
      "1.0.0": {
        "name": "codifier/socket",
        "version": "1.0.0",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Socket",
          "type": "git",
          "reference": "v1.0.0"
        }
      }
    },
    "codifier/stdlib": {
      "dev-master": {
        "name": "codifier/stdlib",
        "version": "dev-master",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/StdLib",
          "type": "git",
          "reference": "master"
        }
      },
      "0.1.0": {
        "name": "codifier/stdlib",
        "version": "0.1.0",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/StdLib",
          "type": "git",
          "reference": "v0.1.0"
        }
      }
    },
    "codifier/text": {
      "dev-master": {
        "name": "codifier/text",
        "version": "dev-master",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Text",
          "type": "git",
          "reference": "master"
        }
      },
      "1.0.0": {
        "name": "codifier/text",
        "version": "1.0.0",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Text",
          "type": "git",
          "reference": "v1.0.0"
        }
      }
    }
  }
}

This part works as expected, so far. When I do $ composer show -a in a random folder, I get this output:

No composer.json found in the current directory, showing available packages from codifier
codifier/cache      
codifier/environment
codifier/event      
codifier/mime       
codifier/net        
codifier/number     
codifier/persistence
codifier/process    
codifier/socket     
codifier/stdlib     
codifier/text

All these packages define their own dependencies. For instance, the codifier/socket package has the following composer.json file in its root directory:

{
  "name": "codifier/socket",
  "authors": [ ##REDACTED## ],
  "require": {
    "php": ">=7.3.0",
    "codifier/event": "^1.0",
    "codifier/net": "^1.0",
    "codifier/process": "^1.0"
  },
  "autoload": {
    "psr-4": {
      "Codifier\\Socket\\": "src"
    }
  }
}

Now, I thought the whole point of Composer was that it would automatically and recursively install all required dependencies, instead of me having to manually require all dependencies again, but that does not appear to be the case.

When I create a new clean application directory $ mkdir Test && cd Test and then do $ composer require codifier/socket, I get this output:

Using version ^1.0 for codifier/socket
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing codifier/socket (1.0.0): Cloning v1.0.0 from cache
Writing lock file
Generating autoload files

...and then when I do $ composer install, I get this output:

Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Nothing to install or update
Generating autoload files

In other words, only codifier/socket is installed but not its dependencies. As such, the contents of Test/vendor is now:

- codifier/
  - socket/

...when I expected the contents to be:

- codifier/
  - socket/
  - event/
  - net/
  - process/
  etc.

...because I expected Composer to fetch all required dependencies recursively.

I tried $ composer clear-cache as well, but that doesn't make a difference and I think I've also seen some posts suggesting I need to define "repositories" inside composer.json for this application, but that just doesn't make any sense to me, as I've already pointed to those in my global config.json file.

What am I missing here? Have I missed the point of Composer, in that I thought it would automatically resolve and install all required dependencies automatically?

--- Update ---

I've now also tried serving the packages through my local web server (and changed all "url" fields in the json files accordingly, of course), as I thought perhaps Composer wasn't able to handle the file:// protocol properly, but to no avail: it gives the exact same result: it only installs codifier/socket and just ignores its dependencies.

I don't know what else I have to do to make this local packages.json repository work.


Solution

I just had an epiphany and finally figured out how to get it to work, but it feels very redundant. The way I got it to work is by simply copying the "require" information from the packages' composer.json files into my repository's packages.json file.

Taking the composer.json file from the codifier/socket package as an example again:

{
  "name": "codifier/socket",
  "authors": [ ##REDACTED## ],
  "require": {
    "php": ">=7.3.0",
    "codifier/event": "^1.0",
    "codifier/net": "^1.0",
    "codifier/process": "^1.0"
  },
  "autoload": {
    "psr-4": {
      "Codifier\\Socket\\": "src"
    }
  }
}

...the relevant info for it, in packages.json, would then become:

{
  "packages": {

    ...

    "codifier/socket": {
      "dev-master": {
        "name": "codifier/socket",
        "version": "dev-master",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Socket",
          "type": "git",
          "reference": "master"
        },
        "require": {
          "php": ">=7.3.0",
          "codifier/event": "^1.0",
          "codifier/net": "^1.0",
          "codifier/process": "^1.0"
        }
      },
      "1.0.0": {
        "name": "codifier/socket",
        "version": "1.0.0",
        "source": {
          "url": "file:///usr/local/codifier/library/PHP/Codifier/Socket",
          "type": "git",
          "reference": "v1.0.0"
        },
        "require": {
          "php": ">=7.3.0",
          "codifier/event": "^1.0",
          "codifier/net": "^1.0",
          "codifier/process": "^1.0"
        }
      }
    },
    
    ...

  }
}

When I apply this for all packages, everything works smoothly.

What I still don't understand, though, is why Composer is not picking up this "require" info from the actual composer.json of the package itself. I know the documentation states Composer doesn't recursively follow repositories, but surely it must recursively follow dependencies, no? Maybe it simply doesn't, though, and this is simply how it is intended to work.

This all means I'll have to do more git parsing to get the correct data for each individual version of a package, but so be it.1)

This solution will possibly also lead me to the solution for the autoload problem I had, in which the "autoload" namespaces defined in composer.json weren't picked up on either. I will try that out next and amend this answer if that solves it as well.

--- Update ---

As anticipated: when I incorporated the "autoload" info into packages.json as well, autoloading started working too.


1) I already know about Satis, but I don't want to have to install and learn yet another piece of software.



Answered By - Codifier
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing