Change the error message in inserting a url with $ form -> $ filed - yii2

I want to change the error message that comes out when you enter a url wrong. I show you what I mean:
Image
The message must become: Inserisci un URL valido. Es: https://www.google.it
I am modifying the view.php generated automatically by gii. Here is the code:
<?= $form->field($model, 'link')->input('url')?>
This is the function I use to enter a valid url.

You can change the rules in your model for the attribute link using an inline validator:
public function rules()
{
return [
[['link'], 'required'],
['link', function ($attribute, $params, $validator) {
// Check validity of attribute
if ($this->$attribute != ...) {
$this->addError($attribute, 'Inserisci un URL valido. Es: https://www.google.it');
}
}],
];
}
When checking the validity of the $link attribute, you also can use the Yii2 UrlValidator.

Related

How to route a url to include scrolling down to a div id in Laravel

I am validating a contact form. I wrapped it in a div with the id of "contactform". When validation messages appear after submission I want the redirected page to scroll down automatically to the "contactform" div so users don't have to scroll down themselves to correct the form.
I can accomplish this easily by manually typing the url:localhost:8000/#contactform
However I cannot get the routing to work in Laravel.
I tried altering the controller to:
return Redirect::to('/#contactform');
I tried:
return Redirect::to('#contactform');
return Redirect::to('/' . '#contactform');
return view('/')->with('#contactform');
return view('/#contactform');
return view('/pages.index.#contactform');
return view('/pages.index#contactform');
They all return without the #contactform in the url.
I know there is a javascript way to accomplish this, but I was really trying to stay away from javascript for now. There has to be a simpler way I just cannot see it. I'm new to Laravel and completely self-taught. Thanks
***EDIT
I tried a new controller step by step. Without validation it works. Validation seems to break it.
This works:
public function store() {
return (string) Redirect::to('/#contactform');
}
This breaks it:
public function store(Request $request) {
$this->validate($request, [
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required|email',
'telephone' => 'nullable',
'comments' => 'required',
]);
return (string) Redirect::to('/#contactform');
}
The top of the controller page I call the request and redirect like this:
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
Can anyone help me get down to the reason why I cannot validate without breaking the url route?
On validation failure it will cause a redirect 'back'. It is entirely possible that 'back' is the same URI you want to redirect to, so from your perspective it looks like it is redirecting wrong when it is correct. If you remove the validation you should get the correct redirect.
Side note: On the server side the hash is not part of the URL. It is a client side thing.
A solution that works for me is to compact() a Boolean variable through the controller.
Link example
Passing the variable to the controller
Route::get('/post={post_id}+{scroll}',[PostController::class, 'show']);
If the variable equals 'scroll' then switch the boolean variable to true
public function show($post_id, $scroll){
if($scroll == 'scroll'){
$scroll = true;
}else{
$scroll = false;
}
return view('yourview', compact('scroll'))
}
Run the script if $scroll is true
<script>
#if($scroll)
$(document).ready(function () {
$('html,body').animate({ scrollTop: 99999 }, 'slow');
});
#endif
</script>

Yii2 ActiveForm Stripe token

In Yii2, we are using \Stripe\Charge::create following the site's documentation example:
https://stripe.com/docs/payments/accept-a-payment-charges
Everything works great as long we use straight HTML in the views, but when we embed the card-element in an ActiveForm, the stripe.js returns:
XMLHttpRequest cannot load https://api.stripe.com/v1/tokens due to
access control checks.
We would like to use ActiveForm to simplify the validation and handling of other fields on the form. Any help?
Best,
Joe
The error is CORS related, see CORS. Use the appropriate Access-Control as described there.
You can use Yii's build in behavior yii\filters\Cors in your controller.
Try first without any restriction:
public function behaviors()
{
return [
'corsFilter' => [
'class' => \yii\filters\Cors::className(),
],
];
}
If it works, than you can restrict the access by parametrising the behavior, something like that:
public function behaviors()
{
return [
'corsFilter' => [
'class' => \yii\filters\Cors::className(),
'cors' => [
'Origin' => [https://api.stripe.com'],
'Access-Control-Request-Method' => ['POST', 'PUT'],
],
],
];
}
So, for anyone landing here, the only way I can get this to work is to remove the ActiveForm scaffolding. Real bummer because I've had to validate the non-Stripe input fields with Javascript, which is lot more work.
I do challenge anyone to post working code in Yii using ActiveForm that will return a token. I don't think it can be done...but I would love to be wrong.
Best,
Joe

inconsistent email format of html input field with laravel email validation

In my blade file i have a html form for user in which input field email have type email. But i think it provide inconsistent email format validation. example it show abc#xyz and abc#xyz.com both are correct email address but in my controller, validator method return me invalid email format for abc#xyz. How can i resolve this issue???
In my blade file:
<input type="email" name="email" value="">
And in my controller:
$validator = Validator::make($request->all(), [
'email' => 'email|unique:table_name,col_name',
],[
'email.unique' => 'email is already in used',
]);
if ($validator->fails()) {
return redirect()->back()->withInput($request->all())->withErrors($validator);
}
Actually Laravel using PHP builtin function called filter_var (source code).
// Illuminate\Validation\Concerns\ValidateAttributes
/**
* Validate that an attribute is a valid e-mail address.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function validateEmail($attribute, $value)
{
return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
}
The rules implemented by PHP is quite different with the rules implemented by the browser. abc#xyz passed the browser validation rule because xyz is a valid hostname (you can read it here). But PHP implementing more strict rule that the email address should contains top level domain.

Upload via Ajax in Yii2 not including files

I'm trying to upload an image via Ajax request and seem to be hitting a similar issue as this question but it has no answer. I'm not sure if they are exactly the same so I'll post all the details I can here and hope the more detail helps someone find an answer.
I'm paraphrasing the below from my code (cutting out a lot of what I think is irrelevant to this question) so any typos you see are likely just me changing the code below.
The following is included in my model:
use yii\web\UploadedFile;
...
class Image extends \yii\db\ActiveRecord
{
public $imageFile;
public function rules()
{
return [
[['imageFile'], 'file', 'skipOnEmpty' => true, 'extensions' => 'png, jpg'],
];
}
public function upload()
{
if ($this->validate()) {
$this->imageFile->saveAs('uploads/' . $this->imageFile->baseName . '.' . $this->imageFile->extension);
return true;
} else {
return false;
}
}
Here is a portion of my view file:
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'title') ?>
<?= $form->field($model, 'imageFile')->fileInput() ?>
<?= Html::submitButton('Upload', ['class' => 'btn btn-success']) ?>
<?php ActiveForm::end(); ?>
And the Ajax in the view
$('form').on('beforeSubmit', function(e) {
var form = $(this);
$.post(form.attr('action'), form.serialize()).done(function(result) {
console.log(result)
});
return false; // Prevent default form submit action
});
And the following in my controller
use yii\web\UploadedFile;
...
public function actionUpload()
{
$model = new Image();
if (Yii::$app->request->isAjax) {
$model->load(Yii::$app->request->post());
$model->imageFile = UploadedFile::getInstance($model, 'imageFile');
if ($model->upload()) {
$model->save(); // To save the title to the database
Yii::$app->getSession()->addFlash('success', 'Image uploaded');
return $this->redirect(['index']);
}
}
Yii::$app->response->format = Response::FORMAT_JSON;
return ['return' => 'just me testing here'];
}
The above Ajax will only ever save the title to the database and will not upload the file. If I transition everything to a standard post request I can get it all to work (title is saved to the database and image is uploaded to the proper directory). If I debug around the various views, models, and controllers, it looks like I'm just not getting the imageFile via the Ajax request. The $model->load(Yii::$app->request->post()); loads the title that was submitted via Ajax, so why does that not also pull the file? I thought maybe the $model->imageFiles = UploadedFile::getInstances($model, 'imageFiles'); would be the part that pulls the Ajax submitted files but it doesn't seem to get what I need either. As a test, I even tried treating the imageFile property as plain text and assigning it to another database property to be written and it worked just fine. So it seems it's being included in the model properly, just not being send with the Ajax submit.
Can anyone tell me how, in Yii2, I can submit the form over Ajax, including the selected file?
The Problem
What the problem in ajax is that $_FILES details are not sent in asynchroous request.
When we submit the filled form without ajax request and debug in backend side in PHP by
echo '<pre>';
print_r($_FILES);
print_r($_POST);
echo '</pre>';
die;
then we successfuly get $_FILES and $_POST data.
But when we debug the same thing in ajax request, we get only $_POST values and we get $_FILES as NULL. This led us to conclusion that $_FILES data are not sent in ajax request by our above code.
The Solution
We need to use FormData of JavaScript.
What does it do?
In simple words, it adds all necessary information of file which needs to be uploaded to data param in $.ajax OR fill up $_FILES as well as all $_POST data ie non file input such as strings number etc.
In your view file
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'title') ?>
<?= $form->field($model, 'imageFile')->fileInput() ?>
<button type="button" class="btn btn-success subm">Upload</button>
<?php ActiveForm::end(); ?>
<script>
$('.subm').click(function(e){
var formData = new FormData($('form')[0]);
console.log(formData);
$.ajax({
url: "some_php_file.php", //Server script to process data
type: 'POST',
// Form data
data: formData,
beforeSend: beforeSendHandler, // its a function which you have to define
success: function(response) {
console.log(response);
},
error: function(){
alert('ERROR at PHP side!!');
},
//Options to tell jQuery not to process data or worry about content-type.
cache: false,
contentType: false,
processData: false
});
});
</script>
Testing
Now make ajax request and debug in PHP code by print_r() as shown above, you will notice that $_FILES is not NULL and its contains all file (which needs to be uploaded) data. And if it is set you can upload using move_uploaded_file() funtion
So this is how your file is uploaded via Ajax.
Referece 1
Referece 2
Referece 3

YII - Adding error code in form validation

I have a web-service and want to send a custom error-code and string in case form validation fails. We can specify error 'message' in form validation rules, but I want to add a numerical error code, that I can use later to get a text string. Extending CValidator is not an option as I want to use standard validators.
Ideally, I would like something like this in my rules() function.
array('page', 'numerical', 'integerOnly' => true, 'min' => 1, 'message' => '{attribute} is invalid', 'code' => 10079),
Later I return a JSON block like
{
'code': 10079,
'message' : 'page is invalid'
}
I am thinking of attaching a behavior to validators, but not quite able to figure out a way to make it work. Is there any other yii-way to do it?
instead of message , you just return the error code as message and on the view page just call a function to retrieve the appropriate error message.
provide $form->error(); as parameter to get errorMessage on the view page.