I'm setting up Laravel echo to broadcast events. But whenever I try to broadcast to a channel the channel name gets an automatic prefix: 'laravel_database_'
I've tried switching the return inside the Event to a regular 'Chanel' as following:
public function broadcastOn()
{
return new Channel('public');
}
but when I look into the laravel-echo-server logs I see it is still being broadcasted on: 'laravel_database_public'.
This way I would need to do the following in my JS:
Echo.channel('laravel_database_public').listen('MessageSent', ({message}) => {
console.log(message);
});
But ofcourse, I want to remove the prefix (or figure out why its there). Hopefully someone can clear this up for me. Thanks in advance.
This is configurable in config/database.php (and I believe even removable) under
'redis' => [
'options' => [
'prefix' => // change here.
]
]
The accepted answer does not work with laravel-echo-server.
The solution is rather to let the whole Redis Laravel config untouched and to run version ^1.6.0 of laravel-echo-server with the proper keyPrefix option in laravel-echo-server.json config file:
{
"databaseConfig": {
"redis": {
"keyPrefix": "laravel_database_"
}
}
}
Source
As at Laravel 7, the config/database.php looks like this
'redis' => [
'client' => env('REDIS_CLIENT', 'predis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_database_'),
],
]
So it searches the .env file for your REDIS_PREFIX variable, if there's none, then it generates laravel_database_ or based on whatever you set APP_NAME to in your .env file.
All you have to do is set your REDIS_PREFIX. You can leave it empty so that there is no prefix at all.
Related
I'm writing a couple of laravel packages and I'm wondering if it is possible to have the package write to a specific log file but only for messages related to the package?
I tried making a logging.php file in the packages/myorg/mypackage/config (below) but it doesn't seem to do anything.
use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogUdpHandler;
return [
'default' => env('LOG_CHANNEL', 'stack'),
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single'],
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/mypackage.log'),
'level' => env('LOG_LEVEL', 'debug'),
]
]
];
I am using "jeroen-g/laravel-packager" to set up the packages. It appears to manually load the mypackage.config in the ServiceProvider bootForConsole
protected function bootForConsole(): void
{
// Publishing the configuration file.
$this->publishes([
mypackage.'/../config/mypackage.php' => config_path('mypackage.php'),
], 'mypackage.config');
}
I'm not sure how to add custom logging to that though. I'm still learning Laravel and I'm not quite sure what or how the main applications config/logging.php is read so I'm not quite sure how to inject a custom version for an add-on package.
EDIT:
I found a post that suggested using the following in the ServiceManager boot() method:
$this->app->make('config')->set('logging.channels.mychannel', [
/* settings */
]);
I used the package config to set a 'logging' => [ 'channels' => [ 'mychannel' => [ /* settings */ ] ] ] and could then do the same thing as above with:
$this->app->make('config')->set('logging.channels.mychannel', config('mypackage.logging.channels.mychannel');
But that still required something in the code. The next best thing I have found thus far is to change my config/logging.php to config/logging.channels.php and include something like:
return [
'mychannel' => [
'driver' => 'single',
'path' => storage_path('logs/mypackage.log'),
'level' => env('LOG_LEVEL', 'debug'),
]
];
Then in the service provider register() method add:
$this->mergeConfigFrom(__DIR__ . '/../config/logging.channels.php', 'logging.channels');
I tried doing it from the original 'logging.php' with channels array nested in a 'logging' key, but array_merge doesn't appear to merge the nested elements so my channel never showed up in logging.channels.
I'm not sure if this is ideal, however. I'd still like to know if there is a 'better' or best practices way of adding custom package logging parameters and whether there is a need to publish it in any way (and how).
First of all, i'm not a pro in PHP development or Laravel but will try to explain my question as well as possible for me. I also try to give enough information but when something is missing, please let me know whats missing and i will add it!
Some important context about my project:
Laravel 6.18 (will update soon if my first goal is reached)
I use Hyn/Multi-tenant to make my application mutli tenant.
I use a Vue front end, i give a bearer token to Vue via the app.js
The application should be a multi tenant application where each tenant has its own user table. I first built everything as "single tenant". When the basic functionality was implemented and worked fine, i added Hyn/MT to make it multi tenant, moved the tenant specific tables to the tenant db folder and updated the models. Now i know it was better to start with Hyn/MT before building all the functionality but so far i got everything working fine.
After i added the multi tenant support to my project and fixed the broken functionality i decided to add an admin specific area to manage the tenants. To achieve this i added a SystemU ser table to the master database which contains the admin users. After that i update my web.php so it gives the subdomain to the LoginController.guard() function. My code:
// web.php
Route::group(array('domain' => '{subdomain}.festipay.xlan'), function () {
Route::post('login', 'Auth\LoginController#login');
});
// LoginController.php
protected function guard()
{
if (Request::route("subdomain") == "admin") {
return Auth::guard('admin_web');
} else {
return Auth::guard('web');
}
}
I also updated my config/auth.php, it looks like this now:
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin_web' => [
'driver' => 'session',
'provider' => 'admin_users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admin_users' => [
'driver' => 'eloquent',
'model' => App\SystemUser::class,
]
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
],
],
Except for the mentoined changes i did not implement any admin specific logic yet. So i expect that the admin users are handeled exactly the same except for the way they are authenticated.
The tenant users who log in to e.g. tenant_x.domain.com are redirected to /dashboard when they login and are redirected back to /login when they log out. The admin users who log in to admin.domain.com are not redirected to /dashboard when the login is successfull but are redirected back to /login again. Offcourse this is not the expected behaviour as it should be (currenly) the same as the tenant users (so a redirect to /dasboard when the login is succesfull)
I think that the authentication them selve works fine as the LoginController.attemptLogin() returns true when i use valid admin credentials and false (and view shows wrong credetials) when i use invalid credentials.
I found in this post that is may be a session issue and i tried to apply the solution mentoined in that post. Unfortunately did adding protected $primaryKey = 'id'; to the SystemUser class not solve the issue. I also compared the tenant User class with the SystemUser class but they are almost identical exccept for unimportant fields i removed from the SystemUser like address.
I have no idea how i can find out where the issue occurs or how to solve this. The goal is that an admin which logged in succesfully is redirect to another page as the /dashboard. Can someone help me find out what goes wrong? i'm already happy when someone can help me to get the same behaviour for the admin's as the tenants currently have.
Thanks in advance!
Update 1 #David Barker
When its about the session, i think this is important to know as well:
- I use a Vue front end, i give a bearer tokento Vue via theapp.js``
My session config:
<?php
use Illuminate\Support\Str;
return [
'driver' => env('SESSION_DRIVER', 'file'),
'lifetime' => env('SESSION_LIFETIME', 120),
'expire_on_close' => false,
'encrypt' => false,
'files' => storage_path('framework/sessions'),
'connection' => env('SESSION_CONNECTION', null),
'table' => 'sessions',
'store' => env('SESSION_STORE', null),
'lottery' => [2, 100],
'cookie' => env(
'SESSION_COOKIE',
Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
),
'path' => '/',
'domain' => env('SESSION_DOMAIN', null),
'secure' => env('SESSION_SECURE_COOKIE', false),
'http_only' => true,
'same_site' => null,
];
I did a dd($request->session();) in the LoginController->attemptLogin(); function, see the result bellow. The result is the same for both users except for the id and _token. (i cleaned the cookies before the login attempt in both cases)
Illuminate\Session\Store {#490 ▼
#id: "7WI7JUWPnS4pg3EHvaxk5TOKaM9l9UXJi1zJNKuG"
#name: "festipay_session"
#attributes: array:1 [▼
"_token" => "mtMWanYGMUxFHivOqAaEmVQnHDE0hvwKkHMgCswg"
]
#handler: Illuminate\Session\FileSessionHandler {#489 ▼
#files: Illuminate\Filesystem\Filesystem {#198}
#path: "/var/www/domain.com/storage/framework/sessions"
#minutes: "120"
}
#started: true
}
Maybe this is also interesting infomation. Left are the responses for the admin (after i clicked the login button) and right the working tenant login.
I finally found the issue. It was very easy to solve. I did not specify the auth guard for the Route::group.
It was like this:
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () { return redirect('/dashboard'); });
Route::get('/dashboard', function () { return view('dashboard'); })->name('dashboard');
Route::get('/logout', 'Auth\LoginController#logout')->name
I changed it to this to make it work:
Route::group(['middleware' => 'auth:system_user_web,web'], function () {
Route::get('/', function () { return redirect('/dashboard'); });
Route::get('/dashboard', function () { return view('dashboard'); })->name('dashboard');
Route::get('/logout', 'Auth\LoginController#logout')->name
I want to remove the environment variables, database details and the information showing on Laravel Debug.
Here is the screenshot:
Go to config/app and add the following
/**
* Debug Blacklist
*/
'debug_blacklist' => [
'_COOKIE' => array_keys($_COOKIE),
'_SERVER' => array_keys($_SERVER),
'_ENV' => array_keys($_ENV),
],
it will replace all environment variables value with an asterisks (*******)
This is from my config/app file:
'debug_blacklist' => [
'_ENV' => [
'APP_KEY',
'DB_DATABASE',
'DB_PASSWORD',
'DB_USERNAME',
'REDIS_PASSWORD',
'MAIL_PASSWORD',
'PUSHER_APP_KEY',
'PUSHER_APP_SECRET',
],
'_SERVER' => [
'APP_KEY',
'DB_DATABASE',
'DB_PASSWORD',
'DB_USERNAME',
'REDIS_PASSWORD',
'MAIL_PASSWORD',
'PUSHER_APP_KEY',
'PUSHER_APP_SECRET',
],
'_POST' => [
'password',
],
],
Add this array to our config/app file, the the system will replace real values with ***.
This way is useful if you want control on specific key items.
You can make your own error pages. (official documentation)
Make a blade file for 500 errors. (resources/views/errors/500.blade.php)
And print error messages or trace log
<h2>{{ $exception->getMessage() }}</h2>
Change from APP_DEBUG=true to APP_DEBUG=false in the .env file. Then you can rely on the laravel logs for your errors. (yourLarvelApp/storage/logs)
Go to your project file: open .env file in notepad and find out APP_DEBUGAPP_DEBUG=true you just rename false; and save. your problem is solve.
I have an application based on CakePHP version 3.2.10. I'm totally new in CakePHP so sorry if it is a banal problem. In my application I use CSRF component and Auth component configured in this way:
$this->loadComponent('Auth', [
'authorize'=> 'Controller',
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email',
'password' => 'password'
],
'scope' => [
'Users.active' => 1,
]
]
],
'loginAction' => [
'controller' => 'Users',
'action' => 'login'
],
'logoutAction' => [
'controller' => 'Users',
'action' => 'logout'
],
'logoutRedirect' => [
'controller' => 'Pages',
'action' => 'index'
],
'unauthorizedRedirect' => '/', // $this->referer()
]);
and login action like
public function login()
{
$this->set('title', 'Logowanie');
$this->set('bodyclass', 'main-page');
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
if($user['blocked'] == 0) {
$this->Auth->setUser($user);
if ($this->Auth->user('role') == 'admin')
return $this->redirect(['controller' => 'Admin', 'action' => 'index']);
return $this->redirect($this->Auth->redirectUrl());
}
else{
$this->Flash->error('Konto zostało zablokowane przez administratora serwisu. Skontaktuj się z Biurem Obsługi.');
}
} else $this->Flash->error('Błędne dane logowania. Spróbuj ponownie.');
}
}
Now the problem:
Few days ago I changed server where application is running, and after changing it logging in stopped working. After clicking login there is a message CSRF Token cookie is missing. To test if the component is the problem i disabled csrf and try again then white screen appears and nothing happen if i refresh page i'm not logged in. I checked the working version and not working version and realized that Cake not store any cookies on new server, while on old there is everything ok and cookies are set.
After few researches i found out that not only cookies not work but all sessions. I try to dump $_SEESION but it shows something only right after calling $this->Auth->setUser($user), and nowhere else. So i look through some solutions and find that there is a setting in config/app.php to set up the session:
'Session' => [
'defaults' => 'php',
],
And read that when set in that way the session is stored in default php dir. So i changed it to cake(even make a dir sessions in tmp folder and added 777 permissions). But the problem was not solved. I have no idea why it not work. I tried setting cookiePath and other settings i Session config, but it still not work.
I think that this may be the server problem(permissions). So few words about servers: Old server where everything was working was my private server(i have full access), new server(or maybe virtual server/host) is on one of hosting companies(home.pl) where i have almost no privileges to configure.
Make sure you follow these steps:
//For Set
var $var = array('Cookie');
//For Write
$this->Cookie->write('YOUR DESIRED NAME', cookieData, $expires = null);
//For Read
$this->Cookie->read('YOUR DESIRED NAME');
Check in your Conroller code should be in src/Controller/AppController.php for below points
1) have you loaded cookie component properly in initialize() or beforeFilter() method?
2) do you have configured domain and path in your cookie configuration using $this->Cookie->configKey(), if Yes, then change domain to new domain or remove domain configuration.
3) delete cache folders for model and persistence from tmp folder
For more information about Cookie refer Document
I am new to Slim Framework (PHP). I was going through tutorials and testing some code and tried the following:
$app=new App([
'mode'=>file_get_contents(INC_ROOT . '/mode.php')
]);
echo $app->config('mode');
The output was blank.
It seems the function config() works with V2, however I am using V3. What am I doing wrong?
Slim 3 no longer has a config method. Instead, you must add configuration settings through the dependency injection container:
$app = new \Slim\App([
'settings' => [
'mode' => true
]
]);
$container = $app->getContainer();
echo $container->get('settings')['mode'];
A few things worth noting:
Slim 3 no longer handles managing different versions of configuration settings through a mode setting. So, you can set a value for a setting variable called mode as I've demonstrated here, but it won't actually do anything (i.e., Slim won't use it to determine your environment).
As an alternative, you can check out userfrosting/Config, a library we've been working on that can search multiple directories and different environment configuration files, merging together their contents:
/path/to/config/default.php
return [
'contacts' => [
'housekeeper' => [
'name' => 'Alex',
'email' => 'alex#cleansthetoilet.com'
]
]
];
/path/to/config/production.php
return [
'contacts' => [
'housekeeper' => [
'email' => 'alex#istheboss.com'
]
],
'database' => [
'password' => 'sup3rC-cr3t'
]
];
index.php
$app = new \Slim\App();
$container = $app->getContainer();
// Site config object (separate from Slim settings)
$container['config'] = function ($c) {
// Create and inject new config item
$config = new \UserFrosting\Config\Config();
$config->setPaths([
'/path/to/config'
]);
$config->loadConfigurationFiles('production');
return $config;
};
This will recursively merge in the settings from development.php with those in default.php, updating settings with the same name and scope as necessary:
Running print_r($container['config']); returns:
[
'contacts' => [
'housekeeper' => [
'name' => 'Alex',
'email' => 'alex#istheboss.com'
]
],
'database' => [
'password' => 'sup3rC-cr3t'
]
]
Notice that the value of contacts.housekeeper.email has been updated to 'alex#istheboss.com', and that the database config info has been merged in. Incidentally, you can also access config settings using the more convenient "dot syntax":
$config = $container->get('config');
echo $config['contacts.housekeeper.email'];
// Easier to type instead of $config['contacts']['housekeeper']['email'];
We recommend injecting this as a separate config service in Slim, rather than using their settings array.
You can combine this with phpdotenv to load settings from your system environment, or any .env files you create:
/path/to/config/production.php
return [
'database' => [
'password' => getenv('DB_PASSWORD')
]
];