I am new to Laravel and I am having an issue to write a test function that asserts that the HTTP response of my welcome page is 200 knowing that I have EN and FR locales defined, meaning that the test should test both localhost:8000/en and localhost:8000/fr.
This is my exampletest.php:
<?php
namespace Tests\Feature;
use App\Http\Middleware\SetLanguage;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*
* #return void
*/
public function testBasicTest()
{
$response = $this->get('/');
$response->assertStatus(301);
}
public function test_getRedirected_DefaultedEnglish_WelcomePage()
{
$response = $this->get('/en');
$response->assertStatus(200);
}
public function test_getRedirected_French_WelcomePage()
{
$response = $this->get('/fr');
$response->assertStatus(200);
}
}
I don't like writing the code twice for both /en and /fr.
This is my web.php:
<?php
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
Route::redirect('/', 'en', 301);
Route::group(['prefix' => '{lang}', 'where' => ['lang' => '[a-zA-Z]{2}'], 'middleware' => 'setlanguage'], function() {
Auth::routes();
Route::get('/','App\Http\Controllers\welcomeController#index')->name('welcome');
});
And i have written my localization middleware below:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
class SetLanguage
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
App::setLocale($request->lang);
return $next($request);
}
}
I would appreciate your help on the above. I believe the test should be dynamic.
Thank you in advance..
I don't think there's any way around repeating yourself if you want to test multiple locales. But there's no requirement to put each test in a separate method. This may work, but I've never done testing on multiple locales in my applications.
public function provideLocales(): array
{
return [
"english" => ["en"],
"francais" => ["fr"],
];
}
/**
* #dataProvider provideLocales
*/
public function testWelcomePage($locale): void
{
$this->app->setLocale($locale);
$this->get(route("welcome"))
->assertStatus(200);
}
You could take this further and actually check that the localized content is being served correctly.
public function provideLocales(): array
{
return [
"english" => ["en", "welcome"],
"francais" => ["fr", "bienvenue"],
];
}
/**
* #dataProvider provideLocales
*/
public function testWelcomePageContents($locale, $text): void
{
$this->app->setLocale($locale);
$this->get(route("welcome"))
->assertStatus(200)
->assertSeeText($text);
}
Related
I'm trying to run some middleware on my routes via my package's service provider before the routes run in my Laravel project but I'm not seeing my var_dump despite running php artisan route:list showing that the BeforeMiddleware is applied. Am I using the wrong middleware?
My service provider:
<?php
namespace Company\FudgeInboundManagementBridge;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;
use Company\FudgeInboundManagementBridge\Http\Middleware\BeforeMiddleware;
class FudgeInboundManagementBridgeServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
$this->registerFiles();
}
/**
* Register files
*/
protected function registerFiles(): void
{
Route::middleware(BeforeMiddleware::class)->group(function () {
$this->loadRoutesFrom(__DIR__.'/routes/fudge-routes.php');
});
$this->publishes([
__DIR__ . '/config/FudgeInboundManagementBridge.php' => config_path('FudgeInboundManagementBridge.php'),
], 'config');
}
}
My middleware:
<?php
namespace Company\FudgeInboundManagementBridge\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class BeforeMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
var_dump('hello from before middleware - bridge');
die;
// return $next($request);
}
}
Seems like it's not triggering?
How to call a method, function or initialize class after an middleware in a controller constructor in Laravel and Lumen?
I try initialize class Translator after middleware('lang'), but class Translator initialized before execute middleware('lang').
Controllers/IndexController.php
<?php
namespace App\Http\Controllers;
use Laravel\Lumen\Routing\Controller;
use App\Helpers\Translator;
class IndexController extends Controller
{
private $transhome;
public function __construct()
{
$this->middleware('lang');
$this->transhome = new Translator('home');
}
public function home()
{
return view('home', [
'transhome' => $this->transhome,
]);
}
}
Middleware/LangMiddleware.php
use Closure;
class LangMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
config(['app.lang' => 'fr']);
return $next($request);
}
}
Another example
After execution we will see: 132
$this->middleware('lang'); the last will be called
Controllers/IndexController.php
<?php
namespace App\Http\Controllers;
use Laravel\Lumen\Routing\Controller;
class IndexController extends Controller
{
public function __construct()
{
echo '1';
$this->middleware('lang');
echo '3';
}
public function home()
{
return view('home');
}
}
Middleware/LangMiddleware.php
use Closure;
class LangMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
echo '2';
return $next($request);
}
}
Actually, this should work because you have the $transhome as private above. Try this with public.
It should work because in the constructor you tell it to set it to a translator.
Have you ever looked with dd() if transhome returns null?
I have a middleware which just grabs the sub domain and binds it to the Store model.
<?php
namespace App\Http\Middleware;
use Closure;
use App\Models\Store;
class SubDomain
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
$sub_domain = array_first(explode('.', $request->getHost()));
app()->bind(Store::class, function () use ($sub_domain) {
return Store::query()->where('sub_domain', $sub_domain)->firstOrFail();
});
return $next($request);
}
}
However, when I am inside of a controller I am trying to extend it so I can always do $this->store->id or something alike however, the Store isn't getting found.
<?php
namespace App\Http\Controllers;
use App\Models\Store;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
/**
* #var Store
*/
protected $store;
/**
* Controller constructor.
*
* #param Store $store
*/
public function __construct(Store $store)
{
$this->store = $store;
}
}
The store is always just a basic model with no data.
This is my route:
Route::group(['middleware' => ['auth', 'sub_domain'], 'prefix' => 'admin'], function () {
Route::get('/dashboard', 'Admin\DashboardController#index');
});
And I have registered the sub_domain middleware inside of the Kernel.
The service container and model do not work how you are expecting in your code. So try with the following code snippet inside the controller's method. You may get what you are looking for.
$store = app(Store::class);
dd($store);
You want to bind an instance of a model so use app()->instance(Store::class, $store)
ref: https://laravel.com/docs/5.7/container#binding
I followed this article on how to make your site multi language.
But I don't understand why I always get an error when I surf to hoemstead.app/lang/en for example.
The error:
Sorry, the page that you're looking for does not exist
My LanguageController
use Config;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Session;
class LanguageController extends Controller
{
public function switchLang($lang)
{
if (array_key_exists($lang, Config::get('languages'))) {
Session::put('applocale', $lang);
}
return Redirect::back();
}
}
My routes:
Route::get('lang/{lang}', ['as'=>'lang.switch', 'uses'=>'LanguageController#switchLang']);
My Language Middleware
use Closure;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Session;
class Language
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Session::has('applocale') AND array_key_exists(Session::get('applocale'), Config::get('languages'))) {
App::setLocale(Session::get('applocale'));
}
return $next($request);
}
}
I've also added this middleware to my Kernel.php file
My Languages.php file in the config folder
return [
'en' => 'English',
'nl' => 'Nederlands',
'fr' => 'Français',
];
I am new in laravel 5. I have a dashboard page and a login page. whenever I go to localhost:8080/dashboard it always redirect me to localhost:8080/auth/login.
I wanted to show my dashboard localhost:8080/dashboard to be viewed without logging in first. Here is my code in VerifyCsfrToken
namespace App\Http\Middleware;
use Closure;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
class VerifyCsrfToken extends BaseVerifier {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
protected $except_urls = [
'dashboard/dashboard',
];
public function handle($request, Closure $next)
{
$regex = '#' . implode('|', $this->except_urls) . '#';
if ($this->isReading($request) || $this->tokensMatch($request) || preg_match($regex, $request->path()))
{
return $this->addCookieToResponse($request, $next($request));
}
throw new TokenMismatchException;
return parent::handle($request, $next);
}
}
routes.php
Route::get('dashboard', 'ReservationController#index');
Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);
controller :
use App\reservations;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Console\Scheduling\Schedule;
use Carbon\Carbon;
use Request;
class ReservationController extends Controller {
/*
|--------------------------------------------------------------------------
| Welcome Controller
|--------------------------------------------------------------------------
|
| This controller renders the "marketing page" for the application and
| is configured to only allow guests. Like most of the other sample
| controllers, you are free to modify or remove it as you desire.
|
*/
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application welcome screen to the user.
*
* #return Response
*/
public function schedule()
{
$schedules = schedules::all();
return view('calendar.schedule',compact('schedules'));
}
public function index()
{
return view('dashboard.dashboard');
}
public function create()
{
return view('reserve.reserve');
}
public function update()
{
return view('calendar.update');
}
public function login()
{
return view('login');
}
public function store(Requests\CreateReservationRequest $request)
{
$input = Request::all();
$reservation = new reservations(['user_id' => '13100024',
'status_id' => '1',
'room_id' => $input['room'],
'purpose' => $input['purpose'],
'start_time' => $input['date']." ".$input['hour1'].":".$input['minute1'].":00",
'end_time' => $input['date']." ".$input['hour2'].":".$input['minute2'].":00",
'add_date' => Carbon::now()
]);
$reservation->save();
return "success";
// return redirect('schedule');
}
This is what causes the issue:
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
It restricts access to the page to logged in users. Just remove it from your controller and users will be able to access the page whether they're logged in or not.
public function __construct()
{
$this->middleware('auth', ['except' => ['Whatever You want to Bypass']]);
}