Laravel validator's equivalent of isset() - laravel

In my FormRequest I need to validate, if selected category is actually present in the categories array.
I solved my problem with withValidator method, where I manually check if the category is present.
However, I feel like there must be a nicer way of doing this. I went over validation documentation, but could not find my fit.
Has anyone tackled this problem, or do you have an idea how to do this better?
Thank you.
class StoreWarehouseItemRequest extends FormRequest
{
public function rules()
{
return [
'name' => 'required',
'category' => 'required|integer',
'specification' => 'nullable|string',
'recipient' => 'nullable|string',
'unit' => 'nullable|string',
'sellers_code' => 'nullable|string',
'note' => 'nullable|string',
];
}
public function withValidator(Validator $validator)
{
$cat = $validator->getData()['category'];
$cats = WarehouseItem::CATEGORIES;
$validator->after(
function ($validator) use ($cat, $cats) {
if (!isset($cats[$cat])) {
$validator->errors()->add('category', 'Kategória musí byť vybraná zo zoznamu.');
}
}
);
}
}

You could use Laravel's in:foo,bar validator.
return [
'name' => 'required',
'category' => ['required', 'integer', Rule::in(WarehouseItem::CATEGORIES)],
'specification' => 'nullable|string',
'recipient' => 'nullable|string',
'unit' => 'nullable|string',
'sellers_code' => 'nullable|string',
'note' => 'nullable|string',
];
Additionally, if you are looking if the key exists in the WarehouseItem::CATEGORIES array, you can do array_flip(WarehouseItem::CATEGORIES) on it.

Related

Laravel Livewire Mixed Content error in production

I deployed a Laravel-Livewire on Digital Ocean and now I'm having a Mixed content problem when I try to upload a file.
Here is the error:
UploadManager.js:131 Mixed Content: The page at 'https://intake.freejiji.ca/clients/3/extensions' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://intake.freejiji.ca/livewire/upload-file?expires=1625251608&signature=9d98c598db4f6fccc01c009bcfc3051c6a97b56f4058f4d9489a8d30d6d497c2'. This request has been blocked; the content must be served over HTTPS.
The error happens when after I click "Select File" and chose the .csv file I want. Since I'mdoing this on a livewire component I'm not sure how to fix this so that the request goes over HTTPS instead of HTTP.
I was able to fix similar problems on the app by changing "asset()" with "secure_asset()"
and "route()" with "secure_url()" but in this case I'm not sure what to do.
Here is the whole "Import" component:
<?php
namespace App\Http\Livewire\Modals;
use Validator;
use Livewire\Component;
use App\Http\Traits\Csv;
use App\Models\AccountUser;
use Livewire\WithFileUploads;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\Auth;
class ImportExtensions extends Component
{
use WithFileUploads;
public $clientID;
public $showModal = false;
public $upload;
public $columns;
public $fieldColumnMap = [
'first_name' => '',
'last_name' => '',
'email' => '',
'password' => '',
'extension' => '',
'user_type' => '',
];
protected $rules = [
'fieldColumnMap.first_name' => 'required|max:255',
'fieldColumnMap.last_name' => 'required|max:255',
'fieldColumnMap.email' => 'required|max:255',
'fieldColumnMap.password' => 'required|max:255',
'fieldColumnMap.extension' => 'required|max:255',
'fieldColumnMap.user_type' => 'required|max:255',
];
protected $validationAttributes = [
'fieldColumnMap.first_name' => 'First Name',
'fieldColumnMap.last_name' => 'Last Name',
'fieldColumnMap.email' => 'Email',
'fieldColumnMap.password' => 'Password',
'fieldColumnMap.extension' => 'Extension',
'fieldColumnMap.user_type' => 'User Type',
];
public function updatingUpload($value)
{
Validator::make(
['upload' => $value],
['upload' => 'required|mimes:csv'],
)->validate();
}
public function updatedUpload()
{
$this->columns = Csv::from($this->upload)->columns();
$this->guessWhichColumnsMapToWhichFields();
}
public function import()
{
// Validate that you are importing any data
$this->validate();
$importCount = 0;
Csv::from($this->upload)
->eachRow( function ($row) use (&$importCount){
$eachRow = $this->extractFieldsFromRow($row);
// Validate each Row of the csv file
$validatedData = Validator::make([
'first_name' => $eachRow['first_name'],
'last_name' => $eachRow['last_name'],
'email' => $eachRow['email'],
'password' => $eachRow['password'],
'extension' => $eachRow['extension'],
'user_type' => $eachRow['user_type'],
],[
'first_name' => 'required',
'last_name' => 'required',
'password' => 'required|max:255',
'user_type' => 'required|in:user,admin',
'email' => 'required|email|unique:account_users',
'extension' => ['required', 'numeric', Rule::unique('account_users', 'extension')
->where(function($query)
{return $query->where("account_id", $this->clientID);
})],
],);
if($validatedData->fails()){
$this->notify(['error','Oops something went wrong!']);
}else{
AccountUser::create([
'user_id' => Auth::user()->id,
'account_id' => $this->clientID,
'first_name' => $eachRow['first_name'],
'last_name' => $eachRow['last_name'],
'email' => $eachRow['email'],
'password' => $eachRow['password'],
'extension' => $eachRow['extension'],
'user_type' => $eachRow['user_type'],
]);
$importCount++;
}
});
$this->reset();
$this->emit('refreshExtensions');
if($importCount!=0) $this->notify(['success','Successfully Imported '.$importCount.' Extensions']);
}
public function guessWhichColumnsMapToWhichFields()
{
$guesses = [
'first_name' => ['first_name', 'name'],
'last_name' => ['last_name'],
'email' => ['email'],
'password' => ['password', 'pass'],
'extension' => ['extension', 'ext'],
'user_type' => ['user_type', 'user', 'type'],
];
foreach ($this->columns as $column) {
$match = collect($guesses)->search(fn($options) => in_array(strtolower($column), $options));
if ($match) $this->fieldColumnMap[$match] = $column;
}
}
public function extractFieldsFromRow($row)
{
$attributes = collect($this->fieldColumnMap)
->filter()
->mapWithKeys(function($heading, $field) use ($row) {
return [$field => $row[$heading]];
})
->toArray();
return $attributes;
}
public function downloadTemplate()
{
$filename = 'extensions_template.xls';
$path = public_path('files/' . $filename);
return response()->download($path, $filename, [
'Content-Type' => 'application/vnd.ms-excel',
'Content-Disposition' => 'inline; filename="' . $filename . '"'
]);
}
}
If you get mixed content problem it is mostly about you fetching the assets or resources from different http scheme. Here you are using HTTP to fetch data in HTTPS site. Change all the links to have HTTPS link.
If you want to force all the routes to use https you can achieve this by using following code.
if(env('APP_ENV', 'production') == 'production') { // use https only if env is production
\URL::forceScheme('https')
}
The above should solve your problem as all contents now will load from https.

Laravel Validation of two combined columns

i am new to Laravel i need some help in validation. i have two fields one is for country code and other is for phone number and they are being stored separately in respective column in database. i want to validate phone number as unique what i want is get phone number (1234567) country_Code(+12) join them as one like (+121234567) and then validate(unique) against db columns country_Code(+12) + phone(1234567). how can i achieve this?
here is my validation rules method for custom form request
public function rules()
{
return [
'first_name' => 'required|string',
'last_name' => 'required|string',
'email' => ['required', Rule::unique('clients')->ignore($this->client)],
'country_code' => 'required',
'phone' => ['required',Rule::unique('clients')->ignore($this->client)],
'receive_video_lessons' => 'required|boolean'
];
}
You could use a custom rule. Try something like this:
public function rules()
{
return [
'first_name' => ['required', 'string'],
'last_name' => ['required', 'string'],
'email' => ['required', Rule::unique('clients')->ignore($this->client)],
'country_code' => ['required'],
'phone' => ['required', new IsValidPhoneNumber($this->country_code, $this->client)],
'receive_video_lessons' => 'required|boolean'
];
}
Then in your custom validation rule:
class IsValidPhoneNumber implements Rule
{
protected $countryCode;
protected $clientId;
public function __construct($countryCode, $clientId)
{
$this->countryCode = $countryCode;
$this->clientId = $clientId;
}
public function passes($attribute, $value)
{
return ! Client::where('country_code', $this->countryCode)
->where('phone', $value)
->where('client_id', '!=', $this->clientId)
->exists();
}
public function message()
{
return 'This :attribute is not valid.';
}
}
You might have to massage it to work but you get the idea.

Validation : Laravel

In ContactsRequest.php
public function rules()
{
return [
'org_id' => 'required',
'name' => 'required',
'office' => 'required',
'mobile' => 'required_without:home',
'home' => 'required_without:mobile'
];
}
So basically what i want is , i have a form which will be taking the attributes specified in the code. But i want to modify code so that entering either one of 'home' or 'mobile' will allow me to create the new user.
What should be done.Any help would be appreciated

update function is not working

I am trying to update my database for a user by this code , but it is not working . there is no change by the way!
public function update( Request $request)
{
$request->user()->tasks()->where('id', '=', $request->id)->update([
'name' => $request->title,
'body' => $request->body,
]);
return redirect('/request');
}
Try code and update database:
App\User::find($request->id)->tasks()->update([
'name' => $request->title,
'body' => $request->body
]);
return redirect('/request');
If you already know the id of the task, make it easy on yourself.
Task::find($request->id)->update([
'name' => $request->title,
'body' => $request->body
]);

How can I maintain foreign keys when seeding database with Faker?

Below is my model factory.
$factory->define(App\Business::class, function (Faker\Generator $faker){
return [
'name' => $faker->bs,
'slug' => $faker->slug,
'address' => $faker->streetAddress,
'phone_no' => $faker->phoneNumber,
'mobile_no' => $faker->phoneNumber,
'email' => $faker->companyEmail,
'website' => $faker->domainName,
'latitude' => $faker->latitude,
'longitude' => $faker->longitude,
'location' => $faker->city,
'business_days_from' => $faker->dayOfWeek,
'business_days_to' => $faker->dayOfWeek,
'description' => $faker->text,
'user_id' => $faker->factory(App\User::class),
];
});
and This my database seeder class
class DatabaseSeeder extends Seeder
{
public function run()
{
factory(App\Business::class, 300)->create();
}
}
But when I execute php artisan db:seed ...it does not work..
What should be the workaround here..any help would be appreciated..
you can get all ids using pluck (lists is depricated for laravel >= 5.2)
$userIds = User::all()->pluck('id')->toArray();
and get a random id for FK column:
'user_id' => $faker->randomElement($userIds)
You may also attach relationships to models using Closure attributes in your factory definitions.
'title' => $faker->title,
'content' => $faker->paragraph,
'user_id' => function () {
return factory(App\User::class)->create()->id;
}
I just found the workaround .. I replaced
'user_id' => $faker->factory(App\User::class),
with
'user_id' => $faker->randomElement(User::lists('id')->toArray()),
and that solves the problem for now..

Resources