I have an input field and would like to compare the data which got sent with those in my database.
Suppose we have a book with a serial number. Now this customer borrows this book and wants to return it after one week. Then he verifies himself with his membership card and sees a table where his borrowed books are listed. Before he can return the book he has to scan the serial number of this book. This is to compare whether the serial number is really in the database.
And this is exactly what I'm looking for help with, everything else I've implemented so far, and with the help of this community I'd like to thank everyone again.
Now I need your help again how I could implement this check. I think I could solve it somehow in the controller with an if statement but don't know how to implement it correctly.
My Controller function:
public function verify(AusleihRequest $request){
$this->middleware('guest');
$validator = Ausleih::make($request->all(), [
'seriennummer' => 'required'
]);
return redirect()->route('ausleihe.yourdevices')
->with('success','Gerät erfolgreich verifiziert');
}
EDIT:
And the user shouldn't have to log in again after verifying.
Use the exists rule:
The first param after the : specifies the name of your table, the second (after the ,) the name of the field, the number is stored.
$validator = Ausleih::make($request->all(), [
'seriennummer' => 'required|exists:serialnumbers,number' // or however your field is named
]);
https://laravel.com/docs/master/validation#rule-exists
Related
Apologies if this has been asked before. All of the examples I can find are old or apply to legacy versions of CakePHP, e.g. cakephp: saving to multiple models using one form is 7 years old.
I have an application in CakePHP 4.1.6. Two of the tables in the database are called tbl_users and tbl_orgs ("orgs" in this case means "Organisations").
When I add an Organisation I also want to create a User who is the main contact within the Organisation. This involves saving to both the tbl_orgs and tbl_users tables when the form is submitted.
The problem I'm experiencing is how to get the form working in a way where it will run the validation rules for both tbl_users and tbl_orgs when submitted.
This is how our application is currently structured:
There is a Controller method called add() in src/Controller/TblOrgsController.php. This was generated by bake and was initially used to insert a new Organisation into the tbl_orgs table. At this point it didn't do anything in terms of tbl_users however it worked in terms of saving a new Organisation and running the appropriate validation rules.
One validation rule is that every companyname record in tbl_orgs must be unique. If you try to insert more than 1 company with the name "My Company Limited" it would give the validation error "This company name already exists":
// src/Model/Table/TblOrgsTable.php
public function buildRules(RulesChecker $rules): RulesChecker
{
$rules->add(
$rules->isUnique(['companyname']),
[
'errorField' => 'companyname',
'message' => 'This company name already exists',
]
);
return $rules;
}
Whilst the above applies to TblOrgs we also have an buildRules() in TblUsers which applies similar logic on an email field to make sure that all email addresses are unique per user.
In the add() Controller method we start by specifying a new empty entity for TblOrgs:
// src/Controller/TblOrgsController.php
public function add()
{
$org = $this->TblOrgs->newEmptyEntity();
// ...
$this->set(compact('org'));
}
When the form is created we pass $org:
// templates/TblOrgs/add.php
<?= $this->Form->create($org) ?>
<?= $this->Form->control('companyname') ?>
<?= $this->Form->end() ?>
When the TblOrgs fields are rendered by the browser we can inspect the HTML and see these are obeying the corresponding Model. This is clear because of things such as required="required" and maxlength="100" which correspond to the fact that field is not allowed to be empty and is a VARCHAR(100) field in the database:
<input type="text" name="companyname" required="required" id="companyname" maxlength="100">
It also works in terms of the rules specified in buildRules for TblOrgs. For example if I enter the same company name twice it shows the appropriate error in-line:
I then tried to introduce fields for TblUsers. I prefixed the form fields with dot notation, e.g. this is intended to correspond to tbl_users.email input field:
<?= $this->Form->control('TblUser.email') ?>
When inspecting the HTML it doesn't do the equivalent as for TblOrgs. For example things like maxlength or required are not present. It effectively isn't aware of TblUsers. I understand that $org in my Controller method is specifying a new entity for TblOrgs and not TblUsers. I reviewed the CakePHP documentation on Saving With Associations which says
The save() method is also able to create new records for associations
However, in the documentation the example it gives:
$firstComment = $articlesTable->Comments->newEmptyEntity();
// ...
$tag2 = $articlesTable->Tags->newEmptyEntity();
In this case Tags is a different Model to Comments but newEmtpyEntity() works for both. With this in mind I adapted my add() method to become:
$org = $this->TblOrgs->TblUsers->newEmptyEntity();
But this now gives an Entity for TblUsers. It seems you can have either one or the other, but not both.
The reason this doesn't work for my use-case is that I can either run my Validation Rules for TblOrgs (but not TblUsers) or vice-versa.
How do you set this up in a way where it will run the validation rules for both Models? It doesn't seem to be an unreasonable requirement that a form may need to save data to multiple tables and you'd want the validation rules for each of them to run. I get the impression from the documentation that it is possible, but it's unclear how.
For reference there is an appropriate relationship between the two tables:
// src/Model/Table/TblOrgsTable.php
public function initialize(array $config): void
{
$this->hasMany('TblUsers', [
'foreignKey' => 'o_id',
'joinType' => 'INNER',
]);
}
and
// src/Model/Table/TblUsersTable.php
public function initialize(array $config): void
{
$this->belongsTo('TblOrgs', [
'foreignKey' => 'o_id',
'joinType' => 'INNER',
]);
}
Okay, lots of confusion to clear up here. :-) My assumption here, based on what you've written, is that you're trying to use a single form to add a new organization, and the first user in it, and then maybe later you'll add more users to the org.
First, $this->TblOrgs->TblUsers is your users table object, so when you use
$org = $this->TblOrgs->TblUsers->newEmptyEntity();
what you're doing is creating a new user entity. The fact that you got to that table object through the orgs table, and that you're calling it $org doesn't change that. It doesn't somehow magically create a blank org entity with a blank user entity in it. But you don't need that entity structure here at all here, just the empty org entity. Go back to simply:
$org = $this->TblOrgs->newEmptyEntity();
Now, in your form, you'll want something like this:
<?= $this->Form->create($org) ?>
<?= $this->Form->control('companyname') ?>
<?= $this->Form->control('tbl_users.0.email') ?>
<?= $this->Form->end() ?>
The field is called tbl_users.0.email because:
The table name gets converted to lower case underscore format.
It's a hasMany relation from orgs to users, so it's expecting an array of users; we have to give a numeric index into that array, and 0 is a great place to start. If you were going to add a second user at the same time, the field for that would be tbl_users.1.email.
Note: A great way to figure out what format the form helper is expecting you to create your field names in is to read an existing set of records from the database (in this case, an org and its users), and then just dump that data, with something like debug($org);. You'll see that $org has a property called tbl_users, which is an array, and that will point straight to this structure I've described above.
With the fields set up like this, you should be able to patch the resulting data directly into your $org entity in your controller, and save that without any other work. The patch will created the entire structure, with a entity of class TblOrg, with a tbl_users property which is an array containing a single entity of class TblUser, and validation will have been done on both of them. (At least it should; you can use debug($org); as mentioned above to confirm it.) And when you save this entity, it will first save the TblOrg entity, then add that new ID into the TblUser entity before saving it, as well as checking the rules for both and making sure that nothing gets saved to the database if it can't all be saved. That all happens automatically for you with the single save call!
If your association was a hasOne or belongsTo relation (for example if you were adding a new user and also the org that they're in, instead of the other way around), you could dump a sample $user, and see that it has a property called tbl_org which is just a straight-up entity, not an array of entities, and note that tbl_org is now singular, because it's just one entity instead of a bunch. In this case, the field name to use would be tbl_org.companyname, no array index in there at all.
I have a question,
I have a Controller and I Have a form request to validate the update.
I want to make conditions for example. If I update an "name" the form request allow change the name but if I didn't make change use the same and don't appear "unique rule" because sometimes I have to change the name, but some times not and the problem is when I haven't to change the name because if I put the same name, I have the message "duplicated" and if I try to update another ID appear "duplicated".
I don't know if you understand but i am trying to be specific.
My rule is the next with a condition.
public function rules()
{
if (Attribute::where('name', '=', Request::get('name'))->count() == 1) {
return [
'name' => 'required'
];
} elseif (Attribute::where('name', '=', Request::get('name'))->count() != 1) {
return [
'name' => 'unique:attributes'
];
}
}
So I compare if name count is ==1 only required but when is !=1 only unique but doesn't work correctly.
Some suggestion?
Based on this Answer,
How validate unique email out of the user that is updating it in Laravel?
You can ignore the current user details and preserve the unique rule while validating the update request in such rule,
As per documentation,
Forcing A Unique Rule To Ignore A Given ID:
Sometimes, you may wish to ignore a given ID during the unique check. For example, consider an "update profile" screen that includes the user's name, e-mail address, and location. Of course, you will want to verify that the e-mail address is unique. However, if the user only changes the name field and not the e-mail field, you do not want a validation error to be thrown because the user is already the owner of the e-mail address. You only want to throw a validation error if the user provides an e-mail address that is already used by a different user. To tell the unique rule to ignore the user's ID, you may pass the ID as the third parameter:
Your rule while updating should look like,
'name' => 'unique:attributes,name,'.$attribute->id
Here, $attribute refers to the attribute being updated.
I hope you will understand.
you can use Rule to check unique
use Illuminate\Validation\Rule;
Rule::unique('table_name')->ignore('id');
I'm not sure if I explained briefly what's the problem is about.
I have a user voting form in which user passes his first name,surname,mothers' surname, and ID.
I have also a table users which stores all this data. Yesterday I found a bug or I misunderstood how laravel validation works because it passes submit every time when it find all the data existing in table.
This is a table with two records.
EXAMPLE
What i expected from validation was to check if the ID=98111091239 name=Andrzej surname=Pianowski and mother surname =Mila and only if everything is correct and exists in one row then the vote can be made.
Instead i can pass ID from first row, other things from second and it also will allow user to vote.
Is that a bug, laravel works that way or what?
I'm really looking forward for any tip,help,sugestions.
And here's validation rule i'm using
/*This validates whether all data is correct */
$validator = Validator::make($request->all(),[
//check whether such pesel exists in votes and in voters
'pesel' =>'required|exists:wyborca|max:11|min:11',
'imie' =>'required|exists:wyborca|max:64|min:2',
'nazwisko' => 'required|exists:wyborca|max:128|min:2',
'nazwisko_matki' => 'required|exists:wyborca|max:128|min:2'
]);
if($validator->fails())
{
return back()
->with('errors','Wprowadzono nieprawidłowe dane')
->withInput();
}
The validator seems to be passing since those values probably exist in multiple records and not just a single one.
One solution would be to validate to ensure that all the fields are present in the request and then do a simple Eloquent query to check if the record exists:
$user = App\User::where('id', $request->id)
->where('name', $request->name)
->where('surname', $request->surname)
->where('mother', $request->mother)
->exists(); //true or false
if($user){
//vote
}
return response()->json(['error' => 'user not found'], 404);
If it does exist, cast the vote else return an error.
I have been trying to figure this one out for quite a whiale and have gone through every post from here and Laracast to figure this out but in vein.
I have done this before and it worked but I am not quite sure why it doesn't now.
Basically setting up a rule in your form request should follow the format below:
<?php
class MyFormRequest extends Request{
public function rules(){
return [
'field' => 'required|unique:table_name:field,' . $this->input('field');
];
}
}
This to me should work but according to my experience at the moment doesn't. I have tried to separate the rules by checking the incoming request method and assign rules based on whether the request is an update or create.
Shouldn't what I have suffice for this requirement? What would be the best way of re-using my FormRequest but making sure that I am able to validate uniqueness of as many table fields as I want regardless of their data types because I am sensing that perhaps this is related to the fact that Laravel seems to be doing an aggregate on the field being validated and if it is not an integer for example it will keep on displaying the error message.
Another possible way of solving this is if I implement my own validation method for the fields I am interested to validate. How would I go about doing this?
This rule works only if the primary key of "table_name" is "id" but if it is different then you have to write it as the fourth parameter to unique rule as follows:
<?php
class MyFormRequest extends Request{
public function rules(){
return [
'field' => 'required|unique:table_name:field,' . $this->input('field').','.'primary_key_field';
];
}
}
hope it help you !!!
You need to tell the validator which rows to exclude from duplicate search.
If your primary key is id, you need to pass its value:
'field' => 'required|unique:table_name,field,' . $this->input('id')
Your code has also some other errors:
'field' => 'required|unique:table_name:field,' . $this->input('field');
^ ^
The rule "unique" needs aditional arguments when updating. Those aditional arguments will be responsible for ignore the actual registry you're working on. If not applied, this rule will always invalidate, since the registry always will be found on database.
Your thirdy argument should be the ID you want to ignore. (you're passing a value...)
*Another thing: I picked up a misstype from your rule. Check below the right sintax with new arguments.
'field' => 'required|unique:table_name,field,'.$this->input('id')'
PS: if your id column from your table has a different name than "id", you need to specify this column name as the fourth parameter.
'field' => 'required|unique:table_name,field,'.$this->input('id').',column_name'
I have 2 forms: $patientForm and $investigationForm.
They are both combined into one view, so the user fills in the fields and 2 records are created in Patient table and Investigation table. Investigation table has a foreign key - to the patient name. So one patient can have many investigations.
So I obviously need the patient id to add it to an investigation record as a foreign key. However, the patient id isn't created until the patient form is saved.
So I have devised the following function:
protected function processPatientInvestigation(sfWebRequest $request, sfForm $investigationForm, sfForm $patientForm)
{
$patientForm->bind($request->getParameter($patientForm->getName()), $request->getFiles($patientForm->getName()));
if ($patientForm->isValid() && $investigationForm->isValid() ) {
$patientForm->save();
$values = $request->getParameter($investigationForm->getName());
$values['patient_id'] = $patientForm->getObject()->getId();
$investigationForm->bind($values, $request->getFiles($investigationForm->getName()));
$investigationForm->save();
}
The if statement always fails because $investigationForm isn't valid until I give its form field a patient_id value. So this value is empty at this point. However, if I just took the isValid() check out for $investigation form and put it down later on after the $patientForm is saved. This means that if it failed validation and the user had missed a field, when they don't click submit again, the whole function would run again meaning we'd have duplicate patient records.
So what I think the answer is, is making the patient_id field not be validated, so it can be empty and still pass the isValid() function.
Please let me know if this isn't clear. Hope you can advise!
Try the following though this should really be done in the forms configure method.
$patientForm->getValidator('patient_id')->addOption('required', false);
The cleaner solution would be to set all your validation rules in the /lib/form/*Form.class.php file itself (rather than manipulating it in your action).
$this->validatorSchema['patient_id'] = new sf*Validator(array(
'required' => false
), array());
If you just want to let a form field completely unvalidated, use
$this->validatorSchema['patient_id'] = sfValidatorPass()
I'd go with embedded forms and let symfony handle the saving correctly.