Change the storage path in Laravel 5 - php

I want to change the Laravel 5.1 storage path: something like /home/test/storage. This has the advantage that these files are not stored in the repository, which is fairly ugly I think.
In Laravel 4, this was very simple with bootstrap/paths.php.
In Laravel 5, it works by using $app->useStoragePath('/path/') in bootstrap/app.php. However, I want to define the storage path with a config option, like $app->useStoragePath(config('app.storage_path'). The config option calls an environment variable or returns a default location.
Doing this results in a Uncaught exception 'ReflectionException' with message 'Class config does not exist'; this makes sense, because this function is not loaded yet.
I tried setting the storage path just after booting:
$app->booted(function () use ($app) {
$app->useStoragePath(config('app.storage_root'));
});
This changed nothing. I also tried directly binding it to path.storage:
$app->bind('path.storage', function ($app) {
return config('app.storage_root');
});
The last option works partially; the view cache is now placed in the correct location, but the logs are still at the old location.

Set it up in .env
app.php
'app_storage' => env('APP_STORAGE', storage_path()),
app/Providers/AppServiceProvider.php
public function register()
{
$this->app->useStoragePath(config('app.app_storage'));
}
.env
APP_STORAGE=custom_location

Laravel 5.3 is in bootstrap/app.php
/*
|--------------------------------------------------------------------------
| Set Storage Path
|--------------------------------------------------------------------------
|
| This script allows us to override the default storage location used by
| the application. You may set the APP_STORAGE environment variable
| in your .env file, if not set the default location will be used
|
*/
$app->useStoragePath( env( 'APP_STORAGE', base_path() . '/storage' ) );

Here is a simple solution of changing the storage path in Laravel 5 like we do in Laravel 4
on bootstrap/app.php
# new storage path
# base_path() -> returns root path
$path_storage = base_path() . "../../storage";
# override already $app->storagePath using the function
$app->useStoragePath($path_storage);
this will make the storage path to be same with the session, views, cache, logs

This works on Laravel 5.2
File: app/Providers/AppServiceProvider.php
public function register() {
...
$this->app->useStoragePath(config('what_ever_you_want'));
...
}

Calling useStoragePath on your AppServiceProvider wouldn't do the job properly because the AppServiceProvider is called after the config files are loaded. so any use of storage_path in config files would still refer to the old storage path.
In order to properly solve this problem I suggest you extend Application class and then on the constructor of your own class write the followings.
/**
* MyApplication constructor.
*/
public function __construct($basePath = null)
{
parent::__construct($basePath);
// set the storage path
$this->afterLoadingEnvironment(function () {
$this->useStoragePath(/*path to your storage directory*/);
});
}

if your website is hosted;
move everything from public folder to root folder
$app->bind('path.public', function() {
return __DIR__;
});

add this code in your bootstrap/app.php :
$app->useStoragePath(__DIR__ . '/../custom-path/');
and in config/filesystem.php :
'local' => [
'driver' => 'local',
'root' => storage_path('everything'), //custom-path/everything
],
'public' => [
'driver' => 'local',
'root' => storage_path(''),
'url' => env('APP_URL'),
'visibility' => 'public',
],
and then run php artisan config:cache

This works on Laravel 5.8 because you have to load the environment variables before you try to use them.
File: bootstrap/app.php
$app->afterLoadingEnvironment(function() use ($app) {
$app->useStoragePath(env('APP_STORAGE', storage_path()));
});

Related

Lumen - Mono Log - Create Custom log file [duplicate]

I want to add to my Lumen project a daily Log.
I try this in the app.php (Folder Bootstrap/)
$logFile = 'laravel.log';
Log::useDailyFiles(storage_path().'/logs/'.$logFile);
But this set me that error
Call to undefined method Monolog\logger::useDailyFiles()
Any help I appreciate...Thanks
If you look at the framework source code here you can see that it will not do daily logs, but rather write to a single log file lumen.log. There is a public method available configureMonologUsing seen here and referenced here that you can use to override the default behavior without extending the Application.
Lumen just sets a handler to monolog, so another good solution is you could do this:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\RotatingFileHandler;
class LogServiceProvider extends ServiceProvider
{
/**
* Configure logging on boot.
*
* #return void
*/
public function boot()
{
$maxFiles = 5;
$handlers[] = (new RotatingFileHandler(storage_path("logs/lumen.log"), $maxFiles))
->setFormatter(new LineFormatter(null, null, true, true));
$this->app['log']->setHandlers($handlers);
}
/**
* Register the log service.
*
* #return void
*/
public function register()
{
// Log binding already registered in vendor/laravel/lumen-framework/src/Application.php.
}
}
Then don't forget to add the service provider to your Lumen bootstrap/app.php:
$app->register(\App\Providers\LogServiceProvider::class);
In Lumen 5.6 better way is to configure your default setting in .env as LOG_CHANNEL=daily
By default the setting is LOG_CHANNEL=stack which use single file for logging.
Starting from version 5.6, configuring the logging system is much easier:
Create directory config in your project if it doesn't exist
Copy the logging config file from
vendor/laravel/lumen-framework/config/logging.php to your project config dir
Edit file config/logging.php and adjust the channels property to your liking.
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily'],
],

Unable to use Laravel / Socialite with Lumen

I try to use the package Laravel\Socialite in my system in Lumen (5.1)
I added this in the config\services.php file :
<?php
//Socialite
'facebook' => [
'client_id' => '##################',
'client_secret' => '##################',
'redirect' => 'http://local.dev/admin/facebook/callback',
],
In bootstrap\app.php file :
class_alias(Laravel\Socialite\Facades\Socialite::class, 'Socialite');
$app->register(Laravel\Socialite\SocialiteServiceProvider::class);
Then I created a controller for the facebook authentication :
<?php
namespace App\Http\Controllers\Facebook;
use App\Http\Controllers\Controller;
use Laravel\Socialite\Contracts\Factory as Socialite;
class FacebookController extends Controller
{
public function redirectToProviderAdmin()
{
return Socialite::driver('facebook')->scopes(['manage_pages', 'publish_actions'])->redirect();
}
public function handleProviderCallbackAdmin()
{
$user = Socialite::driver('facebook')->user();
}
}
And in the routes.php :
$app->get('/admin/facebook/login', 'App\Http\Controllers\Facebook\FacebookController#redirectToProviderAdmin');
$app->get('/admin/facebook/callback', 'App\Http\Controllers\Facebook\FacebookController#handleProviderCallbackAdmin');
I just followed the documentation, changing according to my needs. When I go to page http://local.dev/admin/facebook/login, I get the following error :
Non-static method Laravel\Socialite\Contracts\Factory::driver() cannot be called statically, assuming $this from incompatible context
Indeed, according to the code, driver function must be instanciate.
EDIT : And if I try to instanciate this class, I get the following error :
Cannot instantiate interface Laravel\Socialite\Contracts\Factory
How do you make this module to work?
here's how that works in my case
in services.php file
'facebook' => [
'client_id' => '***************',
'client_secret' => '***************',
'redirect' => ""
],
i left redirect empty cause my site is multilingual (so, it fills in a bit later with sessions). if you use only one language, put there your callback absolute path. for example
"http://example.com:8000/my-callback/";
also check your config/app.php. in providers array
Laravel\Socialite\SocialiteServiceProvider::class,
in aliases array
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
my routes look like this
Route::get('facebook', 'Auth\AuthController#redirectToProvider');
Route::get('callback', 'Auth\AuthController#handleProviderCallback');
here's auth controllers methods. put in top
use Socialite;
//იობანი როტ
public function redirectToProvider(Request $request)
{
return Socialite::with('facebook')->redirect();
}
public function handleProviderCallback(Request $request)
{
//here you hadle input user data
$user = Socialite::with('facebook')->user();
}
my facebook app
giga.com:8000 is my localhost (so its the same localhost:8000)
as you can see in Valid OAuth redirect URI, you should put there your callback. in my case i use three urls cause i have three languages. in your case it should be just
http://your-domain-name.com:8000/callback
if you work on localhost, you should name your domain in config/services.php
mine look like this
'domain' => "your-domain.com",
after everything run these commands
php artisan cache:clear
php artisan view:clear
composer dump-autoload
restart your server, clear your browser cookies. hope it helps

Laravel 5 File Delete Error

There is an issue related to my laravel 5 web application regarding the file deletion.
I want to delete an entry from my table with corresponding image file.
Here is my table structure.
Schema::create('master_brands',function($table){
$table->increments('pk_brand_id');
$table->string('brand_name');
$table->string('brand_logo');
$table->timestamps();
});
I added 3 brands to db and storing image path in brand_logo field like : (/uploads/masters/logocatagory_Computers & IT.png).
When deleting the record from database I want to delete the image file from uploads folder also.
But the File was not deleting when I performing delete action.
here is my delete controller.
public function branddelete($id)
{
$filename = DB::table('master_brands')->where('pk_brand_id', $id)->get();
$filname = url()."/app".$filename[0]->brand_logo;
File::delete($filname); // http://localhost/genie-works/devojp/app//uploads/masters/logocatagory_Computers & IT.png
}
The file is exist in my directory and the directory having 777 permission. !!
I also tried the Storage class to delete file.But there is no way !!!..
How can I solve this issue? Any Ideas... :(
You are doing it the wrong way. You can't possibly delete a file from URL, you must provide file PATH not URL
Edited
Assuming the file you wish to delete is located in public/uploads/masters/logocatagory_Computers you could do this:
public function branddelete($id)
{
$filename = DB::table('master_brands')->where('pk_brand_id', $id)->get();
$filname = $filename[0]->brand_logo;
//example it.png, which is located in `public/uploads/masters/logocatagory_Computers` folder
$file_path = app_path("uploads/masters/logocatagory_Computers/{$filname}");
if(File::exists($file_path)) File::delete($file_path);
}
If you have the file out Storage/app/ , Storage:: does not work, change the /Config/Filesystems.php try put your 'local' at base_path() and comment default storage_path(),
'disks' => [
'local' => [
'driver' => 'local',
'root' => base_path(),
// 'root' => storage_path('app'),
],
Then in Controller
use Illuminate\Support\Facades\Storage;
Then in public funtion use Storage Model
$path= 'uploads/masters/';
Storage::delete($path . $filname);
In Laravel 5.1. When using the local driver, note that all file operations are relative to the root directory defined in your configuration file. By default, this value is set to the storage/app directory. Therefore,
the following method would store a file in storage/app/file.txt:
Storage::put('file.txt', 'Contents');
this would delete file.txt in storage/app
Storage::delete('file.txt');
If you want to change the root directory,take 'storage/app/uploads/' for example , you could set the filesystem.php as following :
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app/uploads/'),
],
...
then this following method would store a file in storage/app/uploads/file.txt:
Storage::put('file.txt', 'Contents');
this would delete file.txt in storage/app/uploads directory.
Storage::delete('file.txt');
Something that took me quite some time to figure out today:
In case you're trying to delete a list of files that are wrapped in Laravel's own Collection wrapper, you might need to call ->all() to get the underlying array instance:
// The following is an example scenario
$files = Storage::list('downloads');
$collection = collect($files)->filter(function ($file) {
return str_contains($file, 'temp');
});
Storage::delete($collection->all()); // Note the "all()" call here

Laravel 5 - Config sub-folder

In Laravel 5, we can read a config value via this:
config('app.url')
But, how can we read config file value in the sub-folder? I have tried with config('subfolder/app.url') but it didn't work.
You can do like this in laravel 5 config('subfolder.myfile.var'); subfolder is folder name , myfile is your file name and var is your variable.
I've created: config/local/app.php containing:
<?php
return [
"key" => "value"
];
and using artisan, here's what i got:
Create Folder with name subfolder inside config directory create file app.php
Inside app.php put all your constants
return array(
'APP_URL' => 'http://www.test.com/xyz',
'APP_MAX_FOLDER_SIZE' => 1000000000,
);
and access like
config('subfolder.app.APP_URL');
it is advisable to create constants in Upper case letter and create file name that makes sense like constans.php or appconstants.php etc
for Lumen developers
Just in case someone need it. This is the way I was able to do it:
Step 1 - Create the sub directory under config/ for example validator
Step 2 - Create the configuration files: messages.php, rules.php
config
└── validator
├── messages.php
└── rules.php
Step 3 - Enable the configuration files under bootsrap/app.php
/*
|--------------------------------------------------------------------------
| Register Custom Configuration
|--------------------------------------------------------------------------
|
| Register custom configuration files that are under config/
|
*/
$app->configure('validator/messages');
$app->configure('validator/rules');
/**/
$app->router->group([
'namespace' => 'App\Http\Controllers',
], function ($router) {
require __DIR__.'/../routes/web.php';
});
return $app;
Step 4 - Get the configuration
config('validator/rules.key');
ref: https://laracasts.com/discuss/channels/lumen/config-in-subdirectory

Setting aliases in Yii2 within the app config file

I'm trying to set an alias in Yii2 but I'm getting a Invalid Parameter / Invalid path alias for the below code that is placed in the app config file:
'aliases' => [
// Set the editor language dir
'#editor_lang_dir' => '#webroot/scripts/sceditor/languages/',
],
If I remove the # it works.
I noticed you can do this:
Yii::setAlias('#foobar', '#foo/bar');
...but I would prefer to set it within the app config file. Is this not possible? If so, how?
Yii2 basic application
To set inside config file, write this inside $config array
'aliases' => [
'#name1' => 'path/to/path1',
'#name2' => 'path/to/path2',
],
Ref: http://www.yiiframework.com/doc-2.0/guide-structure-applications.html
But as mentioned here,
The #yii alias is defined when you include the Yii.php file in your entry script. The rest of the aliases are defined in the application constructor when applying the application configuration.
If you need to use predefined alias, write one component and link it in config bootstrap array
namespace app\components;
use Yii;
use yii\base\Component;
class Aliases extends Component
{
public function init()
{
Yii::setAlias('#editor_lang_dir', Yii::getAlias('#webroot').'/scripts/sceditor/languages/');
}
}
and inside config file, add 'app\components\Aliases' to bootstrap array
'bootstrap' => [
'log',
'app\components\Aliases',
],
In config folder create file aliases.php. And put this:
Yii::setAlias('webroot', dirname(dirname(__DIR__)) . '/web');
Yii::setAlias('editor_lang_dir', '#webroot/scripts/sceditor/languages/');
In web folder in index.php file put:
require(__DIR__ . '/../config/aliases.php');
Before:
(new yii\web\Application($config))->run();
If run echo in view file:
echo Yii::getAlias('#editor_lang_dir');
Show like this:
C:\OpenServer\domains\yii2_basic/web/scripts/sceditor/languages/
#webroot alias is not available at this point, it is defined during application bootstrap :
https://github.com/yiisoft/yii2/blob/2.0.3/framework/web/Application.php#L60
No need to define this alias yourself, you should simply use another one :
'aliases' => [
// Set the editor language dir
'#editor_lang_dir' => '#app/web/scripts/sceditor/languages/',
],
To improve on #vitalik_74's answer
you can place it in config/web.php instead(if you are using the basic yii app, I'm not sure about the main config file in the advance version, but the same applies, just put the require on the main config file) so that it gets shorten to:
require(__DIR__ . '/aliases.php');

Categories