Laravel form validation - validating against 2 data columns - php

I have a database table that tracks and email address and a client id. The rule is that and email can only belong to one client id. An example would be that I could add, email#domian.com and the client_id 20 but I would not be able to save that again, and this is where the form validation comes in,
I have the following validation rules in my controller,
$data = Input::all();
$client_id = Input::get('client_id');
$validation = Validator::make(
array('email' => Input::get('email')),
array('email' => 'required|email|unique:emails, email, NULL, client_id, $client_id')
);
if($validation->fails()) {
return Response::json($validation->messages(), 400);
} else {
}
Basically I am saying that the email should be a valid email and it should be unique against all the other emails adress that have the same client id.
However I get a PHP error back,
Undefined offset: 1
The POST that I am sending looks like this,
client_id: "16"
email: "simon#simonainley.info"
involved: 1
project_id: "64"
visible: true

Related

October CMS | Using a button to send email retrieved from a field

I'm trying to dynamically find email address (from what has been inputted in a field), then sending out email to that address.
So far, I have been able to get the button to send emails but unable to retrieve the address from model.
Examples:
Controller
public function onSend()
{
// Retrieve email address from Machines model in email field
$this->vars['email'] = Machines::get('email');
// Send to email address using partial button
Mail::send('martin.maintenance::mail.maintenancereminder', [], function($message) {
$message->to($this->vars['email']);
});
}
Field (in Machines model)
email:
label: 'Email Address'
span: auto
type: text
tab: Details
Partial (button)
<button
type="submit"
data-request="onSend"
class="btn btn-primary">
Reminder
</button>
Error
Happy to provide any additional info. Thanks in advance!
I'm not sure what part of your code is triggering that error, but I suspect it has something to do with what ::get('email') is returning.
Machines::get('email') returns a Collection of Machines instances like this:
Illuminate\Database\Eloquent\Collection {#4744
all: [
App\Models\Machines {#4745
email: "example#example.com",
},
App\Models\Machines {#4746
email: "example2#example.com",
},
// ...
]
}
If you want all of the email column values in an Array/Collection, do this:
$this->vars['email'] = Machines::pluck('email');
Machines::pluck('email') returns a Collection of strings like this:
Illuminate\Support\Collection {#4516
all: [
"example#example.com",
"example2#example.com",
// ...
]
}
If you explictly need an array, you can do:
$this->vars['email'] = Machines::pluck('email')->toArray();
/*
* [
* "example#example.com",
* "example2#example.com",
* // ...
* ]
*/
Also, sidenote, Model names in Laravel are by convention singular, so it should be Machine instead of Machines.

Laravel admin update users' info, duplicate email entry when updating his own admin account information

I am working on a laravel 8 application and using spatie/laravel-permission for roles and permissions. On the admin page, I'm displaying all users which the admin can do CRUD operations on. The users list also includes his own admin account.
The problem I'm having is when updating user details. The admin can successfully update user account information for other users with validation. However, if the admin tries to edit the information of his own admin account, the validation passes but I get an SQL error :
Integrity constraint violation: 1062 Duplicate entry 'admin#email.com'
for key 'users_email_unique'
See below my UserController update method for updating user information with validation:
public function update(Request $request, User $user)
{
$edit_user_rules = array(
// ... other validation rules ...
//'email' => "required|email|unique:users,email,{{$user->id}}", //. auth()->user()->id,
'email' => ['required', 'string', 'email', Rule::unique('users')->ignore($user->id)],
// ... other validation rules ...
);
$validator = Validator::make($request->all(), $edit_user_rules);
if ($validator->fails()) {
Session::flash('failed', 'Failed to save User details!');
return redirect(route('editUser', ['user' => $user->id]))->withErrors($validator)->withInput();
} else {
$validated = $validator->validated();
$updatedUser = User::find($user)->first();
// ... other user fields ...
$updatedUser->username = $validated['username'];
$updatedUser->email = $validated['email'];
// ... other user fields ...
if ($updatedUser->save()) {
return redirect(route('allUsers'));
} else {
return redirect(route('allUsers')); // with errors
}
}
}
I've tried to use different validation rules on the email field, for example,
"required|email|unique:users,email,{{$user->id}}"
"required|email|unique:users,email," . auth()->user()->id
but none worked. So I used a validation Rule to validate the unique email field. It works fine when I try to update other users' information but I get the SQL duplicate email error when updating the admin's own account.
Would appreciate any help I can get
The error is getting passed the validation rules, but it's failing when it saves the rule. This is because you're not getting the user properly. find() automatically gets the first record, so first() is unneeded, and is actually probably pulling the wrong account. When I try User::find(3)->first() locally, I'm getting user 1 instead of user 3. Remove first() from your call.
$updatedUser = User::find($user->id);
You didn't determined which column should be unique to ignore him self.
Change your email validation line to :
'email' => ['required', 'email', Rule::unique('users', 'email')->ignore($user->id)],
Don't forget to put this like to top of your code use Illuminate\Validation\Rule; .

Laravel custom validation rule on valid email

So basically I have a simple form and one of the fields is an email.
My controller responsible for this form is the following(showing only the essentials)
$messages = array(
'rsvp_email.required' => 'A valid email is required.')
);
$rules = array(
'rsvp_email' => 'required|max:150|email',
);
$validator = Validator::make($request->all(), $rules,$messages);
Now there are 2 scenarios:
a) The email is not inserted and the above validation works with the custom message(This works OK)
b) The email is not in a valid format (myemail#email) and the resulted error message is The rsvp email must be a valid email address. which is not what I want to be displayed.
What additional rule should I include for a valid email?
Thank
IF you want to change this message go to the following path:
resources/lang/en/validation.php
and change value of email index.

Laravel 5 Validations

I want to validate my form fields using laravel 5.
Form field 1 -> User ID :
Form Field 2 -> Other Name :
Either of the form field is required.
i mean if user id is present other name should be blank and if other name is present user_id should be blank.
I am trying to use:
$validator = Validator::make(
[
'user_id ' => $user_id,
'user_name' => $user_name
], [
'user_id' => 'required_without:user_name',
'user_name' => 'required_without:user_id'
]);
if ($validator->fails()) {
return Utility::validation_err($validator);
}
While updating record even if user id is present it gives me error user id is required when other name is not present. also if i am filling out both it accepts both. It should accept one of both fields.
Any help will be appreciated.
You can use your own validation rule, for exmaple "only_one_id_name_required". It should be applied to both of fields. Next put extend Validator in App\Providers\AppServiceProvider
Validator::extendImplicit('only_one_id_name_required', function($attribute, $value, $parameters, $validator) {
return (request()->has('user_id') xor request()->has('user_name'));
});
Use extendImplicit() instead of extend() to cover empty fields request.

PHP mailing list without form

Is there anyway to get a user's email without a form in php? I want to able to send someone an email for a mailing list and instead of them filling out a form where they enter their email, the php page I have linked in the email. They click the link and it sends them to a thank-you page on the site. Then it stores their IP, date/time and email in a database I have set up. I've completed this with a form, but I'm wondering if there's any possible way to do it without a form. Here's my code for the form, I'm using Drupal form API. I've been googling this for hours, but have found nothing. I saw something about URL parameters, but it didn't really pertain to my question. Any help is appreciated.
<?php
//This custom module will be used on the website to gain consent from our clients because of the recent CASL anti spam laws that were passed in Cnada.
//Menu hook starts here, implements menu and sets the title, url of the page.
function form_casl_menu() {
$items = array();
$items['casl-consent/form'] = array( //this creates a URL that will call this form at "url"
'title' => 'CASL Subscription', //page title
'description' => 'A form that allows us to send emails to clients with their consent.',
'page callback' => 'drupal_get_form', //this is the function that will be called when the page is accessed. for a form, use drupal_get_form
'page arguments' => array('form_casl_form'), //put the name of the form here
'access callback' => TRUE
);
return $items;
}
//permission hook
function form_casl_permission() {
return array(
'administer my module' => array(
'title' => t('Administer my module'),
'description' => t('Perform administration tasks for my module.'),
),
);
}
//form hook, form elements start here
function form_casl_form($form, &$form_state) {
//sometext here
$form['some_text'] = array(
'#markup' => '<p><b>Simply enter your email address to subscribe</b>
</p>'
);
$form['email'] = array(
'#type' => 'textfield', //their email
'#title' => 'Email:',
'#size' => 30,
'#maxlength' => 150,
'#required' => TRUE,
);
//submit button
$form['submit_button'] = array(
'#type' => 'submit',
'#value' => t('Submit Data'),
);
return $form;
}
//validate hook
function form_casl_form_validate($form, &$form_state) { //invalid email error
if (!valid_email_address($form_state['values']['email'])) {
form_set_error('mail', t('You must enter a valid e-mail address.'));
}
}
//submit hook
function form_casl_form_submit($form, $form_state) {
$sDate = date("Y-m-d H:i:s"); //returns the date and time
global $name;
$subbed = 'Yes';
//----------------------------------------------------------------\\
$ip55 = &drupal_static(__FUNCTION__);
//ip get function, returns a clients IP address and checks if they're behind a proxy.
if (!isset($ip55)) {
$ip55 = $_SERVER['REMOTE_ADDR'];
if (variable_get('reverse_proxy', 0)) {
$reverse_proxy_header = variable_get('reverse_proxy_header', 'HTTP_X_FORWARDED_FOR');
if (!empty($_SERVER[$reverse_proxy_header])) {
// If an array of known reverse proxy IPs is provided, then trust
// the XFF header if request really comes from one of them.
$reverse_proxy_addresses = variable_get('reverse_proxy_addresses', array());
// Turn XFF header into an array.
$forwarded = explode(',', $_SERVER[$reverse_proxy_header]);
// Trim the forwarded IPs; they may have been delimited by commas and spaces.
$forwarded = array_map('trim', $forwarded);
// Tack direct client IP onto end of forwarded array.
$forwarded[] = $ip55;
// Eliminate all trusted IPs.
$untrusted = array_diff($forwarded, $reverse_proxy_addresses);
// The right-most IP is the most specific we can trust.
$ip55 = array_pop($untrusted);
}
}
}
//-----------------------------------------------------------------\\
//inserting data into database
db_insert('CASL')
->fields(array(
'email' => $form_state['values']['email'],//email
'ip' => $ip55,//ip
'substatus' => $subbed,
'datetime' => $sDate,//date and time
))->execute();
//sending confirmation email to the user, letting them know they can unsub at any time.
$values = $form_state['values'];
$to = $form_state['values']['email'];
$subject = 'Confirmation';
$message ="Thank you for your submission. You may unsubscribe at any time by refilling out this form http://www.localhost.ca/casl-consent/form and selecting the 'unsubscribe' option. Or, you can simply email us a request to unsubscribe, and we will remove you from our database immediately.
If you have any questions or concerns, you can email us at this link: http://www.localhost.ca/contact";
mail($to, $subject, $message);
drupal_set_message("Thank you! Your information has been received successfully and you have been sent a confirmation email.");
//thank you message after submission
}
?>
Based on your comment, it sounds like you are attempting to associate a known email address to an IP address. You say you are sending an email and they are clicking a link. I'm making the assumption that each of these links on each email is uniquely generated an associated to a specific address. In that case, your problem comes down to "How do I find a client's IP address?".
In PHP, you can do this using $_SERVER['REMOTE_ADDR']. This is the most reliable, but by no means fool proof.
'REMOTE_ADDR'
The IP address from which the user is viewing the current page.
If the user is behind a proxy, the $_SERVER['HTTP_X_FORWARDED_FOR'] may have been set, but this value can be spoofed by both the client and the proxy. It's not guaranteed to be accurate and shouldn't be trusted. If the user if using a proxy, though, the value in REMOTE_ADDR will be the IP address of the proxy that hits your webserver, not that of the client.
So, assuming you are going to use REMOTE_ADDR, how do you associate the email address to the IP address?
The user clicks a unique link that you have stored with the known email address. That link runs a very simply script and looks at REMOTE_ADDR and maybe HTTP_X_FORWARDED_FOR and you store those two values.
Your table should be as simple as this:
email_address | unique_link | remote_addr | http_x_forwarded_for
The last two values are filled out once the user clicks the unique_link. How you populate email_address initially, remains your secret.

Categories