Laravel vendor:publish directory permission issues - php

I'm building a package that needs to publish to these directories when php artisan vendor:publish is called.
Directories includes
public_path('vendor/package/assets')
resources_path('vendor/package/views')
resources_path('vendor/package/translations')
I get permission related error when I run vendor:publsih which tries to write to these directories.
However vendor:publish works for database_path('migrations').
Laravel requires permission 775 for storage and bootstrap/cache.
I don't want package users to be forced to give write permission to public and resources directories.
NB:My package already uses $this->loadViewsFrom, $this->loadTranslationsFrom and $this->loadMigrationsFrom as default options. I wish to give my package users full access to modify views, translations, migrations etc. My package also needs to publish some assets to public directory such as js, css etc, which are very necessary for some views.
What am I missing about artisan vendor:publish, and how do I get this to work?

In your package's service provider boot method, you should rely on the loadViewsFrom and loadTranslationsFrom methods to properly include views and translations files:
public function boot()
{
$this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
$this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');
}
More information about including views can be found here and translations here.
If you are looking to publish the files instead of just loading them for use, then use the publishes method:
public function boot()
{
$this->publishes([
__DIR__.'/path/to/assets' => public_path('vendor/courier'),
]);
}

Related

Is it possible to override a laravel package view from another package

Is it possible to override package view from another package?
When you register a view path via
loadViewsFrom('path/to/views', 'package')
it will also look in
/resources/views/vendor/package
So you can override a view when using a package,
but is there a way to override a view within a different package?
Yes it is.
Steps:
Publish the package views you want to override:
php artisan vendor:publish --provider="Another\Package" --tag=views
Modify the published ones.
Place the modifications in a dir in your package, e.g.:
/resources/vendor/another-package/views
Make it available for publishing. Add to your package's service provider boot():
public function boot()
{
$this->publishes([
__DIR__.'/resources/vendor/another-package/views' =>
base_path('resources/views/vendor/another-package')
], 'views');
}
Publish the modifications:
php artisan vendor:publish --provider="Your\Package" --tag=views --force
Note: change Another\Package and another-package as necessary. Works well in Laravel 7.

Fallback location for psr-0/4 autoloading

I'm building a PHP package and in it I have a folder (let's say /vendor/myvendor/packagename/src/Classes) which I want to autoload using PSR-4.
But I would also like to provide an option to copy that folder from its current location to the project root (let's say /packagename/Classes, something along the lines of Laravel's publish command).
So how could I go about autoloading it?
I would like Composer to first see if the folder exists under the app's root, and if it does then autoload that. Else fall back to the default location inside /vendor. Is that possible?
FWIW, this is Laravel specific package, which means that I could use Laravel's publish command to copy the entire folder where ever, but then
I would have to manually add the new location to autoload;
Even if I do, there would be namespace conflict between the old and new location.
I would like Composer to first see if the folder exists under the app's root, and if it does then autoload that. Else fall back to the default location inside /vendor. Is that possible?
Yes, it is possible.
You need to mention everything on your ServiceProvider for your package.
There are every informations about how to publish your views, assets in the docs and it fits your needs.
Have a look at the docs:
https://laravel.com/docs/5.3/packages#public-assets
I am copying some example for you over here:
If you want to publish your translations, you need to perform this task:
/**
* Perform post-registration booting of services.
*
* #return void
*/
public function boot()
{
$this->loadTranslationsFrom(__DIR__.'/path/to/translations', 'courier');
$this->publishes([
__DIR__.'/path/to/translations' => resource_path('lang/vendor/courier'),
]);
}
If you don't have translation in app's lang/vendor/courier then it falls back to your package translation.
You don't need to copy your class codes, which could remain in your package directory. The only things you copy will be your views, assets, translation files etc.
This should help you.

Laravel: Edit file in the vendor directory

I am working with laravel and I have installed a package using composer by running this command composer require mailchimp/mailchimp=~2.0.
After that I got a folder 'mailchimp' in the vendor directory. In there, there is a file named Mailchimp.php that I have to modify, but based on some old posts here, if I modify the file, any time I run the command composer update, I will loose my changes in the file, just because it is located in the vendor directory. So is there any option for me to solve this problem ?
I tried using the command php artisan vendor:publish but I do not get the expected results.
You can create a custom class which will extend the Mailchimp class and override the function you want. Then use the custom class in your code.
use DrewM\MailChimp\MailChimp;
class CustomMailChimp extends MailChimp {
...
// The function you would like to override
}
Then use it new CustomMailChimp(..)

How to create Helper Methods on Laravel not a Facade

I've read a lot of questions on how to make helper methods in Laravel 5.1. But I don't want to achieve this via a Facade.
HelperClass::methodName();
I want to make helper methods just like on these methods Laravel Helper Methods like:
myCustomMethod();
I don't want to make it a Facade. Is this possible? How?
If you want to go the 'Laravel way', you can create helpers.php file with custom helpers:
if (! function_exists('myCustomHelper')) {
function myCustomHelper()
{
return 'Hey, it\'s working!';
}
}
Then put this file in some directory, add this directory to autoload section of an app's composer.json:
"autoload": {
....
"files": [
"app/someFolder/helpers.php"
]
},
Run composer dumpauto command and your helpers will work through all the app, like Laravel ones.
If you want more examples, look at original Laravel helpers at /vendor/laravel/framework/Illuminate/Support/helpers.php
To start off I created a folder in my app directory called Helpers. Then within the Helpers folder I added files for functions I wanted to add. Having a folder with multiple files allows us to avoid one big file that gets too long and unmanageable.
Next I created a HelperServiceProvider.php by running the artisan command:
artisan make:provider HelperServiceProvider
Within the register method I added this snippet
public function register()
{
foreach (glob(app_path().'/Helpers/*.php') as $filename){
require_once($filename);
}
}
lastly register the service provider in your config/app.php in the providers array
'providers' => [
'App\Providers\HelperServiceProvider',
]
After that you need to run composer dump-autoload and your changes will be visible in Laravel.
now any file in your Helpers directory is loaded, and ready for use.
Hope this works!
This is what is suggested by JeffreyWay in this Laracasts Discussion.
Within your app/Http directory, create a helpers.php file and add your functions.
Within composer.json, in the autoload block, add "files": ["app/Http/helpers.php"]. And run
composer dump-autoload.

laravel 4 workbench routing to the package

I have been working with laravel 4 for some time now and i needed to create an admin area so i decided to use a package to keep things all organized and separated from the rest of the application.
So i created a package with composer as 'vendor/admin'.
then i added those lines as documemented on laravel site
AdminServiceProvider.php
public function boot()
{
$this->package('vendor/admin', 'admin');
include __DIR__.'/../../routes.php';
}
public function register()
{
//
$this->package('vendor/admin');
}
I also created a routes.php file in vedor/admin/ directory to route all admin area in this file.
following i run the 'php artisan dump-autoload' and i finalized with this commend on artisan 'php artisan config:publish vendor/admin'
now i wanna be able use this package for mysite.com/admin route and i want the routes.php file in the package to render the routing for that URI, to do that:
Do i need to modify my app/routes.php?
How can i make vendor/admin/src/routes.php file to do the routing for all mysite.com/admin routes?
Thanks.
No you don't need to edit app/routes.php. As long as it doesn't contain any admin routes that could collide with the ones in your package you can leave it that way.
The routes file in a package can be used like the "normal" app/routes.php. An easy way to deal with admin routes is to have a prefix group:
Route::group(array('prefix' => 'admin'), function(){
// all your admin routes. for example:
Route::get('dashboard', '...');
// will match GET /admin/dashboard
});
Besides that, make sure you're package gets loaded correctly! One part being registering the service provider. Assuming the namespace of your package is Admin you need to add Admin\AdminServiceProvider to the providers array in app/config/app.php. More information

Categories