I have a user registration form, where i am using file input box to upload image.
Now the problem is , if i will select video file to upload it will pass ValidateRequest .
In ValidateRequest, i already define the rule for image, below is the code:
class UserValidateRequest extends Request {
public function __construct() {
}
protected $messages = [
'required.password' => 'We need to know your e-mail address!',
];
protected $rules = [
'first_name' => 'required|regex:"[a-zA-Z 0-9]"',
'last_name' => 'regex:"[a-zA-Z 0-9]"',
'image' => ' mimes:jpeg,jpg,png,gif |max:2048',
];
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize() {
return true;
}
public function messages() {
return [
'password.regex' => 'Password shall be 8-20 characters, must have a number and an alphabet', ,
'image.mimes' => 'Upload Gif || JPG || JPEG || PNG Images Only'
];
}
public function attributes() {
return[];
}
}
Instead of using mime type validation, try to add image validation rule to image field:
'image' => 'image|max:2048'
Related
I'm working on validating an image file with two different dimensions rule, it can b Icon or Banner depending on the selection of recently selected field. I'm doing this by adding a custom Rule class, here is my validation rule which works fine on Icon Only OR Banner Only
$validator = Validator::make([
'file' => $value,
], [
'file' => 'mimes:png,webp|dimensions:width=512,height=512|max:2048'
]);
$validator->validate();
now the problem is to validate the banner with a different dimension in the same field. Is there any way to add another Width & Height to this line? I've tried to add another rule under this file with the same name, but it doesn't work. Or is there any other approach to solve this problem? I've read the documentation but could not find the solution there.
Thanks in advance.
Validation rules by default must all pass for the input to be valid. In your case you need one of the two rules to pass which is not possible via built-in validation rules. You can create your own validation rule e.g.:
php artisan make:rule DimensionRule
Then modify the generated rule:
class DimensionRule implements Rule {
public function passes($attribute, $value) {
$validator1 = Validator::make([ $attribute => $value ], [ $attribute => 'dimensions:width=512,height=512' ]);
if ($validator1->passes()) {
return true;
}
$validator2 = Validator::make([ $attribute => $value ], [ $attribute => 'dimensions:width=800,height=30' ]);
return $validator2->passes();
}
public function message()
{
return 'Dimensions must either be 512x512 or 800x30';
}
}
Then you can use this rule:
$validator = Validator::make([
'file' => $value,
], [
'file' => [ 'mimes:png,webp', new DimensionRule(), 'max:2048' ]
]);
$validator->validate();
I would do it this way, buy running few validations in a row, and if it passes one, it should be OK. You can write more validation rules after that of course, I think only the dimensions validation should be here.
class FileUploadController extends Controller
{
/**
* Update the avatar for the user.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function fileUpload(Request $request)
{
foreach ([[100, 50], [200, 150]] as $k => $dim) {
$validators[$k] = Validator::make($request->all(), [
'avatar' => "dimensions:width={$dim[0]},height={$dim[1]}"
]);
}
foreach ($validators as $validator) {
if ($validator->fails()) {
$invalid = true;
} else {
$invalid = false;
break;
}
}
if ($invalid) {
return redirect()->back()
->withErrors($validator)
->withInput();
}
$path = Storage::putFile('public', $request->file('avatar'));
return $path;
}
}
And here is also a feature test:
class FileUploadTest extends TestCase
{
/**
* #dataProvider cases
*/
public function test_avatars_can_be_uploaded($w, $h, $shoudReturnError)
{
Storage::fake('public');
$file = UploadedFile::fake()->image('av1.jpg', $w, $h);
$response = $this->post('/file-upload', [
'avatar' => $file,
]);
if ($shoudReturnError) {
// The image dimensions are not right and it should return error
$response->assertSessionHasErrors(['avatar']);
} else {
// The image dimensions are fine and it should pass
Storage::assertExists('public/' . $file->hashName());
}
}
public function cases()
{
return [
[100, 50, $shoudReturnError = false],
[600, 850, $shoudReturnError = true],
[200, 150, $shoudReturnError = false],
[102, 50, $shoudReturnError = true],
];
}
}
I've provided cases where the validation should pass and where it should fail.
Cheers
Although there are quite a lot of questions concerning Yii2 captchas as well as problems with saving, I couldn't find and answer that solved my problem. Hope someone can help:
In my website I included a contact form along with a captcha. Therefor I added code to the model, to the IndexController and the form as described here: https://yii2-cookbook-test.readthedocs.io/forms-captcha/#how-add-captcha-to-a-form
The captcha is displayed and prevents from submitting the form if the code wasn't entered correctly. However, if I include the captcha validation rules, the message is not saved to the database. So there seems to be something wrong with the validation rule.
['verifyCode', 'captcha', 'captchaAction' => '/contact/index/captcha']
I just don't see what is wrong here. When I comment it out, it the model is saved but the captcha isn't validated. Leaving the part with "captchaAction" out leads to an Invalid Captcha ID error, the solution is to include the captchaAction as described here: Yii2 Invalid CAPTCHA action ID in module
Does anyone have an idea of what might be wrong here? Running in circles...
Form:
...
<div class="form-group">
<div><?= Yii::t('ContactModule.form', 'Please enter the letters from the image.'); ?></div>
<?= $form->field($model, 'verifyCode')->widget(Captcha::class, [
'captchaAction' => '/contact/index/captcha',
])->label(false); ?>
</div>
...
Model:
class Contact extends ActiveRecord{
public $verifyCode;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'contact';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['name','email','message'], 'required'], //Checking that all the fields are required
['email', 'email'], // Validating that email is a valid email
[['name'],'string', 'max' => 50], //Verifying that name is not greater than its max length
[['email'], 'string', 'max' => 50], //Verifying that email is not greater than its max length
[['message'], 'string', 'max' => 255],//Verifying that message is not greater than its max length
['state', 'boolean'],
[['date'], 'date', 'format' => 'php:Y-m-d'],
['verifyCode', 'captcha', 'captchaAction' => '/contact/index/captcha'],
];
}
...
Controller
class IndexController extends Controller
{
public $subLayout = "#contact/views/layouts/default";
/**
* #inheritdoc
*/
public function actions()
{
return [
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
]
];
}
/**
* Renders the index view for the module
*
* #return string
*/
public function actionIndex()
{
$model = new Contact();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$model->save();
...
I'm trying to save my uploaded file using Spatie's media libray (v9) and somehow I can't persist the image in my media table and my storage folder. When i dd() the request it finds the file and every information it needs, what am I missing ?
Here is my controller store method :
public function store(Request $request, User $user) {
$validationToken = Str::random(32);
$user->create([
'name' => $request->name,
'email' => $request->email,
'description' => $request->description,
'validation_token' => $validationToken
]);
if($request->file('avatar')) {
// persists the uploaded file into the media table
$user->addMediaFromRequest('avatar')->toMediaCollection('avatars');
// fills the avatar column in user table with image path
$user->update(['avatar' => $request->file('avatar')]);
}
session()->flash('message', 'L`utilisateur a bien été créé');
return redirect()->back();
}
}
And my Model
class User extends Authenticatable implements HasMedia
{
use Notifiable, InteractsWithMedia;
public function registerMediaConversions(Media $media = null): void
{
$this->addMediaConversion('thumb')
->width(368)
->height(232)
->sharpen(10);
}
// allows to delete previous avatars when new one is submitted with singleFile() method
public function registerMediaCollections(): void
{
$this
->addMediaCollection('avatars')
->singleFile();
}
}
Thank you in advance for your help
Well, just found the answer, I was actually really close.
The addMediaFromRequest() method must be called on the $user->create() and not on the model itself.
public function store(Request $request, User $user) {
$validationToken = Str::random(32);
$createUser = $user->create([
'name' => $request->name,
'email' => $request->email,
'description' => $request->description,
'validation_token' => $validationToken
]);
if($request->file('avatar')) {
$createUser->addMediaFromRequest('avatar')->toMediaCollection('avatars');
$createUser->update(['avatar' => $request->file('avatar')]);
}
}
I'm working on a file upload and it upload well until I try to get a file I'm not supposed to be able to upload.
My rules are:
public function rules()
{
return [
'media' => ['required', 'image', 'max:2000']
];
}
public function messages()
{
return [
'media.required' => 'You must give a file to upload!',
'media.image' => 'The file is not an image!',
'media.max' => 'The file is too big!',
];
}
and when I try to upload a file which is 2,3Mo I got a 422 but the message is always The given data is invalid without telling me which one is invalid.
Then in my controller, this is how I use it:
public function uploadMedia(AddMediaRequest $request, MyEntity $entity)
{
$filename = $entity->addMedia($request->validated());
return response()->json(['filename' => $filename], 200);
}
Am I missing a simple point ? (I use Vue for the front end with axios)
so this is my register controller
protected function validator(array $data)
{
return Validator;
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
register here
}
I want to add a referral system to this process basically when registering user might send a refer_id (id of a user who has referred this user to website), I'll check that refer id and if it was valid I'll do some my thing
I want to change my validation function to something like
protected function validator(array $data)
{
$validation = Validator::make($data, [
'email' => ['required' ,'email' , 'max:255', Rule::unique('users')->where('rep_id' , $this->rep->id) ] ,
'password' => 'required|string|min:6|confirmed',
'name' => 'required|max:255',
'last_name' => 'required|max:255',
'refer_id' => 'present|numeric',
]);
if(isset($data['refer_id']))
{
$refer = User::find($data['refer_id']) ;
if($refer)
{
// return error : refer id is wrong !
}
}
return $validation ;
}
my problem is this part
// return error: refer id is wrong!
how can I return registering the user with this error back to view or add this error to validation errors?
Laravel has a clean approach to do this
try this
'refer_id' => 'nullable|exists:users,id'
or may be
'refer_id' => 'present|numeric|exists:users,id'