Code in Laravel AppServiceProvider halts Composer & build when deploying via DeployHQ - laravel

I have the following code in my AppServiceProvider.php file:
<?php
namespace App\Providers;
use App\Models\Setting;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
if (Schema::hasTable('settings')) {
foreach (Setting::all() as $setting) {
Config::set('settings.'.$setting->key, $setting->value);
}
}
}
}
Which does it's job fine locally, but when I deploy via DeployHQ, it kills the process with the following error:
SQLSTATE[HY000] [2002] No such file or directory (SQL: select * from
information_schema.tables where table_schema = giga and table_name =
settings and table_type = 'BASE TABLE')
Which kinda makes sense, the database doesn't exist on the build server, so the check cannot run as there's nothing to check. Is there a different way to hydrate a settings config with values from a database on boot which doesn't affect the running of php artisan package:discover?
I know it'll probably be asked, but the .env file etc is all set up correctly. This issue is to do with the fact the build server doesn't have the database, but the server the files get piped to does.
Edit:
To give some more context, and perhaps some advice could be given on this, I'm only really using this config value in this code inside a Service class:
public function __construct()
{
$this->domain = config('api.domain');
$this->apiVersion = config('api.version');
$this->bearerToken = config('settings.bearer_token');
$this->clientId = config('api.client_id');
$this->clientSecret = config('api.client_secret');
}
Everything online suggests putting these values into the config, however if it's only being called here would it be okay to retrieve it from the Database directly?

Related

Passing Company Data to All controller in Laravel 6.x

I am building an app where each company have multiple users. And all users can upload documents/images/xls etc. I want to keep all company data in company separate folder. To complete this I am checking the company detail for every user and then upload data to company specific folder. Can I check company database once per user login and share user's company details to all controller and can easily access.
Use view composer in your AppServiceProvider
App\Providers\AppServiceProvider.php
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
view()->composer('*',function($view) {
if(auth()->user()) {
$comanyData = App\Company::where('user_id',auth()->user()->id);
$view->with('companyData', $companyData);
}
});
}
}
You can make the helper function to use in controllers or blades files.
Let’s create a helper!
Create a simple PHP file.
Create Helper.php inside the app directory or wherever directory you want.
<?php
/**
* get company data
*
*/
function companyData()
{
// Create logic of company data
// return company data
}
Autoload Composer
After we created our helper, Laravel won’t recognize our file so we need to register the helper file to our composer.json. Add File array inside the autoload section. It may look like this:
"autoload": {
"classmap": ["database"],
"psr-4": {"App\\": "app/"},
"files" : ["app/Helper.php"]
}
Then don’t forget to run
composer dumpautoload
Using helper function
Our helper is autoloaded now, so we should be able to use our helper immediately on different controllers. Just call our function in any class
$companyData = companyData();
or in blade view
{{ companyData() }}
Let me know if you are facing an issue.
Below is how to share a variable with your entire application via the AppServiceProvider, You can also do this inside of your base controller in the construct method.
File: App\Providers\AppServiceProvider.php
<?php
namespace App\Providers;
use View;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
View::share('key', 'value');
}
}
You can then access $key inside of any view.

Artisan command for clearing all session data in Laravel

What is the artisan command for clearing all session data in Laravel, I'm looking for something like:
$ php artisan session:clear
But apparently it does not exist. How would I clear it from command line?
I tried using
$ php artisan tinker
...
\Session::flush();
But it flushes session of only one user, I want to flush all sessions for all users. How can I do it?
I tried this:
artisan cache:clear
But it does not clear session, again.
If you are using file based sessions, you can use the following linux command to clean the sessions folder out:
rm -f storage/framework/sessions/*
UPDATE: This question seems to be asked quite often and many people are still actively commenting on it.
In practice, it is a horrible idea to flush sessions using the
php artisan key:generate
It may wreak all kinds of havoc. The best way to do it is to clear whichever system you are using.
The Lazy Programmers guide to flushing all sessions:
php artisan key:generate
Will make all sessions invalid because a new application key is specified
The not so Lazy approach
php artisan make:command FlushSessions
and then insert
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use DB;
class flushSessions extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'session:flush';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Flush all user sessions';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
DB::table('sessions')->truncate();
}
}
and then
php artisan session:flush
The problem is that PHP's SessionHandlerInterface does not force session drivers to provide any kind of destroyAll() method. Thus, it has to be implemented manually for each driver.
Taking ideas from different answers, I came up with this solution:
Create command
php artisan make:command FlushSessions
Create class in app/Console/Commands/FlushSessions.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class FlushSessions extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'session:flush';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Flush all user sessions';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$driver = config('session.driver');
$method_name = 'clean' . ucfirst($driver);
if ( method_exists($this, $method_name) ) {
try {
$this->$method_name();
$this->info('Session data cleaned.');
} catch (\Exception $e) {
$this->error($e->getMessage());
}
} else {
$this->error("Sorry, I don't know how to clean the sessions of the driver '{$driver}'.");
}
}
protected function cleanFile () {
$directory = config('session.files');
$ignoreFiles = ['.gitignore', '.', '..'];
$files = scandir($directory);
foreach ( $files as $file ) {
if( !in_array($file,$ignoreFiles) ) {
unlink($directory . '/' . $file);
}
}
}
protected function cleanDatabase () {
$table = config('session.table');
DB::table($table)->truncate();
}
}
Run command
php artisan session:flush
Implementations for other drivers are welcome!
An easy way to get rid of all sessions is to change the name of the session cookie. This can be easily done by changing the 'cookie' => '...' line in config/session.php file.
This works independently of the session storage you use and also won't touch any other data except the session data (and thus seems preferable over the renewing the app key solution to me, where you would loose any encrypted data stored in the app).
If you want completely remove session from whatever driver you use.
Use this piece of code
\Session::getHandler()->gc(0); // Destroy all sessions which exist more 0 minutes
Sometimes the most helpful answer is at the end
This thread is quite much old. But I would like to share my implementation of removing all sesssions for file based driver.
$directory = 'storage/framework/sessions';
$ignoreFiles = ['.gitignore', '.', '..'];
$files = scandir($directory);
foreach ($files as $file) {
if(!in_array($file,$ignoreFiles)) unlink($directory . '/' . $file);
}
Why I have not used linux command 'rm'?
Because PHP is one of the prerequisites for Laravel and Linux is not. Using this Linux command will make our project implementable on Linux environment only.
That's why it is good to use PHP in Laravel.
I know this is an old thread, but what worked for me is just remove the cookies.
In Chrome, go to your develop console, go to the tab "Application". Find "Cookies" in the sidebar and click on the little arrow in front of it. Go to your domainname and click on the icon next to the filter field to clear the cookies for your domain. Refresh page, and all session data is new and the old ones are removed.
My solution
Laravel
// SESSION_DRIVER=file
$files = File::allFiles(storage_path('framework/sessions/'));
foreach($files as $file){
File::delete(storage_path('framework/sessions/'.$file->getFilename()));
}
//OR
//SESSION_DRIVER=redis
Artisan::call('cache:clear'); // == php artisan cache:clear
If you use database session , just delete all data on that table.
In my case it is 'sessions' table.
If you are using the database for session driver, then empty the sessions table. Regenerating the key will cause a lot of problems if you are using single login on many subdomains. Emptying the session table helps reduce the useless data in the session table. You can delete cookies on everyone's browswer.

Can laravel blade service injection can be done from outside view

I want to inject service globally for all application views
can i inject it thorough application service provider boot method ?
What service you want to inject? How will you use it?
An easy way to share variables across all views is to call the share method:
view()->share([
'myService' => app()->make(My\Service::class),
]);
You can call this within your controller or maybe inside a middleware to work across many different controllers, too.
Then, in your views, something like this:
#foreach ($myService->getItems() as $item)
...
#endforeach
Follow this steps:
create service provider: php artisan make:provider UserServiceProvider
Go to
app\providers\UserServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\View;
use Auth;
class UserServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
// key can be anything
// value what you want
View::share('key', 'value');
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
}
}
Than register this service provider inside the config\app.php
App\Providers\UserServiceProvider::class,
Now you can access this key for every views.

Override sendSwiftMessage() Laravel Swiftmailer with custom

I am using Laravel 4.2
The answer given by user3158900 is for Laravel 5.*
Any one can help me with version 4.2 ?
I would like to override sendSwiftMessage() protected function with my own function.
sendSwiftMessage() is located in
"vendor/laravel/framework/src/Illuminate/Mail/Mailer.php"
I created a
Lib/Mailer/CustomMailer.php
and Set the folder Lib to autoload in composer (PSR4).
I can now call/load my function in my controllers by writing:
new Lib\Mailer\CustomMailer;
This is how my file looks like:
<?php namespace Lib\Mailer;
class CustomMailer extends \Illuminate\Mail\Mailer {
/**
* Send a Swift Message instance.
*
* #param \Swift_Message $message
* #return void
*/
protected function sendSwiftMessage($message)
{
if (strpos($message->toString(), 'noemail#noemail.com') == true) {
Log::info('Not sending mail to noemail#noemail.com');
}
else
{
if ($this->events)
{
$this->events->fire('mailer.sending', array($message));
}
if ( ! $this->pretending)
{
$this->swift->send($message, $this->failedRecipients);
}
elseif (isset($this->logger))
{
$this->logMessage($message);
}
}
}
}
However, this sendSwiftMessage() function is not used when I send an email with Swiftmailer in my controller by doing EXAMPLE:
Mail::send(xxxx);
My question: How can I make Swiftmailer/Laravel use my custom sendSwiftMessage() function when I send a message if I don't want to modify all my Controllers that currently use the Mail::send() code
Think I got this figured out, however I am getting an error but I think that's on you because your custom class is using a property that doesn't exist so here's the solution anyway.
In AppServiceProvider.php in the boot() method, I've added the following:
$this->app->singleton('customMailer', function($app) {
return new CustomMailer(
$app['view'], $app['swift.mailer'], $app['events']
);
});
In app/Lib/Mailer folder, I've added another class for the facade.
namespace App\Lib\Mailer;
use Illuminate\Support\Facades\Facade;
class Mail extends Facade
{
/**
* Get the registered name of the component.
*
* #return string
*/
protected static function getFacadeAccessor()
{
return 'customMailer';
}
}
In config/app.php, I've replaced the Mail alias with the following...
'Mail' => App\Lib\Mailer\Mail::class,
And that should be all you need to do.
One other thing, I just noticed you are missing in your namespace the App which explains why you had to add the Lib folder to the autoloader. If you namespace it correctly to keep it inline with PSR-4 by adding the App\ onto the beginning, then you don't need to add anything to your composer.json file to get additional classes loaded.

Laravel 5.2 - ServiceProvider boot not working

Trying to use service provider to set a variables throughout all views pages that #extends('layouts.app') but not working, first I show the codes below.
AppServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Auth;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
// Using class based composers...
view()->composer('layouts.app', function($view){
$view->with('current_user', Auth::user());
});
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
}
When I visit the page that calls {{$current_user}}, it shows the following error
ErrorException in 5a5612347179ad88a6d4ebacc5d911a184c1b4ed.php line 14:
Undefined variable: current_user (View: C:\xampp\htdocs\soyegg\resources\views\shops\edit\showroom.blade.php)
Went through a several questions solved in the website and checked the followings but still failed:
1. AppServiceProvider is in config.app (default by Laravel 5.2)
2. php artisan clear-compiled
3. php artisan optimize
4. check whether there is compiled.php and try to clear it mannually but there is in neither storage/framework nor vendor.
Please help!
I think your ServiceProvider is working fine, you only need to change the way you passing data to the view. I've tested it myself and I can confirm that passing data to a view which later will be included with #extends() won't work. Instead you can use another methods:
view()->share('current_user', Auth::user());
Or using wildcard:
view()->composer('*', function ($view) {
$view->with('current_user', Auth::user());
});
// wildcard with prefix
view()->composer('prefix.*', function ($view) {
$view->with('current_user', Auth::user());
});

Resources