I'm trying to check whether or not an email or username exists in the database before inserting data into the database. For a reason I do not understand, despite using the email_exists and username_exists functions, when inserting the data, the database throws a field not unique error for username and email fields.
The username_exists and email_exists functions gets any usernames or emails where they match the username or email submitted by the form. The functions then return true if there is a username or email that exists, or false if the opposite. When both functions return false (i.e. username and email don't exist in the database) it inserts the form data into the database.
Any help would be great!
Controller Function
public function register(){
if($this->session->userdata('loggedIn') == TRUE){
$this->session->set_flashdata('error_msg', 'please log out to access this page ');
echo 'Please log out to access this page!...';
sleep(2);
redirect('index.php/user/dashboard');
}
$data['session_data'] = array(
'userID' => $this->session->userdata('userID'),
'loggedIn' => $this->session->userdata('loggedID')
);
$this->load->view('navigation');
$this->load->view('register', $data);
echo 'registration page - ';
if($this->input->post('register')){
$this->form_validation->set_rules('username', 'username', 'required');
$this->form_validation->set_rules('email', 'email', 'required|valid_email');
$this->form_validation->set_rules('password', 'password', 'required');
$user_details = array(
'username' => strip_tags($this->input->post('username')),
'email' => strip_tags($this->input->post('email')),
'password' => strip_tags($this->input->post('password'))
);
if($this->form_validation->run() == true){
$username_exists = $this->user_model->username_exists($user_details[0]);
$email_exists = $this->user_model->email_exists($user_details[1]);
if($username_exists == false && $email_exists == false) {
$this->user_model->add_user_account($user_details);
echo 'user added successfully: '. $user_details[0];
$this->session->set_flashdata('success_msg', 'SUCCESSFULLY ADDED USER, username and email do not already exist!... ');
sleep(2);
redirect('index.php/user/login');
} else {
echo 'username or email already exists! try again!...';
$this->session->set_flashdata('error_msg', 'ERROR OCCURRED - username or email exists!...');
sleep(2);
redirect('index.php/user/register');
}
} else {
echo 'error occured, try again!...';
$this->session->set_flashdata('error_msg', 'ERROR OCCURRED- something didn\'t work');
sleep(2);
redirect('index.php/user/register');
}
}
}
Model Functions
public function add_user_account($user_details){
$this->db->insert('user_account', $user_details);
}
public function username_exists($username){
$this->db->select('username');
$this->db->from('user_account');
$this->db->where('username', $username);
$query = $this->db->get();
if($query->num_rows() > 0){
return true;
} else {
return false;
}
}
public function email_exists($email){
$this->db->select('email');
$this->db->from('user_account');
$this->db->where('email', $email);
$query = $this->db->get();
if($query->num_rows() > 0){
return true;
} else {
return false;
}
}
$user_details[0] doesn't reference anything as you have non-numerical keys for the user_details array. I assume you mean to access the key username thus you should do $user_details['username'].
Like so:
$username_exists = $this->user_model->username_exists($user_details['username']);
$email_exists = $this->user_model->email_exists($user_details['email']);
To be honest I'm surprised this isn't giving you notice errors.
Further, you could easily make your username/email exists functions into a callback or simply use the is_unique feature of the form_validation library.
Also I'm pretty sure that you can apply strip_tags as a form_validation rule and it will remove the tags in the post variables.
Well to address your question via a means of simplification, you can use is_unique[table.field] as a validation rule.
That way you do not need to write any model methods for checking that your username or email is unique.
So in your form validation rules you can alter your username and email rules to include the is_unique rule.
$this->form_validation->set_rules('username', 'Username', 'required|is_unique[user_account.username]');
$this->form_validation->set_rules('email', 'Email', 'required|valid_email|is_unique[user_account.email]');
Note: The 2nd Field is the Form Label and can be anything. In this case I uppercased it. The 1st field IS case sensitive.
As to why your existing code isn't working...
Try getting friendly using var_dump(); or print_r();
i.e.
$username_exists = $this->user_model->username_exists($user_details[0]);
$email_exists = $this->user_model->email_exists($user_details[1]);
// Debug these two and see what they are...
var_dump($username_exists);
var_dump($email_exists);
Now seeing you are using an associative array in setting up
$user_details = array(
'username' => strip_tags($this->input->post('username')),
'email' => strip_tags($this->input->post('email')),
'password' => strip_tags($this->input->post('password'))
);
And then referencing them like
$username_exists = $this->user_model->username_exists($user_details[0]);
Using the above var_dump's should give you an "Aha!!!" moment.
When in doubt var_dump();
Related
I have set the CI framework with database connection, put it on autoload and created a form, yet still, nothing is inserted into the Database!
I've tried using objects(classes) and different ways to pass information in an array
if (isset($_POST['register-submit'])) {
$this->load->model('Registermodel');
$this->load->library('form_validation');
$this->form_validation->set_rules('register-username', 'Username', 'required');
$this->form_validation->set_rules('register-password', 'Password', 'required|min_length[6]');
$this->form_validation->set_rules('register-password-repeat', 'confirm passphrase', 'required|min_length[6]|matches[register-password]');
$this->form_validation->set_rules('register-pin', 'pin', 'required|regex_match[/^[0-9]{6}$/]');
//If form validation was successful
if ($this->form_validation->run() == TRUE) {
echo 'successfully registered!';
//Add user to database
$data = array(
'ci_useruniqid'=> $_POST['register-uniqid'],
'ci_userdate'=> $_POST['register-date'],
'ci_useruid'=> $_POST['register-username'],
'ci_userpwd'=> password_hash($_POST['register-password'], PASSWORD_DEFAULT),
'ci_usermnemonic'=> $_POST['register-mnemonic'],
'ci_usercurrentaddress'=> $_POST['register-address'],
'ci_useraccount'=> $_POST['register-account'],
'ci_useraccountbalance'=> $_POST['register-account-balance'],
'ci_userpin'=> $_POST['register-pin'],
'ci_userstatus'=> $_POST['register-status'],
'ci_usertype'=> $_POST['register-type'],
'ci_userinfo'=> $_POST['register-info'],
'ci_userpgp'=> $_POST['register-pgp'],
'ci_usercurrency'=> $_POST['register-currency']
);
$this->RegisterModel->adduser($data);
redirect("AuthController/loginview", "refresh");
}
What I expect to happen is for the data(as seen above) to be inserted into the DB. My actual result is no response even something as simple as echoing something out in an if statement.
My table structure:
ci_userid int(11)
ci_useruniqid
ci_userdate date
ci_useruid
ci_userpwd
ci_usermnemonic
ci_usercurrentaddress
ci_useraccount
ci_useraccountbalance decimal(12,8)
ci_userpin
ci_userstatus
ci_usertype
ci_userinfo
ci_userpgp
ci_usercurrency
The rest are text, here is my adduser model:
public function adduser($data) {
$insert = $this->db->insert('users', $data);
}
As this was too long for a comment, I present to you my quasi answer that will help you debug.
echo 'hello world <br><pre>';
print_r($_POST);
if (isset($_POST['register-submit'])) {
$this->load->model('Registermodel');
$this->load->library('form_validation');
$this->form_validation->set_rules('register-username', 'Username', 'required');
$this->form_validation->set_rules('register-password', 'Password', 'required|min_length[6]');
$this->form_validation->set_rules('register-password-repeat', 'confirm passphrase', 'required|min_length[6]|matches[register-password]');
$this->form_validation->set_rules('register-pin', 'pin', 'required|regex_match[/^[0-9]{6}$/]');
//If form validation was successful
if ($this->form_validation->run() == TRUE) {
echo 'successfully registered!';
//Add user to database
$data = array(
'ci_useruniqid' => $_POST['register-uniqid'],
'ci_userdate' => $_POST['register-date'],
'ci_useruid' => $_POST['register-username'],
'ci_userpwd' => password_hash($_POST['register-password'], PASSWORD_DEFAULT),
'ci_usermnemonic' => $_POST['register-mnemonic'],
'ci_usercurrentaddress' => $_POST['register-address'],
'ci_useraccount' => $_POST['register-account'],
'ci_useraccountbalance' => $_POST['register-account-balance'],
'ci_userpin' => $_POST['register-pin'],
'ci_userstatus' => $_POST['register-status'],
'ci_usertype' => $_POST['register-type'],
'ci_userinfo' => $_POST['register-info'],
'ci_userpgp' => $_POST['register-pgp'],
'ci_usercurrency' => $_POST['register-currency']
);
$this->RegisterModel->adduser($data);
echo 'success';
//redirect("AuthController/loginview", "refresh");
} else {
echo validation_errors();
}
} else {
echo 'register-submit... well... does not exist';
}
Please note, use $this->input->post('somename'); for all your $_POST stuff. e.g. assume that register-uniqid doesn't exist (form validation won't catch it because it isn't required) you'll get an undefined index error; thus you'd have to do isset($_POST['register-uniqid']) ? $_POST['register-uniqid'] : null whereas $this->input->post() does that logic for you.
Now, even if you make this fix, if register-uniqid is absolutely critical (cannot be null) then make sure form validation covers it with a required. Even though you may have some hidden fields, it doesn't mean the user can't delete them if they want and post a null to that db column. I would suggest forgoing hidden fields entirely and coding any non-user-related input in to this controller or model.
So what I'm trying to do:
Pull User data from database, including email address, username etc.
Edit it
Save it
But I want to keep username and email unique.
And for this I'm setting validation rules like this:
$this->form_validation->set_rules('firstname', 'First Name', 'required|min_length[2]|max_length[15]');
$this->form_validation->set_rules('lastname', 'Last Name', 'required|min_length[2]|max_length[15]');
$this->form_validation->set_rules('email', 'Email', 'required|valid_email|is_unique[users.email]');
$this->form_validation->set_rules('username', 'Username', 'required|min_length[4]|max_length[12]|is_unique[users.username]');
$this->form_validation->set_rules('password1', 'Password', 'required|matches[password2]');
$this->form_validation->set_rules('password2', 'Password Confirmation', 'required');
$this->form_validation->set_rules('group', 'User Group', 'required');
And as you can see I have is_unique[users.username] and is_unique[users.email] rules. But it doesn't let me update my entry using this rules.
So the question is, how can I update database entry, and keep those 2 fields unique(username and email)?
use the call back validation function
$this->form_validation->set_rules('email', 'Email', 'required|valid_email|callback_check_user_email');
function check_user_email($email) {
if($this->input->post('id'))
$id = $this->input->post('id');
else
$id = '';
$result = $this->user_model->check_unique_user_email($id, $email);
if($result == 0)
$response = true;
else {
$this->form_validation->set_message('check_user_email', 'Email must be unique');
$response = false;
}
return $response;
}
in model
function check_unique_user_email($id = '', $email) {
$this->db->where('email', $email);
if($id) {
$this->db->where_not_in('id', $id);
}
return $this->db->get('user')->num_rows();
}
use same for the user name....
In Codeigniter 4
// is_unique[table.field,ignore_field,ignore_value]
$validation->setRules([
'name' => "is_unique[supplier.name,uuid, $uuid]", // is not ok
'name' => "is_unique[supplier.name,uuid,$uuid ]", // is not ok
'name' => "is_unique[supplier.name,uuid,$uuid]", // is ok
'name' => "is_unique[supplier.name,uuid,{uuid}]", // is ok - see "Validation Placeholders"
]);
Eg.
$validation->setRules(['email' => 'required|valid_email|is_unique[users.email,id,4]']);
// 'id' = ignore table field name (users table 'id' field)
// '4' = ignore field value(currnet user id)
codeigniter 4 validation
For Codeigniter 3
Add following helper class (edit_unique_helper.php)
function edit_unique($value, $params) {
$CI =& get_instance();
$CI->load->database();
$CI->form_validation->set_message('edit_unique', "Sorry, that %s is already being used.");
list($table, $field, $current_id) = explode(".", $params);
$query = $CI->db->select()->from($table)->where($field, $value)->limit(1)->get();
if ($query->row() && $query->row()->id != $current_id)
{
return FALSE;
} else {
return TRUE;
}
}
Add to autoload ()
Use edit_unique where you pass an extra parameter which is the id of the row you're editing
eg. $this->form_validation->set_rules('user_name', 'User Name', 'required|trim|xss_clean|edit_unique[users.user_name.'.$id.']');
Source
So i started my first CodeIgniter project, and I'm still learning a lot of things. Right now I've made this user sign-up page.
When the user fills in the sign-up form and presses submit it will trigger the following function:
/**
* Signup validation
*/
public function signup_validation(){
$this->load->library('form_validation');
$this->form_validation->set_rules('email', 'Email', 'required|trim|valid_email|is_unique[users.email]');
$this->form_validation->set_rules('password', 'Password', 'required|trim');
$this->form_validation->set_rules('cpassword', 'Confirm Password', 'required|trim|matches[password]');
$this->form_validation->set_message('is_unique', "That email address is already is use");
if($this->form_validation->run()){
$this->load->model('model_users');
if ($this->model_users->add_user()){
echo "user has been added";
} else {
echo "Something went wrong";
}
$this->model_users->add_user();
} else {
$this->load->view('view_signup');
}
}
This function then makes a call to "model_users" and runs the function "add_user":
public function add_user(){
$data = array(
'email' => $this->input->post('email'),
'password' => $this->input->post('password')
);
$query = $this->db->insert('users', $data);
if ($query){
return true;
} else {
return false;
}
}
So this codes adds the data in the database fine. The validation works great. But for some reason it adds every user twice. I've tried to figure out what causes this problem, but I cannot seem to find out why.
I've also created another small piece of code where you can add page-categories into the database, the code is very similar, but it does not post twice.
You call
$this->model_users->add_user()
twice.
Once in the if statement as a condition and again after the else. Remove the second call.
$this->model_users->add_user() is called twice once inside if() and once after if else.
if ($this->model_users->add_user()){
echo "user has been added";
} else {
echo "Something went wrong";
}
$this->model_users->add_user();
I think you want to remove the below one.
I've developed a simple login system which works ok but fails, and I need to know why
QUESTION: How to show what is causing the fail. This is not a validation error but an error either with the data being passed to MySQL or the query somehow failing
here's the db function:
function login($email,$password)
{
$this->db->where("email",$email);
$this->db->where("password",$password);
$query=$this->db->get("users");
if($query->num_rows()>0)
{
foreach($query->result() as $rows)
{
//add all data to session
$newdata = array(
'user_id' => $rows->id,
'user_name' => $rows->username,
'user_email' => $rows->email,
'logged_in' => TRUE,
);
}
$this->session->set_userdata($newdata);
return true;
}
return false;
}
And here's the logic:
public function login()
{
$this->load->library('form_validation');
// field name, error message, validation rules
$this->form_validation->set_rules('email', 'Your Email', 'trim|required|valid_email');
$this->form_validation->set_rules('password', 'Password', 'trim|required|min_length[4]|max_length[32]');
if($this->form_validation->run() == FALSE)
{
$this->signin();
}
else
{
$email=$this->input->post('email');
$password=md5($this->input->post('pass'));
$result=$this->user_model->login($email,$password);
if($result)
{
$this->dash();
}
else
{
$data['title']= 'Login Error';
$this->load->view('nav/header', $data);
$this->load->view('login', $data);
$this->load->view('nav/footer', $data);
}
}
}
I know the error is happening as I redirect back to login page if fail and change title text to show me (only in testing mode for right now) - but how can I find out what is going wrong with the query?
You can use log_message and check the logs if the y behave as expected:
http://ellislab.com/codeigniter/user-guide/general/errors.html
I usually just use echo '<pre>'; print_r($query->result());die; just after the $query is formed.
It's faster.
$this->db->where("email",$email);
$this->db->where("password",$password);
$query=$this->db->get("users");
echo $this->db->last_query();
die();
you can echo the query you just did by using $this->db->last_query() this will show the query that your made with the values, and check if the query is valid.
read more at http://ellislab.com/codeigniter/user-guide/database/helpers.html
I have a form on my website header where i allow the user to log in with his username/password... then i POST to /signin page and check if the username exists to allow the user to log in.. if there is a problem upon login i output these errors...
i tried using the following code to show a custom error but with no luck
if ($this->form_validation->run() == false){
$this->load->view("login/index", $data);
}else{
$return = $this->_submitLogin();
if ($return == true){
//success
}else{
$this->form_validation->set_message('new_error', 'error goes here');
//error
}
$this->load->view("login/index", $data);
}
how does set_message work and if this is the wrong method, which one allow me to show a custom error in this case?
EDIT :
validation rules:
private $validation_rules = array(
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'trim|required|callback__check_valid_username|min_length[6]|max_length[20]|xss_clean'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'trim|required|min_length[6]|max_length[32]'
),
);
The set_message method allows you to set your own error messages on the fly. But one thing you should notice is that the key name has to match the function name that it corresponds to.
If you need to modify your custom rule, which is _check_valid_username, you can do so by perform set_message within this function:
function _check_valid_username($str)
{
// Your validation code
// ...
// Put this in condition where you want to return FALSE
$this->form_validation->set_message('_check_valid_username', 'Error Message');
//
}
If you want to change the default error message for a specific rule, you can do so by invoking set_message with the first parameter as the rule name and the second parameter as your custom error. E.g., if you want to change the required error :
$this->form_validation->set_message('required', 'Oops this %s is required');
If by any chance you need to change the language instead of the error statement itself, create your own form_validation_lang.php and put it into the proper language folder inside your system language directory.
As you can see here, you can display the custom error in your view in the following way:
<?php echo form_error('new_error'); ?>
PS: If this isn't your problem, post your corresponding view code and any other error message that you're getting.
The problem is that your form is already validated in your IF part! You can fix the problem by this way:
if ($this->form_validation->run() == false){
$this->load->view("login/index", $data);
}else{
$return = $this->_submitLogin();
if ($return == true){
//success
}else{
$data['error'] = 'Your error message here';
//error
}
$this->load->view("login/index", $data);
}
In the view:
echo $error;
The CI way to check user credentials is to use callbacks:
$this->form_validation->set_rules('username', 'Username', 'callback_username_check');
...
public function username_check($str) {
// your code here
}
I recommend you to read CI documentation: http://codeigniter.com/user_guide/libraries/form_validation.html
The way I did this was to add another validation rule and run the validation again. That way, I could keep the validation error display in the view consistent.
The following code is an edited excerpt from my working code.
public function login() {
$this->form_validation->set_rules('email', 'Email', 'required');
$this->form_validation->set_rules('password', 'Password', 'required');
$data['content'] = 'login';
if($this->form_validation->run()) {
$sql = "select * from users where email = ? and password = ?";
$query = $this->db->query($sql, array($this->input->post('email'), $this->input->post('password')));
if($query->num_rows()==0) {
// user not found
$this->form_validation->set_rules('account', 'Account', 'callback__noaccount');
$this->form_validation->run();
$this->load->view('template', $data);
} else {
$this->session->set_userdata('userid', $query->id);
redirect('/home');
}
} else {
$this->load->view('template', $data);
}
}
public function _noaccount() {
$this->form_validation->set_message('_noaccount', 'Account must exist');
return FALSE;
}
Require Codeigniter 3.0
Using callback_ method;
class My_controller extends CI_Controller {
function __construct() {
parent::__construct();
$this->form_validation->set_message('date_control', '%s Date Special Error');
}
public function date_control($val, $field) { // for special validate
if (preg_match("/^[0-9]{2}.[0-9]{2}.[0-9]{4}$/", $val)) {
return true;
} else {
return false;
}
}
public function my_controller_test() {
if ($this->input->post()) {
$this->form_validation->set_rules('date_field', 'Date Field', 'trim|callback_date_control[date_field]|xss_clean');
if ($this->form_validation->run() == FALSE) {
$data['errors']=validation_errors();
$this->load->view('my_view',$data);
}
}
}
}
Result:
if date = '14.07.2017' no error
if date = '14-7-2017' Date Field Date Special Error