I am using Laravel 5.6.* . Now I created saparate route for sub domian and main domain. also create middleware for subdomain. But when I browse my site its get error with "Missing required parameters for [Route: something] [URI: something]"
My Route file
$domain = '{s_domain}.' . parse_url(config('app.url'), PHP_URL_HOST);
Route::group(['domain' => $domain, 'middleware' => 'subdomain'], function () {
Auth::routes();
Route::group(['namespace' => 'Clients', 'middleware' => 'auth'], function () {
Route::get('dashboard', 'ClientDashboardController#index')->name('home');
});
});
$maindomain = parse_url(config('app.url'), PHP_URL_HOST);
Route::group(['domain' => $maindomain], function () {
// My Route
});
My Subdomain Middlware file
public function handle($request, Closure $next)
{
$subdomain = $request->route()->s_domain;
$customer = Customer::where( 'sub_domain', $subdomain )->where('status', 'On')->first();
if( ! $customer ) {
return redirect()->route('customer.inactive');
} else {
Config::set('database.connections.subdomain.database', $customer->customer_database);
Config::set('database.default', 'subdomain');
\DB::purge('subdomain');
\DB::reconnect('subdomain');
}
return $next($request);
}
Related
I have developed an application using Laravvel-5.8.
I have developed the application for just a single company whereby each table have a company_id derived from the company table as shown below:
class Company extends Model
{
protected $table = 'companies';
protected $fillable = [
'id',
'company_name',
'subdomain',
];
}
class User extends Authenticatable
{
protected $fillable = [
'name',
'company_id',
'email',
];
}
and the route/web.php looks like this:
Route::get('/', ['as' => '/', 'uses' => 'IndexController#getLogin']);
Auth::routes();
Route::get('/dashboard', 'HomeController#index')->name('dashboard');
// Config Module
Route::group(['prefix' => 'config', 'as' => 'config.', 'namespace' => 'Config', 'middleware' => ['auth']], function () {
Route::resource('countries', 'ConfigCountriesController');
Route::resource('nationalities', 'ConfigNationalitiesController');
});
// HR Module
Route::group(['prefix' => 'hr', 'as' => 'hr.', 'namespace' => 'Hr', 'middleware' => ['auth']], function () {
Route::resource('designations', 'HrDesignationsController');
Route::resource('departments', 'HrDepartmentsController');
Route::resource('employee_categories', 'HrEmployeeCategoriesController');
});
The main route is :
Route::get('/', ['as' => '/', 'uses' => 'IndexController#getLogin']);
which gives localhost:8888/myapp
config/app.php:
'env' => env('APP_ENV', 'production'),
'url' => env('APP_URL', 'localhost:8888/myapp'),
'asset_url' => env('ASSET_URL', null),
I'm asked to add sub-domains where each will see the data based on the company_id in each table
localhost:8888/myapp
localhost:8888/company1.myapp
localhost:8888/company2.myapp
All will use:
Route::get('/', ['as' => '/', 'uses' => 'IndexController#getLogin']);
After successful login will redirect to:
Route::get('/dashboard', 'HomeController#index')->name('dashboard');
Also each will only see it's data based on company_id
companies table:
id | company_name | subdomain
1 | Main |
2 | Company1 | company1
3 | Company2 | company2
Main=> localhost:8888/myapp
Company1=>localhost:8888/company1.myapp
Company2=>localhost:8888/company2.myapp
How do I modify:
route/web.php
config/app.php
to achieve this?
Thanks
There are two methods by which It can be done.
By Middleware
As per your question, login page urls can be localhost:8888/myapp, localhost:8888/company1.myapp, or localhost:8888/company2.myapp
Using middleware, we will keep the company name in the session using middleware. You can use it from session.
php artisan make:middleware VerifyDomain
will create a domain
<?php
namespace App\Http\Middleware;
use Closure;
class VerifyDomain
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$domain == "myapp"; // your company app name
$path = $request->getPathInfo(); // should return /company1.myapp or /company2.myapp or /myapp
if (strpos($path, ".") !== false) { // if path has dot.
list($subdomain, $main) = explode('.', $path);
if(strcmp($domain, $main) !== 0){
abort(404); // if domain is not myapp then throw 404 page error
}
} else{
if(strcmp($domain, $path) !== 0){
abort(404); // if domain is not myapp then throw 404 page error
}
$subdomain = ""; // considering for main domain value is empty string.
}
$company = Company::where('company_name', $subdomain)->firstOrFail(); // if not found then will throw 404
$request->session()->put('company_name', $company); //store it in session
return $next($request);
}
}
Then add it to route middleware.
In your controller you can redirect to different dashboards as per the company names stored in session.
In route groups
Route::domain('localhost:8888/myapp')->group(function () {
Route::get('/', function ($id) {
//
});
});
Route::domain('localhost:8888/{company_name}.myapp')->group(function () {
Route::get('/', function ($company_name, $id) {
$company = Company::where('company_name', $company_name)->firstOrFail();
// send the value of $company to data to send different view data
});
});
In my Laravel-5.8 application, I have a multi-company application using a single database. Each table have a company_id derived from the company table as shown below:
id | company_name | subdomain
1 | Main |
2 | Company1 | company1
3 | Company2 | company2
Main=> localhost:8888/myapp
Company1=>localhost:8888/company1.myapp
Company2=>localhost:8888/company2.myapp
I created a middleware:
class VerifyDomain
{
public function handle($request, Closure $next)
{
$domain == "myapp"; // your company app name
$path = $request->getPathInfo(); // should return /company1.myapp or /company2.myapp or /myapp
if (strpos($path, ".") !== false) { // if path has dot.
list($subdomain, $main) = explode('.', $path);
if(strcmp($domain, $main) !== 0){
abort(404); // if domain is not myapp then throw 404 page error
}
} else{
if(strcmp($domain, $path) !== 0){
abort(404); // if domain is not myapp then throw 404 page error
}
$subdomain = ""; // considering for main domain value is empty string.
}
$company = Company::where('subdomain', $subdomain)->firstOrFail(); // if not found then will throw 404
$request->session()->put('subdomain', $company); //store it in session
return $next($request);
}
}
Already, I have two (2) route groups in the route/web.php wgich looks like this:
Route::get('/', ['as' => '/', 'uses' => 'IndexController#getLogin']);
Auth::routes();
Route::get('/dashboard', 'HomeController#index')->name('dashboard');
// Config Module
Route::group(['prefix' => 'config', 'as' => 'config.', 'namespace' => 'Config', 'middleware' => ['auth']], function () {
Route::resource('countries', 'ConfigCountriesController');
Route::resource('nationalities', 'ConfigNationalitiesController');
});
// HR Module
Route::group(['prefix' => 'hr', 'as' => 'hr.', 'namespace' => 'Hr', 'middleware' => ['auth']], function () {
Route::resource('designations', 'HrDesignationsController');
Route::resource('departments', 'HrDepartmentsController');
Route::resource('employee_categories', 'HrEmployeeCategoriesController');
});
I have 2 issues:
If subdomain field is null, then the route should be for main domain: Main=> localhost:8888/myapp else localhost:8888/company1.myapp or localhost:8888/company2.myapp
2.How do I accomodate the route groups above into this:
Route::domain('localhost:8888/myapp')->group(function () {
Route::get('/', function ($id) {
//
});
});
Route::domain('localhost:8888/{subdomain}.myapp')->group(function () {
Route::get('/', function ($company_name, $id) {
$company = Company::where('subdomain', $subdomain)->firstOrFail();
// send the value of $company to data to send different view data
});
});
I'm not really sure that i understand you clearly. But, I hope you'll understand me :)
First thing is you're "domain". I suppose it's not real domain, but just uri. And maybe you should use it something like that:
Auth::routes();
$defaultDomain = config('myconfig.default_domain_name', 'myapp');
// I'm not reccomend to you use localhost:8888 here.
Route::domain('localhost:8888')
->group([
'middleware' => ['veryfy_domain'] // Add your VerifyDomain Middleware here
], function () {
// Here you already have a 'subdomain' param in session
// If you need special logic for default domain, you can out it here
Route::group(['prefix' => '/' . $defaultDomain], function () {
Route::get('/', function ($id) {
//
});
});
// Code below will work only with companies.
Route::group(['prefix' => '/{test}.' . $defaultDomain], function () {
Route::get('/', ['as' => '/', 'uses' => 'IndexController#getLogin']);
Route::get('/dashboard', 'HomeController#index')->name('dashboard');
// Config Module
Route::group(['prefix' => 'config', 'as' => 'config.', 'namespace' => 'Config', 'middleware' => ['auth']], function () {
Route::resource('countries', 'ConfigCountriesController');
Route::resource('nationalities', 'ConfigNationalitiesController');
});
// HR Module
Route::group(['prefix' => 'hr', 'as' => 'hr.', 'namespace' => 'Hr', 'middleware' => ['auth']], function () {
Route::resource('designations', 'HrDesignationsController');
Route::resource('departments', 'HrDepartmentsController');
Route::resource('employee_categories', 'HrEmployeeCategoriesController');
});
});
});
And about your middleware. I see it smth like that:
class VerifyDomain
{
public function handle($request, Closure $next)
{
$request->get('domain_name', $this->getBaseDomain());
$company = Company::where('subdomain', $subdomain)->firstOrFail();
$request->session()->put('subdomain', $company);
return $next($request);
}
// Better to store it in config
protected function getBaseDomain()
{
return config('myconfig.default_domain_name', 'myapp');
}
}
If you really want to use different domains, I think you need in your nginx something like this:
server_name *.myapp myapp;
And of course in your hosts file.
Than you can check it like that:
http://company.myapp
http://company1.myapp
http://myapp
Config example:
Create new file your_project_dir/app/config/myconfig.php (name it as you want)
Put this code in the file:
return [
'default_domain_name' => 'myapp'
];
Now you can use in in youre code as i suggest:
config('myconfig.default_domain_name');
I have in my web.php the following routes:
Route::get('admin', ['as' => 'admin.login', 'uses' => 'AdminController#login']);
Route::post('admin', ['as' => 'admin.postLogin', 'uses' => 'AdminController#postLogin']);
Route::group(['middleware' => 'isAdmin'], function () {
// problem is when I redirect to the following route
Route::get('admin/transactions', ['as' => 'admin.transactions', 'uses' => 'AdminController#transactions']);
});
and my controller as follow:
public function postLogin(Request $request){
//some logic
return Redirect::to('admin/transactions');
}
and the transaction action:
public function transactions(){
dd('ok');
}
but I still get Resource not found!! why?
Can anybody help me?
Note!!: I have other routes working fine so I don't think it's an .htaccess problem
EDIT!!
here is my middleware:
public function handle($request, Closure $next)
{
if (!Auth::check() || !Auth::user()->admin) {
return Redirect::to('/');
}
return $next($request);
}
Maybe use Route::middleware?
Route::middleware(['isAdmin'])->group(function () {
Route::get('admin/transactions', 'AdminController#transactions');
});
I use auth:api middleware in controller (Laravel 5.2).
class RestfulController extends Controller
{
public function __construct() {
$this->middleware(['api', 'auth:api'], ['except' => ['login'] ]);
}
}
routes:
Route::group(['prefix' => 'api'], function () {
Route::get('/login', ['uses' => 'RestfulController#login', 'as'=>'login']);
Route::get('/list', ['uses' => 'RestfulController#list', 'as'=>'list']);
});
If request doesn't contain or contains invalid api_token framework redirects to login page. Instead I would like to return JSON response with error. How it can be implemented?
change app/Http/Middleware/Authenticate.php handle method,it will response json
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
$response = [
'status' => 'error',
'message' => 'This is error message'
];
return Response::json($response);
}
}
return $next($request);
}
You should check api and auth:api middleware group and look for witch one is doing it. If it's inside a vendor package, you'll need to extend it and make your changes.
I'm using laravel 5.1 and the modular package.
In my controller I use the following login method:
public function postLogin(Request $request)
{
$email = $request->input('email');
$password = $request->input('password');
if (Auth::attempt(['email' => $email, 'password' => $password])) {
return redirect()->intended('admin/dashboard');
}
return redirect('/login')->withErrors([
'email' => 'These credentials do not match our records.']);
}
My route:
Route::group(array('module' => 'Admin', 'namespace' => 'App\Modules\Admin\Controllers'), function() {
Route::get('admin/dashboard', [
'middleware' => 'auth',
'uses' => 'AdminController#index'
]);
}}
My controller:
public function index()
{
return view("Admin::index");
}
My Middleware/Authenticate:
public function handle($request, Closure $next)
{
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('auth/login');
}
}
return $next($request);
}
This works and redirects me to the index view after login.
When the user is not logged in, it is still possible to access the index view by accessing the url: localhost/admin/dashboard.
How can I redirect the user to a custom page which shows an error to the user that it is not possible to access the url localhost/admin/dashboard when he is not logged in?
Any ideas? Thank you
The issue is with your route the middleware should be at the top level as soon as you hit the controller it should redirect if not authenticated
Route::group(['middleware'=>'auth','module' => 'Admin', 'namespace' => 'App\Modules\Admin\Controllers'], function()
{
Route::get('admin/dashboard', ['uses' => 'AdminController#index']);
});
secondly if you want to redirect user to a custom page you can do this
public function redirectUnAuthenticateUser()
{
\Session::flash('login_error', 'Kindly login before you can access this page');
//create a view that user would be redirected to
return view('session.unauthenticated') ;
}
and the change your auth function to below
public function handle($request, Closure $next)
{
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->route('you-custom-rout-name-matching-above-function');
}
}
return $next($request);
}
and on your view you can get the value of the flash message