Laravel - How to set faker locale in phpunit tests? - laravel

I'm able to change faker locale in my application in config/app.php to pt_BR changing 'faker_locale' => 'pt_BR', and it works fine in my factories but not in my test cases. This is how im importing faker in my Tests:
namespace Tests\Unit;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use App\Models\Proprietario;
class ProprietarioTest extends TestCase
{
use WithFaker, RefreshDatabase;
public function testStore(){
$attributes = [
'name' => $this->faker->name,
'email' => $this->faker->email,
'address' => $this->faker->city,
'phone' => $this->faker->cellPhoneNumber,
'municipio' => $this->faker->randomDigit,
];
$response = $this->post('/api/v1/proprietario', $attributes);
$response->assertStatus(201);
$createdArea = Proprietario::latest();
$this->assertDatabaseHas('proprietarios', $attributes);
}
The test will fail in $this->faker->cellPhoneNumber because it's not available in default locale. I'm using Laravel 5.8 and PHP 7.2

The WithFaker trait gives you a method you can use
$this->faker('nl_NL')->postcode // dutch postcode
If you want to use it for all tests, overide the setupFaker in your test(s)
protected function setUpFaker()
{
$this->faker = $this->makeFaker('nl_NL');
}

Related

excel sheet validation in laravel

I using laravel excel Maatwebsite.
public function collection(Collection $rows)
{
Validator::make($rows->toArray(), [
'*.price' => 'numeric',
])->validate();
}
I need output
Excel Row No not array number
Row No 1.price must be a number.
as I understand you need to validate uploaded excel rows.
the package excel Maatwebsite provided validation rules feature too.
in your import class you need to add WithValidation, WithHeadingRow interface and rules mothod. in this way uploaded excel will be validated before insert into database:
namespace App\Imports;
use App\User;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Validators\Failure;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\SkipsFailures;
class UsersImport implements ToModel, WithValidation, WithHeadingRow,SkipsOnFailure
{
use Importable,SkipsFailures;
public function model(array $row)
{
return new User([
'name' => $row['name'],
'email' => $row['email'],
'password' => 'secret',
]);
}
public function rules(): array
{
return [
'email' => Rule::in(['patrick#maatwebsite.nl']),
// Above is alias for as it always validates in batches
'*.email' => Rule::in(['patrick#maatwebsite.nl']),
];
}
}
and to gather errors:
$import = new UsersImport();
$import->import('users.xlsx');
$failures= $import->failures() ;
foreach ($failures as $failure) {
$failure->row(); // row that went wrong
$failure->attribute(); // either heading key (if using heading row concern) or column index
$failure->errors(); // Actual error messages from Laravel validator
$failure->values(); // The values of the row that has failed.
}
now $failures contains all validation error in all rows
This example use interface Validator that take different arguments to initialize; (array $data, array $rules, array $messages, array $customAttributes) to validate rows and referenced from web sources, do not implement ToModel concern and is similar to the example showed in the question.
namespace App\Imports;
use App\User;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Concerns\ToCollection;
class UsersImport implements ToCollection
{
public function collection(Collection $rows)
{
Validator::make($rows->toArray(), [
'*.0' => 'required',
])->validate();
foreach ($rows as $row) {
User::create([
'name' => $row[0],
]);
}
}
}
Another scenario like defined a custom data or Excel file like the following, suppose you want to access specific cells, you can implement the WithMappedCells concern.
index
user
date
subscription
0
user
2022-12-08
true
1
user
2022-12-08
true
2
user
2022-12-08
false
3
user
2022-12-08
true
use App\User;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithMappedCells;
class UsersImport implements WithMappedCells, ToModel
{
public function mapping(): array
{
return [
'index' => 'B1',
'user' => 'B2',
'date' => 'B3',
'subscription' => 'B4',
];
}
public function model(array $row)
{
return new User([
'index' => $row['index'],
'user' => $row['user'],
'date' => $row['date'],
'subscription' => $row['subscription']
]);
}
}

How set uploaded avatar in this.$page.props.user with inertiajs?

In Laravel 8 app with inertiajs/inertia-vue 0.7/vuejs2 with fortify (but without jetstream)
I use "spatie/laravel-medialibrary": "^9.9" for avatar uploading like
$loggedUser = auth()->user();
$avatar_file_path = $avatarImageUploadedFile->getPathName();
$loggedUser->addMedia( $avatar_file_path )->toMediaCollection('avatar');
and it works, but in which way can I use avatar in on client part when I use
this.$page.props.user
in vue components properties to check which user is logged and show his info?
Thanks!
You can do this with the 'Shared data' feature via the HandleInertiaRequests middleware.
For example, to share user info you can do the following:
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
class HandleInertiaRequests extends Middleware
{
public function share(Request $request)
{
return array_merge(parent::share($request), [
'user' => function () {
return Auth::user() ? [
'id' => Auth::user()->id,
'name' => Auth::user()->name,
'email' => Auth::user()->email,
// get path to avatar
'avatar' => Storage::url('avatar-of-the-user.jpg'),
] : null;
},
]);
}
}
Client side you can then access the avatar's URL with this.$page.props.user.avatar.

Laravel Error: Object of class Torann\GeoIP\Location could not be converted to string

I am getting error on send Location Data To Database Using Laravel GeoIP::getLocation('2405:204:970a:d9b3:10a3:5280:9064:3f31'),
Error:
Object of class Torann\GeoIP\Location could not be converted to string
This Is My Auth LoginController. How to Insert GeoIP Loacation data into database. Please Help me
If i remove this code 'current_location' => GeoIP::getLocation('2405:204:970a:d9b3:10a3:5280:9064:3f31'), i am no longer getting this error, every data inserted into database but i add this code i am getting this error
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Jenssegers\Agent\Agent;
use Carbon\Carbon;
use App\User;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Closure;
use GeoIP;
use Location;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
function authenticated(Request $request, $user)
{
// Chrome, IE, Safari, Firefox, ...
$agent = new Agent();
$browser = $agent->browser();
// Ubuntu, Windows, OS X, ...
$platform = $agent->platform();
$user->update([
'last_signin' => Carbon::now()->toDateTimeString(),
'ip_address' => $request->getClientIp(),
'browser_login' => $agent->browser(),
'browser_version' => $agent->version($browser),
'device_login' => $agent->platform(),
'device_version' => $agent->version($platform),
'current_location' => GeoIP::getLocation('2405:204:970a:d9b3:10a3:5280:9064:3f31'),
'language' => $agent->languages(),
'root' => $agent->robot(),
'https' => $request->server('HTTP_USER_AGENT'),
]);
}
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest',['except'=>['logout', 'userLogout', 'profile']]);
}
public function userLogout()
{
Auth::guard('web')->logout();
return redirect('/');
}
}
Auth Route :
//User Auth Route Function
Auth::routes();
This is happending because GeoIP::getLocation('2405:204:970a:d9b3:10a3:5280:9064:3f31') returns an instance of Torann\GeoIP\Location and you are trying to save it as a String.
Checking the documentation of this object it has this shape:
\Torann\GeoIP\Location {
#attributes:array [
'ip' => '232.223.11.11',
'iso_code' => 'US',
'country' => 'United States',
'city' => 'New Haven',
'state' => 'CT',
'state_name' => 'Connecticut',
'postal_code' => '06510',
'lat' => 41.28,
'lon' => -72.88,
'timezone' => 'America/New_York',
'continent' => 'NA',
'currency' => 'USD',
'default' => false,
]
}
You have to choose a way to represent this location as a String, a possible way can be to save the latitude and the longitude separately.
If you need to use only one column at the DB, you can check some GeoHashing implementations skthon/geogash.
You Might be trying to use getLocation method from wrong instance.
1.) Try as below way :
"use Torann\GeoIP\GeoIPFacade as GeoIP"
$location = GeoIP::getLocation();
2.) Or try as Geoip package documentation suggest here (http://lyften.com/projects/laravel-geoip/doc/methods.html)
from this instance \Torann\GeoIP\GeoIP and then use geoip()->getLocation('27.974.399.65');
This seems to be an issue in the current_location field and how it is typed in your database. From what I read, I guess your field is defined a string, and when trying to save your record to the database, it fails since the data you're trying to save is an Location object.
I would recommend changing your current_location column in your database to make it a json type.
Then you'd be able to insert your data as:
$user->update([
'last_signin' => Carbon::now()->toDateTimeString(),
'ip_address' => $request->getClientIp(),
'browser_login' => $agent->browser(),
'browser_version' => $agent->version($browser),
'device_login' => $agent->platform(),
'device_version' => $agent->version($platform),
'current_location' => json_encode(GeoIP::getLocation('2405:204:970a:d9b3:10a3:5280:9064:3f31')->toArray()),
'language' => $agent->languages(),
'root' => $agent->robot(),
'https' => $request->server('HTTP_USER_AGENT'),
]);

laravel error Call to undefined method Illuminate\Hashing\BcryptHasher::driver()

I'm trying to test my laravel application, run phpunit, but get an error:
Error: Call to undefined method Illuminate\Hashing\BcryptHasher::driver()
laravel 5.5, PHPUnit 7.0
My UserTest:
namespace Tests\Feature;
use App\User;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class UserTest extends TestCase
{
use RefreshDatabase;
/** #test */
function name_should_not_be_too_long()
{
$response = $this->post('/users', [
'name' => str_repeat('a', 51),
'email' => $this->user->email,
'password' => 'secret',
]);
$response->assertStatus(302);
$response->assertSessionHasErrors([
'name' => 'The name may not be greater than 50 characters.'
]);
}
}
In your CreatesApplication class change this line:
Hash::driver('bcrypt')->setRounds(4);
To this:
Hash::setRounds(4);
After that, do a composer dumpautoload
If still no luck, downgrade to phpunit 6.0.

Using a php variable for validation in Laravel 4.2

I have this code that gets an object in a session and i put it in a certain variable. Then i wanted to use it in the laravel 4.2 'same' validation. So far here is the code i have
session_start();
$getsCapt = $_SESSION["captcha"];
$rules = array(
'st' => 'required',
'capt' => 'required|numeric|same:$getsCapt'
);
It is not doing anything. What i wanted to have is i'll compare the value i get from the session with the value i get from the textbox in my view named 'capt' but so far its not doing anything. any ideas to do this properly?
First of all, You are using same validator incorrectly.
same expects a form field name
Example:
same:field_name
Where, the given field must match the field under validation.
You could register and use a Custom Validation Rule
Validator::extend('captcha', function($attribute, $value, $parameters)
{
$captcha = \Session::get('captcha');
return $value == $captcha;
});
So later you can do:
//session_start(); - Please no need for this in Laravel
//$getsCapt = $_SESSION["captcha"]; - Also remove this not necessary
$rules = array(
'st' => 'required',
'capt' => 'required|numeric|captcha'
);
NB:
Use Session::put to save something to session e.g \Session::put('something');
There is also Session::get for retrieving value from session e.g \Session::get('something');
Please avoid using $_SESSION not Laravel way of doing things
[Edited] Where to Register Custom Validation Rule?
There are basically two ways you can register a custom validation rule in Laravel.
1. Resolving from a closure:
If you are resolving through closure you can add it to : app/start/global.php
Validator::extend('captcha', function($attribute, $value, $parameters)
{
$captcha = \Session::get('captcha');
return $value == $captcha;
});
2. Resolving from a class
This is the best and preferred way of extending custom validation rule as its more organised and easier to maintain.
i. Create your own validation class, CustomValidator.php, maybe in app/validation folder
<?php namespace App\Validation;
use Illuminate\Validation\Validator;
use Session;
class CustomValidator extends Validator{
public function validateCaptcha($attribute, $value, $parameters)
{
$captcha = Session::get('captcha');
return $value == $captcha;
}
}
NB: Notice the prefix validate used in the method name, validateCaptcha
ii. Create a Service Provider that will resolve custom validator extension in app/validation folder
<?php namespace App\Validation;
use Illuminate\Support\ServiceProvider;
class CustomValidationServiceProvider extends ServiceProvider {
public function register(){}
public function boot()
{
$this->app->validator->resolver(function($translator, $data, $rules, $messages){
return new CustomValidator($translator, $data, $rules, $messages);
});
}
}
iii. Then add CustomValidationServiceProvider under app/config/app.php providers array:
'providers' => array(
<!-- ... -->
'App\Validation\CustomValidationServiceProvider'
),
iv. And add the custom error message in app/lang/en/validation.php
return array(
...
"captcha" => "Invalid :attribute entered.",
...
)
Change single quotes to double quotes
$rules = array(
'st' => 'required',
'capt' => "required|numeric|same:$getsCapt"
);
Or simply concatenate the value
$rules = array(
'st' => 'required',
'capt' => 'required|numeric|same:' . $getsCapt
);

Resources