Laravel custom package helper autoload - php

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.

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 package not autoloading - Laravel 5.2

I'm building a laravel package, but it won't autoload.
This is the autoload section of my package:
"autoload": {
"classmap": [
"src"
],
"psr-4": {
"Doitonlinemedia\\Translatableroutes\\": "src/"
}
}
Classes are namespaced like Doitonlinemedia\Translatableroutes
Folder structure is like:
- vendor
- - doitonlinemedia
- - - translatableroutes
- - - - composer.json
- - - - src
- - - - - class1.php
I've added the ServiceProvider in app.php like:
Doitonlinemedia\Translatableroutes\TranslatableRoutesServiceProvider::class
But it keeps saying Class 'Doitonlinemedia\Translatableroutes\TranslatableRoutesServiceProvider' not found
Run composer dump-autoload on every change.
What am I doing wrong?
EDIT
For development I added: "Doitonlinemedia\\Translatableroutes\\": "packages/doitonlinemedia/translatableroutes/src" to the main composer.json file. But when I require this composer package into a new project I'm getting the above problems.
To try out this package: https://github.com/doitonlinemedia/TranslatableRoutes and follow the instructions
PHP namespaces are case sensitive.
You have to put this into your composer.json
"psr-4": {
"Doitonlinemedia\\Translatableroutes\\": "src/"
}
instead of this
"psr-4": {
"doitonlinemedia\\translatableroutes\\": "src/"
}
For me it works also without the classmap option
run composer dump-autoload again and retry.
Edit
This works for me
{
"name": "doitonlinemedia/translatableroutes",
"description": "Create translatable resource routes",
"authors": [
{
"name": "Tim van Uum",
"email": "tim#doitonlinemedia.nl"
}
],
"minimum-stability": "stable",
"license": "MIT",
"require": {
"php": ">=5.3.0"
},
"autoload": {
"classmap": [
"src"
],
"psr-4": {
"Doitonlinemedia\\Translatableroutes\\": "src/"
}
}
}
In addition you should add this package to your requirements "illuminate/support": "~5.2".
Note: It seems to composer do not refresh the autoload entries of composer.json files located in vendor packages if they are not updated.
After editing you have to push this into your repository. Reinstall the package in your project.
If you are still developing actively on your package I recommend to setup an environment by following this instructions: Developing your packages in Laravel 5.
It's so much easier to develop your package without reinstalling or updating the remote repository always.
Thanks to some help on laracast forum. I found out that my project was bit corrupt I guess, cause the package was already working.
https://laracasts.com/discuss/channels/laravel/trouble-autoloading-custom-package-laravel-52

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.

Composer Not Generating Autoloads For Library

I've set up two projects, an 'init' and a library, which is required by the init. They both have PSR-0 autoloads set, but the autoload values from the library are not added to the vendor/composer/autoload_namespaces.php in the init project.
Sample composer.json from the Library:
{
"name": "lxp/library",
"description": "A test library",
"autoload": {
"psr-0": {
"LXP\\Library": "src/"
}
}
}
Sample composer.json from the project that requires that library:
{
"name": "lxp/init",
"name": "A test init",
"autoload": {
"psr-0": {
"LXP\\Init": "src/"
}
},
"repositories": [
{
"type": "composer",
"url": "http://satis.repo.redacted/"
}
],
"require": {
"lxp/library": "dev-master"
}
}
The library contains the class LXP\Library\Something in the file src/LXP/Library/Something.php.
The project that requires the library contains the class LXP\Init\Now in the file src/LXP/Init/Now.php.
When running composer install in the 'init' project, it downloads the library project and puts it in vendor correctly, but vendor/composer/autoload_namespaces.php doesn't contain the library's autoload information, only that of the current project.
What am I doing wrong? If I run dump-autoload in the library project then the autoload_namespaces.php file is correct, and a quick bootstrap script confirms that it does indeed pick up the class.
EDIT - This is a problem with the satis-generated packages.json. To fix it, I had to add the autoload information from the library's composer.json into the json file I supply to satis, which seems like an unnecessary duplication and so I'm probably doing it wrong. Is there a single place that autoload information can be stored for satis libraries? For example, can satis read the composer.json files that exist in the libraries it scans?
EDIT #2 - Satis does not read the composer.jsons from repositories specified as 'package' type. This is obvious in hindsight, because 'package' is used for libraries that do not have a composer.json, and is a way to wrap composer-like dependency management around them.
Changing the satis.json's repository to 'vcs' type meant that the composer.json was read, and the information (including the autoload specification) was parsed and stored in the packages.json.
#Seldaek - thank you for suggesting that my satis config was the problem, and I hope that this clarifies satis / composer behaviour for anyone else in my position.
I see two possible mistakes you may have done that would cause this:
You forgot to update your satis repo so the autoload config for lxp/init is not up to date in there
You are running composer install from a lock file, and that means composer just reads the info from the composer.lock file and does not update package metadata to the latest version available in satis. To solve this you should run composer update instead.
Try composer dump-autoload command.
It depends how you installing your library via Composer. For example, when downloading it as package type (same I believe with composer type), Composer never reads the composer.json file, so instead you should use vcs or git type. See: GH-6846.
Here is composer.json which should work:
{
"require": {
"lxp/library": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "http://satis.repo.redacted/"
}
]
}
Then run: composer install.
For troubleshooting, try running:
composer dump-autoload -o -vvv.
composer diagnose -vvv

Categories