Laravel Backpack - laravel

I need help. I am currently working with Laravel backpack and I have the following problem: I have a field called Media, that field has two behaviors, one to upload images and the other to write a URL, the problem is that it only lets me create the one time the field. Is there a way in laravel backpack to create 2 different fields with the same name?
I want to achieve something more or less like this:
CRUD::addField([ 'name' => 'url_media', 'label' => 'url_media', 'type' => 'upload',
]);
CRUD::addField([ 'name' => 'url_media', 'label' => 'url_media', 'type' => 'url', ]);

Because of the HTML spec, you cannot have two inputs with the same name in a form. I mean... you can. But only the last one will be sent in the request.
If you don't want to show both fields at the same time, you can use a conditional (if/else) to show either the upload field or the url field.
Otherwise, a different way would be to choose a fake name for the second field (say... url_media_link), then use a Laravel Mutator in your model, in this case setUrlMediaLinkAttribute() to do what you manipulate the model attributes as you want.

Related

Laravel if one field is filled then others are not required

I have three nullable fields ( Coupon, Membership, Offer) which are to be filled from requests. I want to validate/restrict users so that they can only fill one of these fields.
As the fields are not required, I cannot use the required:* validators to handle this.
I know this can be handled in the front-end, but I want to do it in the backend as well.
Appreciate any help/insight on this.
You can use required_without_all function from laravel validations.
$request->validate([
'coupon' => ['nullable', 'required_without_all:membership,offer'],
'membership' => ['nullable', 'required_without_all:coupon,offer'],
'offer' => ['nullable', 'required_without_all:membership,coupon'],
]);
I would take the approach of having the options as three possible values for the same field. You could use a select or radio button group on your form to fill in a single field. This way the user can only enter one of the three possible values.
If we call the field type for example, your validation would check that the value given for type is one of the three options.
$request->validate([
'type' => [
'nullable',
Rule::in(['coupon', 'membership', 'offer']),
],
]);
EDIT:
Add the nullable validation to allow the field to have no value at all

Two fields overwriting each others values on saving in Backpack for Laravel CRUD (spatie/laravel-tags implementation issues)?

I am trying to use spatie/laravel-tags together with Backpack for Laravel. I have 2 types of tags defined. Currently I have extended the Tag model from spatie/laravel-tags as MyCategory and MyTag and added global scopes to separate the two tag types. This works to the extent that it will display the current categories and tags correctly in Backpack, but when I try to save any changes it will only save the entries in the last field, and delete everything in the first field.
Here is my current field configuration for my CRUD:
$this->crud->addField([
'name' => 'categories',
'label' => 'Categories',
'type' => 'select2_multiple',
'tab' => 'Overview',
'attribute' => 'name',
'model' => 'App\MyCategory',
'pivot' => true,
]);
$this->crud->addField([
'name' => 'tags',
'label' => 'Tags',
'type' => 'select2_multiple',
'tab' => 'Overview',
'attribute' => 'name',
'model' => 'App\MyTag',
'pivot' => true,
]);
When I check Laravel Telescope I see that the same thing happens for both fields. First all current tags (regardless of type) for the item I am saving are deleted, and the new tags from the field are added. This is then repeated for the second field, which of course deletes the tags from the first field that should also be kept.
It seems that GlobalScope on my extended Tag models does not stick around for this part. Is there any way to reintroduce the scopes into the queries run by backpack to get these tags to save correctly?
In my CrudController I created custom update and store functions. See the update example below. This seems to work fine. There are still 2 queries being run, with the second one undoing the first one, but for my purposes this is a good enough workaround to be able to have 2 fields with different tag types in the same form in Backpack, using spatie/laravel-tags.
public function update(UpdateRequest $request)
{
$request = request();
// Merge the values from the two tag fields together into the second field
$request->merge(['tags' => array_merge((array)$request->input('categories'), (array)$request->input('tags'))]);
$redirect_location = $this->traitUpdate($request);
return $redirect_location;
}

Laravel: Validate input only if available in DOM

I created a form with the following fields:
Name
Email
Country
City
Address
If the user selects a country that has states (ex. United States) then the form transforms to:
Name
Email
Country
State
City
Address
To validate this I created a separate form request like so:
public function rules()
{
return [
'name' => 'required|max:255',
'email' => 'required|email,
'country_id' => 'required|integer',
'state_id' => 'nullable|integer',
'city_id' => 'required|integer',
'address' => 'required',
];
}
The problem is that if I leave it like that, then if I don't select a state it will pass validation.
If i make it:
'state_id' => 'sometimes|nullable|integer',
Then again it passes validation.
If I make it:
'state_id' => 'required|nullable|integer',
It will not pass validation, but then again it will throw a validation error if there is no state field in the form.
I read a lot of articles about this but nothing seems to solve it for me.
PS1: I want to solve this in the form request, not in the controller. I assume that an
if($request->has('states')){...}
can help, but then again, i would like to keep everything tidy in the form request.
PS2: I am using VueJS and Axios to add/remove states from the form. The whole form is actually a Vue component.
Any clues?
Thank you in advance!
You can conditionally add rules via the sometimes method on Validator.
$v->sometimes('state_id', 'required|integer', function ($input) {
return in_array($input->countries, [1,2,3,4...]
});
You could use the required_with line of parameters, but because the validation is based on the value of the input instead of just the presence, the custom validation rule is probably your best bet.
Per https://laravel.com/docs/5.7/validation#conditionally-adding-rules

Laravel form request validation

Is there any way to get original data in request?
I mean, in my case I want to validate updating user's in the form. I want the email to be unique on emails in database except on the email that user wrote to the form.
Laravel already has a validation rule for this, you can add an id of the user to ignore to your unique validator.
'email' => [
'required',
Rule::unique('users')->ignore($currentUser->id),
]
I used something like this:
'email' => ['sometimes', 'email', 'unique:users,email,'.$user->getKey().','.$user->getKeyName().',deleted_at,NULL', 'string'],
Not sure if it is the best solution but works. I kind of do not like it because the $user is based on hidden input from the request.
You can do it liks this:
'email' => 'unique:users,email,'.$user->id
The user id will allow you to keep updating the record but maintain the unique constraint on email. You don't need a hidden input field for $user->id btw.

How to implement email validation on admin form in Magento2

I want to use email validation in admin form of my custom module. I've seen core module but couldn't get exact idea.
You can also validate the 'email' text field by adding a class ['validate-email'] in your form
$fieldset->addField(
'email',
'text',
[
'name' => 'email',
'label' => __('Email'),
'title' => __('Email'),
'required' => true,
'class' => 'validate-email'
]
);
Validation is Model's issue. Only model knows how your data should look like. You describe your data fields in model, so you should describe validation rules for this fields in the same place.
It seems to be obvious for me, but I'd gladly listen to opponents.
put database validation in the Model (assuming it's a db model) and http data validation in the controller. Xss filtering, for example, does not pertain to the Model. it pertains to the Controller in input and to the View in output
I found an answer by myself, I used PHP email validation in the save controller.

Resources