Workflow for developing Laravel Packages - php

I'm developing my first Laravel Package, and I realize that my workflow contains much more steps for publishing each modification.
Here is my workflow:
I create a Fresh Laravel 5.4 install. Inside, I create a package/author/name/src where I code my plugin.
I run my tests
Once I have made my change and want to publish it:
a.I push it to my Git rep
b.I tag it with version number
c.In my main project, I run composer update
I check that nothing broke with the integration
This is quite a lot of changes for each little change I want to see in my main project....
Is there a way not to publish any single change, just doing local?

Yes, you can locally develop a package and use it without publishing it. The workflow is: create a packages directory outside of your Laravel project then create the package directory in it, for example the directory structure should look something like this:
- my-laravel-project
- packages
- - my-package-1
- - - composer.json
- - my-package-2
- - - composer.json
Then, in your Laravel project's composer.json file, add the repositories section like given below and add an entry into the require section for each local package, for example:
{
"repositories": [
{
"type": "path",
"url": "../packages/my-package-1"
},
{
"type": "path",
"url": "../packages/my-package-2"
}
],
"require": {
"my/package-1": "*",
"my/package-2": "*"
}
}
In this example, I've two different packages inside packages directory and I've added both packages in the Laravel project. The repositories section describes the package type and path/url for each package so composer can find them locally and require section is simply requiring the dependencies as usual. You may check more on Composer's website.

Related

How do I activate a Laravel package via dowloaded files (not via Composer)

I have a Laravel package I would like to use in my project. I have tested it already and I know I'd need to customize quite a lot of it to fit my needs.
Overriding files in the vendor directory is always quite a chore, especially if you need to touch PHP, Vue, CSS files, etc. Hence, I don't want to go via the usual Composer installation. I also don't care much about future updates to the package, as it already has a solid base.
So the question is: After I download the package files from GitHub and after I place them in their respective directories in my Laravel app - is there a specific list of steps to take in order to make sure the inserted package works? Or is it more like, do it and fix issues one by one until it works?
Cheers.
Composer allows you to choose the local package instead of the remote one.
Create a packages folder in the base directory (the packages folder and Laravel's composer.json file must be in the same directory).
Put your downloaded package into packages (packages/packageName).
Replace the following line in your Laravel's composer.json.
"require": {
by
"repositories": [
{
"type" : "path",
"url" : "./packages/*",
"options" : {
"symLink" : true
}
}
],
"require": {
Run composer require authorName/packageName command in the console.

How to handle multiple composer auto loaders while developing multiple packages

I'm developing an app that will consist of multiple Composer packages.
First I have the "main" app (it will be a "project" in Composer) that will contain all the necessary files and folders:
app/
public/
index.php
logs/
config.php
..etc..
This is not an issue. I just set the type as "project" in the composer file so it can be install with composer create-project foo/bar.
I will also build a few optional extensions for the main app. They will be their own Composer packages. This isn't either an issue. I just make them into type "library" and install them with composer install foo/the-extension.
The issue
The extensions will have their own namespaces and some of them will have their own dependencies. A couple of them will even have the same dependencies.
This is needed since all of them will are optional. You can install one or the other or all.
Currently, I've created a new folder called "/dev" in the main app where I have all my extensions while developing. Then, in the main app, I'm loading all the extensions auto loaders:
# Main apps autoloader
require_once __DIR__ . '/vendor/autoload.php';
# Extensions
require_once __DIR__ . '/dev/foo/vendor/autoload.php';
require_once __DIR__ . '/dev/bar/vendor/autoload.php';
...etc...
This works, but it comes with a few drawbacks:
I need to change the code in the main app every time I'm going to make a commit to the main apps repo. This is a hassle and it's easy to miss something
Potential versioning clashes. If two packages depends on the same package that gets a new update. If I miss to update both, there might be a version clash. (This have happened)
It's never good to have more than one auto loader since that can mess things up royally.
So, does anyone know of a proper way of handling this, or is it one of those "well, if it works for you, do it like that"-type of situations?
Been searching for a good solution for this a while now but haven't found any. If I missed some answer here on SO, please mark it as a duplicate and I'll remove this post.
Edit
As #sammitch points out in the answer below, I could add the extensions using Composers "repositories" key. This would remove the multiple auto loader problem. However, that will make the development flow pretty awkward:
You make a change to an extension
You commit and push that change to a git repo
You do a composer update in the main app (to get the new commit)
Now you can test if your changes work
I rather not need to go through all that every single time I make a change the extensions code just to see if the change worked or not.
Whoa whoa whoa, you should only ever have one composer autoloader, and it's a bad idea to just cram in external dependencies like that as it will complicate your dev and/or deployment pipelines later.
What you want to do is have the main project include the subpackages as actual packages. You can do this either by:
1. Pushing them to a git host
https://getcomposer.org/doc/05-repositories.md#loading-a-package-from-a-vcs-repository
{
"repositories": [{
"type": "vcs",
"url": "https://github.com/youruser/yourrepo"}],
"require": {
"youruser/yourpackage": "^1.0.0"
}
}
2. Specifying a local repo
Composer require local package
{
"repositories": [{
"type": "vcs",
"url": "/home/youruser/src/yourrepo"
}],
"require": {
"youruser/yourpackage": "^1.0.0"
}
}
Now you can simply run composer install or composer update youruser/yourpackage and composer will pull in all the necessaries and build the relevant autoloader.
Note: Repository specifications are only effective in the root composer.json, so if your dependencies have specific repo config you'll need to either put that config into the root composer.json, or into your global composer config.

Local "path" repository doesn't see vcs version information

I'm currently trying to setup a better local development without putting information about my local structure into a project itself or into the composer.json of this project.
I found out, that there is a new way to do this by using a config.json and adding a "repositories" section to it, that points to my local projects I depend on.
My setup
So I setup two projects with a few versions (on Win10 with IIS 10 with PHP 7.0), lets call them php-project1 and php-project2. php-project1 depends on php-project2 and I want to develop both of them at the same time. Changes I make in php-project2 should therefore directly influence the first project. In addition they are git repositories and they contain tags as composer versions. They are also on packagist, but of course I want to use the local version for development.
Their composer.json look like this (2 files):
{
"name": "test/php-project1",
"description": "Some text here",
"type": "library",
"require": {
"test/php-project2": "^0.3",
}
}
{
"name": "test/php-project2",
"description": "Some other text here",
"type": "library"
}
Please note that there is no "version" entry, because I want to use this from the git tags.
Now I tried to setup a global config.json like this:
{
"repositories": [
{
"type": "path",
"url": "/somePath/php-*"
}
]
}
I'm using php-* here because I want to use it later for all my repositories/projects with this pattern.
So what's the problem now?
When running composer update on the first project it doesn't use the local version of php-project2, but instead downloads it from packagist. This only works when I add a "version" entry to the composer.json, but I don't want this!
I also tried "type": "vcs", but this creates a clone and I need a symlink, to have changes directly in other projects too.
The documentation says:
If the package is a local VCS repository, the version may be inferred by the branch or tag that is currently checked out. Otherwise, the version should be explicitly defined in the package's composer.json file.
Currently php-project2 is on tag 0.3.0 without any changes.
So what do I do wrong?
Found my mistake with help of alcohol (this sounds wrong though^^).
When you use this and need a symlink, be sure to add a "version" entry to your composer.json or (in my case) checkout the tag (not the branch!), so composer may see, that your used version matches the required.

Satis Private Repository - satis.json structure

EDIT
I think I misunderstood satis, now this is my new understanding, please correct me if I am wrong:
In satis.json, I must specify the url s of the packages I want to mirror, e.g the doctrine git repo, yaml git repo... Then satis mirrors all these packages on my server. This would mean I need to add once all packages used within my composer.json of my project to the satis json (around 20 packages/requirements ). Now, I can add my private satis repository to the composer.json file of my project and when running "composer update", it will first look within the satis mirrored packages for the required package. Did I understand that correctly?
Situation:
I am trying to use Satis for private composer repository. I have a private project on github for a website of mine. On the project, I am using composer and therefore I have a composer.json on the root of the project. It looks the following:
{
"name": "Peter North",
"license": "proprietary",
"type": "project",
"autoload": {
"psr-4": {
"": "src/"
}
},
"require": {
"php": ">=5.3.9",
"symfony/http-foundation": "dev-master"
}
...
}
Now I wanted to use my private satis repository of url: packages.ait.company, running on an apache and accessible so far. The satis.json looks the following:
{
"name": "AIT Company",
"homepage": "packages.ait.com",
"repositories": [
{
"type": "vcs",
"url": "git#github.com:north/ait.git" // this is the url of my private github project
}
],
"require-all": true,
"require-dependencies": true,
"archive": {
"directory": "dist",
"format": "tar",
"skip-dev": true
}
}
I think that I did not understand well how to structure the satis.json file and what it needs to contain, because the way I am trying, it does not download the "php" and "symfony/http-foundation" packages that I specified in the composer.json file - though it does download the correct composer.json file of the project into /satis/include directory json file.
How does the satis.json need to look like, when I want to read the composer.json of my project from github and build the private satis repository of the "require entries" ?
In my Satis update script, it is a two step process to create local copies from both external packages as well as internal, private repositories.
The first step only downloads the meta data of external dependencies and puts them into an intermediate satis repository. The configuration explicitly does not "require-all", but has explicit statements of all packages that are being used (and some that may be used, or had been used in the past) with an open-ended version wildcard, i.e. "symfony/console":">=2.4" (no tilde or caret - I want to get major version updates here). Adding require-dependencies:true scans all the dependencies of all the required packages and adds them to the meta data collection as well.
The result is stored in a directory "external".
The second step is responsible for scanning all packages from internal "repositories", and creating archives from them. This obviously is a list of all private repos, but the trick is: You can also add to the satis.json a repository of type "composer" - and this is where I add the external repository with the meta data from external packages. Adding it here adds all the external packages' versions to the list of versions that need to have ZIP files created.
Running it for the first time takes a long time because of all the packages that need to be downloaded (and created locally from the private repos). Running it after that is simply an incremental update of only the new versions that haven't been created previously.
The key is to configure collecting external packages without ZIPs and with explicit version ranges ("*" as version would work, but only use it if you really need all versions) in one Satis file, then add the resulting repository to the second Satis configuration. You cannot combine the two operations (only creating ZIPs of selected external dependencies together with ZIPs of ALL internal repositories) into one Satis run.
One more tip: You probably only want to create local copies of your external dependencies to avoid hitting a Github outage when you are deploying to production (or are developing and need that update). In order to ensure every used dependency is in my Satis, I added both the Satis repository to every composer.json, as well as "packagist":false, to turn off any direct contact to Packagist. You cannot just add a random package then, it has to be in your local Satis repository first.

Is there a way to retain certain files during a composer update or install?

I'm using a package in my Laravel application that doesn't have support for Laravel out of the box, so I added a Facade and Service Provider to it myself. Both of those files are checked into my repo (specified in .gitignore using the ! prefix). However, when composer updates a package it completely removes it first, and this is preventing automatic deployment with platforms like Codeship.
Any suggestions?
You should fork the package, create a custom repo with your changes - then include that in your composer.json.
{
"repositories": [ {
"type": "vcs",
"url": "https://github.com/YourGithubUsername/PackageName"
}
}],
"require": {
"laravel/framework": "4.0.*",
"OriginalVendor/PackageName": "1.0.*"
},
}
That way you can pull your custom changes in anytime, without having to commit it to your specific project.
You can read more about forking and loading packages here: https://getcomposer.org/doc/05-repositories.md#vcs
Never change the code of packages! In fact, never touch the vendor directory.
You should either [fork] the repository and add your code (see #TheShiftExchange's answer)
Or add the Facade and the ServiceProvider in your namespace.

Categories