Composer => Wordpress plugin workflow - php

The question first so you know, while reading, what my problem is: What is the correct workflow for updating a plugin within in composer/wordpress project all managed with git?
I've a wordpress project with the following directory structure:
root
httpdocs
wp-content
plugins
wp-config.php
...
composer.json
and inside the plugins folder:
myplugin
composer.json
The stripped root composer.json looks like this:
{
[...]
"require": {
"example/myplugin": "dev-master"
},
"repositories": [
{
"type": "composer",
"url": "http://composer.example.com"
}
],
"extra": {
"installer-paths": {
"httpdocs/wp-content/plugins/{$name}": [
"example/myplugin"
]
}
}
}
And the composer.json inside the the myplugin folder:
{
[...]
"license": "proprietary",
"require": {
[...]
},
"type": "wordpress-plugin",
"autoload": {
"classmap": [
"controllers",
"lib",
"models"
]
}
}
At example.com I installed a private static composer repository (satis). So far so good, I can install all dependencies, myplugin and the myplugin dependencies with php composer.phar install in the root folder.
Now the (my) problems begin:
Updating: myplugin is a composer package, not a git submodule. How can I update the package while developing and testing? With a git submodule I could simply commit and push the changes, but with the composer package I have to keep the git repository for myplugin somwhere else and update from there, correct?
Autoloading: I moved the autoload parameter from the root composer.json into the myplugin composer.json. But now the autoloader wont work correct. I can reinstall the composer dependencies without problems, and replaced the path (before: httpdocs/.../myplugin/controllers, now: controllers)
I was searching for about 6 hours but there are no information about this (or I searched for the wrong keywords)

This only answers part of your question, but if you add the git url to your root project's composer.json as a git repository, Composer will do a clone into the plugin directory. That will allow you to commit back directly.
Example:
"repositories": [
{
"type": "git",
"url": "git#github.com:my-git-name/my-plugin.git"
},
...
]

Related

Use a non-namespace composer package in a custom Laravel package [duplicate]

I am a Composer beginner and I am trying to make one project dependent of another one, while both project only exist on my local machine.
The composer.json in my library project (ProjectA) is:
{
"name" : "project/util",
"type" : "library"
}
I initialized git in the base folder of this project.
My composer.json in the project depending on the first one (ProjectB):
{
"repositories": [
{
"name" : "util",
"type" : "git",
"url" : "/d/workspaces/util"
}
],
"require": {
"project/util" : "*"
},
}
When I run composer install from ProjectB, I get the following error:
[RuntimeException]
Failed to clone , could not read packages from it
fatal: repository '' does not exist
I asume something is wrong with the url of the repository, but I am not sure what else to write there.
Autoload local package using composer (without going to packagist every time you change).
There are many ways to do so, I will be covering 2 of them:
In all cases we have 2 main parties:
- the local package (the code that we do not want to publish on packagist to be able to autoload it in our project composer).
- the main project (the code base that needs to use the local package code, can be another package and or any project).
Method 1: (direct namespace)
Open the main project composer.json file and autoload the local package namespaces using any method (PSR-4, PSR-0, ...).
example:
if in the composer.json of the local package we have:
"autoload": {
"psr-4": {
“Local\\Pack\\": "library"
}
},
"autoload-dev": {
"psr-4": {
"Local\\Pack\\Tests\\": "tests"
}
},
then in the composer.json of the main project we should have:
"autoload": {
"psr-4": {
"Mahmoudz\\Project\\": "src",
"Local\\Pack\\": "../path/to/local/pack/library” << referencing the other local package
}
},
"autoload-dev": {
"psr-4": {
"Mahmoudz\\Project\\Tests\\": "tests"
}
},
Advantages:
- you don’t touche the vendor directory (running composer update by mistake will not override your local changes)
- you don’t need your package to be on packagist to use it
- you work in one place (the local package) and the changes are automatically loaded in the main project
Disadvantages:
- you cannot publish the composer.json on production (needs editing before publishing to require the real package)
Method 2: (local repository)
Download the local package from a local repository.
local package:
1. initialize git in the package (even if you don’t want to use it - no need to commit anything)
2. add composer.json file. In the file make sure you have the following:
"name": "vendor-name/package-name",
"autoload": { … // use whichever method you prefer, but make sure it’s being loaded correctly
"minimum-stability": "dev"
composer dump-autoload
main project:
1. edit your composer.json to contain the following:
"repositories": [
{
"type": "vcs",
"url": "/full/path/to/the/local/package/package-name"
}
],
"require": {
"vendor-name/package-name": "dev-master"
},
composer update vendor-name/package-name
now check your vendor directory you should see the vendor-name/package- name
NOTE: whenever you make change in the local package (not the vendor) you need to git commit then you can composer update the main project, it will get the latest copy of the repo to the main project vendor directory.
Advantage:
- you don’t touch the vendor directory (running composer update by mistake will not override your local changes) - you don’t need your package to be on packagist to use it
Disadvantage:
- you have to keep committing your changes (in the local package) and then running composer update in the main project
- you cannot publish the composer.json on production (needs editing before publishing to require the real package)
I think you've just got the syntax wrong. The type should just be VCS, and then composer figures out what type of VCS it is.
So in your project B, the entry for repositories should be:
"repositories": [
{
"type": "vcs",
"url" : "/d/workspaces/util"
}
],
You don't need to name what library is available in /d/workspaces/util. Composer will scan the composer.json file in that directory and know what project name is available there, and use the project from that directory in preference to a version listed on packagist or other repository.
The easiest way is to use type=path https://getcomposer.org/doc/05-repositories.md#path
{
"repositories": [
{
"type" : "path",
"url" : "/d/workspaces/util"
}
],
"require": {
"project/util" : "*"
},
}
I found this tutorial really useful: https://johannespichler.com/developing-composer-packages-locally/ when I was facing issues with local package production
Note the symlink condition allowing the vendor folder to be a symlink which then means you no longer need to composer update each time you want to see change
"options": {
"symlink": true
}
In addition to Danack's solution: Changing the path from /d/ to d:/ worked for me.
Like this:
"repositories": [
{
"type": "vcs",
"url" : "d:/workspaces/util"
}
],
NOTE: This answer assumes that you have something like a Package Registry or GIT repository where you
can retrieve the releases of your package. If you do not yet have this. https://getcomposer.org/doc/05-repositories.md
Composer enables us to autoload a local development package without contaminating the composer.lock file.
When Composer finds a conflict between two or more packages it wil autoload only one of these packages.
You can use the autoload-dev to autoload a specific folder for development. (https://getcomposer.org/doc/04-schema.md#autoload-dev)
The autoload-dev (and autoload) settings do not touch the composer.lock file
In your projects composer.json file:
"repositories": {
"99999999": {
"type": "composer",
"url": "https://gitlab.com/api/v4/group/99999999/-/packages/composer/packages.json"
}
}
"require": {
"a-vendor-name/test-package": "1.0.*"
},
"autoload-dev": {
"classmap": [
"./../../packages/a-vendor-name/test-package"
],
"exclude-from-classmap": [
"vendor/a-vendor-name/test-package"
]
}
In this example the packages directory lives outside the project root and contains its own package GIT repositories.
autoload-dev because we only want this folder to load when we are developing. (https://getcomposer.org/doc/04-schema.md#autoload-dev)
classmap to load the packages from a local directory. (https://getcomposer.org/doc/04-schema.md#classmap)
exclude-from-classmap to disable loading the package within the vendor directory.
Will also suppress the warning about multiple classes with the same namespace. (https://getcomposer.org/doc/04-schema.md#exclude-files-from-classmaps)
Running DEVELOPMENT (default behaviour):
composer update a-vendor-name/test-package // or any other composer command
Your package will still be downloaded from your Package Registry. This downloaded package is not only ignored in you applications code, its also possible to update it according to the project composer.json file. Which in turn will update the composer.lock file, the right way.
Running DTAP / PRODUCTION by using the --no-dev flag:
composer update a-vendor-name/test-package --no-dev // or any other composer command
In addition to #Glen Solsberry's solutions, if you're running in a docker container like me, you can add a volume to your docker-compose.yml file like:
services:
theservicename:
...
volumes:
- ../:/var/www
- /path/to/src/package:/var/www/vendor/path/to/src/package
...
When you make changes locally they will reflect in the container.

Laravel custom class not found?

I'm getting the following error
"Class 'Martins\ArtisanGUI\ArtisanGUIServiceProvider' not found",
I already write it in config/app.php like Martins\ArtisanGUI\ArtisanGUIServiceProvider::class and recheck namespaces, and composer but I can't figure out what is wrong.
You're editing the composer file of your package, not your project.
As the package does not appear to be installed and managed by composer, you need to make the project's composer aware of this package.
You should be able to add a local vcs repository in your project's composer.json file:
"repositories": [
{
"type": "vcs",
"url": "packages/martins-74/artisangui"
}
],
"require": {
"martins-74/artisangui": "*"
}
This will make it so you won't have to duplicate any composer rules across both json files.
you have two composer.json files in you projects :
the root of you Laravel project
in your package root (packages/martins-74/artisangui)
in the first composer.json file (the laravel composer.json):
"psr-4": {
"App\\": "app/",
"Martines\\ArtisanGUI\\" : "packages/martins-74/artisangui/src"
}
the seconds composer.json file (your package composer.json):
"psr-4": {
"Martines\\ArtisanGUI\\": "src",
}
after that run composer dump-autoload
hope this work for you

Laravel custom package helper autoload

I'm developing a custom laravel package for my needs, and discovered strange issue. My package is supposed to use custom helper function called t().
function t($string, array $options = [])
{
// Function code goes here
}
It is located in my package folder, right near the package service provider.
The service provider itself loads successfully, but helper file is not. I added following lines "autoload" section of the package's composer.json, just as I saw in other package:
"files": [
"src/helpers.php"
]
then I dumped autoload. Everything works fine but this t() function. It's not found. What am I doing wrong?
P.S.: sure, I can include it in package service provider using require_once, but what is composer for either way?)
UPDATE
package composer.json:
{
"name": "astatroth/laravel-i18n",
"require": {
"astatroth/laravel-config": "^1.0"
},
"license": "MIT",
"authors": [
{
"name": ".......",
"email": "........"
},
{
"name": ".......",
"email": "........"
}
],
"autoload": {
"psr-4": {
"Astatroth\\LaravelI18n\\": "src/"
},
"files": [
"src/helpers.php"
]
},
"minimum-stability": "dev"
}
Package file structure:
laravel-i18n
config
src
I18nServiceProvider.php
helpers.php
composer.json
My package
Packages or libraries by design does not support Composer configuration files, in other words composer.json file from your package folder is never read.
To workaround this problem, use vcs type instead of package when requiring the sources.
Related:
Why using PSR4 autoload doesn't add any classes into classmap/namespaces file?
Using autoload in package doesn't generate classmap at GitHub
Please run composer update if you use repositories symlink for adding your package to laravel project. I had a same issue, running composer dump-autload doesn't work, because your vendor folder not updated with your new file.
Hope this can solve your issue.

My composer package's namespace doesn't show in the autoload_psr4 file

I'm creating my first composer package. I'm testing it by pulling it into a vanilla Laravel project.
The issue I'm having is that when I require my composer package in the main Laravel composer.json file and then try to update the autoload.
My package's composer.json:
{
"name": "cschmitz/l5-simplefm",
"description": "A Laravel 5 wrapper for Soliant Consulting's SimpleFM package.",
"require": {
"soliantconsulting/simplefm": "3.0.*"
},
"license": "MIT",
"authors": [
{
"name": "cschmitz",
"email": "schmitz.chris#gmail.com"
}
],
"minimum-stability": "dev",
"autoload": {
"psr-4": {
"L5SimpleFM\\": "src/"
}
}
}
My package's folder structure in the Laravel project's vendor folder:
My Laravel project's composer.json:
{
"name": "laravel/laravel",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"license": "MIT",
"type": "project",
"require": {
"php": ">=5.5.9",
"laravel/framework": "5.1.*",
"cschmitz/l5-simplefm": "dev" // Requiring my package here
},
...
After this, I performed a composer dump-autoload. I don't get any errors from composer, but when I check my vendor/composer/autoload_psr4.php file, my namespace isn't listed in the array:
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
...
'App\\' => array($baseDir . '/app'),
// I expected to see `'L5SimpleFM\\' => array($vendorDir . '/cschmitz/L5SimpleFM/src')` as the last key of this array, but nothing shows past the App key
);
I looked around online and on stackoverflow, but the various answers and suggestions I found didn't resolve the issue.
Can anyone see what I'm missing?
Update
Per Alexandru Guzinschi's answer, I tried telling my Laravel project that there was a local composer repository to inspect by adding the following block into my Laravel project's composer.json file:
"repositories":[
{
"type": "vcs",
"url": "../cschmitz/L5SimpleFM"
}
],
I then moved the package folder starting at the cschmitz directory out to the same level of my laravel project. The file structure looks like this now:
LaravelProjectFolder/
composer.json
cschmitz/
L5SimpleFM/
composer.json
Initially I ran into the error "No driver found to handle VCS repository vendor/cschmitz". After reading a bit I found that to be able to use this kind of local repository, the repo itself needs to be under version control (i.e. git, svn, etc). Makes sense. I hadn't put it under version control yet because this was just a test project used to try to develop the package.
I created a git repository at the root of my Laravel project and ran composer update. Now I'm getting the error:
[Composer\Repository\InvalidRepositoryException]
No valid composer.json was found in any branch or tag of ../cschmitz/L5SimpleFM, could not load a package from it.
This is confusing because I can ls ../cschmitz/L5SimpleFM/composer.json and see the file. I can also run git ls-tree -r master --name-only and see the composer.json file in the local repository version control:
Is there something that would prevent my Laravel project from seeing the local repository's composer.json file?
It is not enough to move your library inside vendor directory, because Composer doesn't scan that directory and doesn't know about your change.
You need to tell Composer about your package by publishing it to Packagist, or by loading it from local file system. In your Laravel project composer.json file, change:
"repositories": [
{
"type": "vcs",
"url": "/path/to/cschmitz"
}
],
"require": {
"cschmitz/l5-simplefm": "dev-develop"
}
Next you need to run composer update in order for your library to be installed.
Not related to your current issue, but it will became an issue soon:
After you will do this and you will continue working on your cschmitz/l5-simplefm library, you will notice that you need to commit your changes made to your library and then run composer update again in your Laravel project before you can use those changes. You have a few solutions here on how to circumvent this issue.

Modify files in /vendor directory and commit changes to composer.lock?

I had to modify a vendor package (avatarguru/mustache-l5), which was not compatible with the latest version of Laravel 5 (dev) framework. But now when I do composer status in the project's root directory, it shows No local changes. I also tried to modify some other packages - same thing...
How do I commit that changes to composer.lock, so that other developers will not have to fix same packages again?
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

Categories