Laravel unique validation must include appended text when validating - laravel

I am using the Laravel tenancy package in which there is a domains table in my database and each value in the domain column within this table is appended with .test.co.uk.
When the user enters the URL in the form, they are presented with an input element (shown above) in which they enter a URL/Domain but the .test.co.uk is already appended so the only thing they need to enter is the text that goes before that, e.g. they would enter johnsmith and in the domain column it would store johnsmith.test.co.uk. The problem I have is that I need the validation on this column to be unique but also include the .test.co.uk when performing the validation so that it looks at the value stored in the table because if a user enters johnsmith and there is currently a record in the domains table where the value is johnsmith.test.co.uk then the validation would pass but I need the validation to fail in this scenario. I am currently using a Request class which is extending the FormRequest class and have this:
public function rules()
{
return [
'url' => 'required|string|unique:domains,domain',
];
}
I have also tried a rule object but I don't think a rule object is the correct solution to this problem. Is there a convenient "Laravel" way of doing this?

In your Request class use prepareForValidation()
Docs: https://laravel.com/docs/7.x/validation#prepare-input-for-validation
protected function prepareForValidation()
{
$this->merge([
'url' => $this->url . '.test.co.uk',
]);
}

Related

How to specify a default value for a field Laravel Nova

I want to set the default value of a resource field to the authenticated user's id. I have a model called Note which has a one to many relationship with Game and User.
User hasMany Note
Game hasMany Note
Note belongsTo User
Note belongsTo Game
In Laravel Nova my fields looks like this for the note
ID::make()->sortable(),
Text::make('Note', 'note')->onlyOnIndex(),
Textarea::make('Note', 'note')->alwaysShow(),
BelongsTo::make('Game', 'game')->hideWhenCreating()->hideWhenUpdating(),
BelongsTo::make('Created By', 'user', 'App\Nova\User')->hideWhenCreating()->hideWhenUpdating(),
DateTime::make('Created At', 'created_at')->hideWhenCreating(),
DateTime::make('Updated At', 'updated_at')->hideWhenCreating(),
Because I am referencing the Note on the Game Nova resource, when I create a Note, the game_id column is populated correctly. But, I want the user_id column to be the value of the authenticated user. It does not seem to work like this, how would I accomplish it?
If I understand correctly from the line BelongsTo::make('Created By', 'user', 'App\Nova\User')->hideWhenCreating()->hideWhenUpdating() you're trying to set a default value for the column without showing the field on the form?
I don't think this is possible in this way. As soon as you use the hide functions the fields aren't rendered and will never be passed along with the request. I tried this, and the user_id field was never sent with the request.
I think there are two ways to do this:
Show the field in the form and set the default value using the metadata (and perhaps making the field read-only for good measure).
BelongsTo::make('Created By', 'user', 'App\Nova\User')->withMeta([
"belongsToId" => auth()->user()->id,
])
See this part of the Nova docs
Or use the Eloquent creating event. The following will go in your Note model.
public static function boot()
{
parent::boot();
static::creating(function($note)
{
$note->user_id = auth()->user()->id;
});
}
Granted, the above method is a bit simple. You'd be better off using proper event listeners.
Sidenote: from an architectural point of view, I'd go with option 2. Setting a default value without getting the end-user involved sounds like a job for the Eloquent model, not for a Nova form.
You can use a method resolveUsing(). An example
<?php
//...
Select::make('My Select', 'my_custom_name')
->options(['a' => 'a', 'b' => 'b', 'c' => 'c'])
->resolveUsing(function ($value, $resource, $attribute) {
// $value = model attribute value
// $attribute = 'my_custom_name'
return 'b';
});

yii2 validate only one input field

In my model (In yii2 project) I have two columns called product and code. And the issue is how to validate only code not product. We know that $model->validate() validates entire model. But I need only one input field: code. Is it possible??
More clearly, In my input form I'm using 3 models. How to validate these 3 models in my controller. That's why I'm trying to validate fields of each model separalety? I meant to validate like:
$model->validate(someField)
$anotherModel->(anotherField)
Is this possible??
You can replace this function with model. also show what you have tried so far?
public function rules()
{
return [
[['code', ], 'required'],
];
}
You can use scenario approach in validations rules, and validate only needed fields, by passing appropriate scenario.
More info about scenarios:
http://www.yiiframework.com/doc-2.0/guide-structure-models.html

Laravel(5.3.24+) Validation: Validate 2 columns

Using the new style of laravel validation seen here: https://laravel-news.com/unique-and-exists-validation
I would like the name column to be required & only unique for a competition.
Using the example table below,
id 3: The validation should stop this from happening, because "a name already exist for that competition".
Custom rule
The best solution would be to create a custom rule for this, that accepts the field with the corresponding competition_id as a parameter.
Something like
//Calling the custom rule like this
['name' => 'required|validateName:yourCompetitionIdFormFieldHere'];
Declaring the custom validation function in your service provider like this
Validator::extend('validateName', function ($attribute, $value, $parameters, $validator) {
$competitionId = ($validator->data, $parameters[0]);
//Now check if the $value is already set for the specific competition_id by using normal database queries and comparison
return count(Team::where("comeptition_id", "=", $competitionId)->whereName($value)->get()) == 0
});
What does it
The custom validation rule receives the data of the field you give with the function (in the code above it's yourCompetitionIdFormFieldHere), so it knows which league/competition_id the user chose. With this information, you now can check if there is already a similar ame for the entered id.

Update Table Using Laravel Model

I've got a table for a sports team. The record shows the team selection and some other information. I want to update the record with the team selection. My model is thus:
class Selection extends Model {
protected $table = "selection";
protected $fillable = [
'loose',
'hooker',
'tight',
'secrow1',
'secrow2',
'blindflank',
'openflank',
'eight',
'scrum',
'fly',
'leftwing',
'rightwing',
'fullback',
'sub1',
'sub2',
'sub3',
'sub4',
'sub5'
];
}
So I have a form which gives all the data for the positions and gives the id for the record in the DB. In my controller, I've got:
public function storeFirstTeam()
{
$input = Request::all();
Selection::update($input->id,$input);
return redirect('first-team');
}
But I get the following error:
Non-static method Illuminate\Database\Eloquent\Model::update() should not be called statically, assuming $this from incompatible context
Can anyone point out my silly error?
Please check the code below and this would solve your problem:
Selection::whereId($id)->update($request->all());
The error message tells you everything you know: you’re trying to call a method statically (using the double colons) that isn’t meant to be.
The update() method is meant to be called on a model instance, so first you need to retrieve one:
$selection = Selection::find($id);
You can then can the update() method on that:
$selection->update($request->all());
You should write it like given example below:
Selection::where('id', $input['id'])->update($input);
// Or use this using dynamic where
Selection::whereId($input['id'])->update($input);
Alternatively, you may write it like this as well:
Selection::find($input['id'])->fill($input)->save();
You can also simply update the fields manually:
Selection::whereId($id)->update($request->all());
it is possible to update with primary key but in my case I dont have id field in the detail table. To do it just run a query like this:
DB::table("shop_menu_detail")
->where(['name' => 'old name', 'language' => 'english'])
->update(['name' => 'new name']);
where is used as it is.

Laravel Validator unique value

I am trying to validate an email address in my Customer table. There is a column in the Customer table called Brand where effectively the same email address could be registered to multiple brands for example:
Email Brand
me#mywebsite.com firstsite.com
me#mywebsite.com secondsite.com
When validating the email address I need to check the email is unique in the Customer table for the current Brand. Currently my validation rule looks like this
$rules = array('email' => 'required|email|unique:Customer,Email');
however Brand must appear in there someone to say the email must be unique to the customer for the current brand
Any help much appreciated
You can use the column and value parameter of the unique validation rule to add a condition to the rule.
'email' => 'required|email|unique:Customer,Email,null,null,column,value'
The problem is you need your Brand input in order to create your rule like this :
$rules['email'] = 'required|email|unique:Customer,Email,null,null,Brand,' . Input::get('Brand');
This rule will check if the email is unique where the brand has the given value.
More information here :
http://laravel.com/docs/validation#rule-unique
There is also a package that could help you :
https://github.com/felixkiss/uniquewith-validator
$rules = array('email' => 'required|email|unique:Customer,Email'); this will query your model for finding the entered email if the email is already present then an error message is raised. so this will not work with your app design flow. you have to run sql query to find out if the email is present with your current brand if yes return error message if not save the data. something like that
I would go for writing my own custom validation rule. Custom validation rule will be more common solution and you can name it as it suites you best. It can be created using the Validator::extend() and a closure, like this :
Validator::extend('awesome', function($field, $value, $params)
{
return $value == 'awesome';
});
or via validator class. Have a research at this topic, maybe here (scroll to custom rules section) or any other source you find.

Resources