public function actionUpdateprofile(){
$user = User::model()->findByPk($_POST['User']['user_id']);
$profile = Profile::model()->findByPk($_POST['User']['user_id']);
if(isset($_POST['User']) || isset($_POST['Profile'])){
$user->attributes = $_POST['User'];
$profile->attributes = $_POST['Profile'];
$user->save();
$profile->save();
}
}
I did this code for update the value in profile and user table. But it's not working.
If i send $_POST['Profile']['email'] = 'abc#gmail.com';
There is no error but database still showed old value. why?
What i did wrong in there?
This is the result for $profile->attributes. email still have old value.
Array
(
[user_id] => 35
[lastname] => asd
[firstname] => asrtyr
[email] => xyz.gmail.com
[phoneno] => 123456
[prof_img] =>
[phoneno2] => 0
[agentKey] =>
[fb_id] =>
)
I suggest you to add error reporting like below
if(!$user->save()){
echo 'Error to save user model<br />';
var_dump($user->getErrors());
}
if(!$profile->save()){
echo 'Error to save profile model<br />';
var_dump($profile->getErrors());
}
I'd reccommend to check possible errors on saving:
istead of
$user->save();
you could use
if (!$user->save()){
print_r($user->getErrors());
}
First, do this to check if it has to do with validation (look example below) and test it:
public function actionUpdateprofile(){
$user = User::model()->findByPk($_POST['User']['user_id']);
$profile = Profile::model()->findByPk($_POST['User']['user_id']);
if(isset($_POST['User']) || isset($_POST['Profile'])){
$user->attributes = $_POST['User'];
$profile->attributes = $_POST['Profile'];
$user->save(false);
$profile->save(false);
}
}
Which will bypass the validation. If it works, and you really need the validation (and you most certainly do), remove the false's I added and build it up by following the validation guide. The thing to remember is: the property not associated with a rule in rules() array is considered unsafe and is NOT saved into the database. This might be your problem.
Related
I have been following a tutorial on youtube about CodeIgniter. The tutorial only relies on $username $_SESSION variable and doesn't touch on other aspects of $_SESSIONs. According to code igniter documentation regarding $_SESSION you can simply call the session super global with the key. This is where my problem starts.
VAR_DUMP($_SESSION)
a var_dump of $_Session provides the following info (I have truncated other fields to keep it shorter)
array (size=5)
'__ci_last_regenerate' => int 1526800056
'' => null
'userID' =>
array (size=1)
0 =>
array (size=14)
'userID' => string '1' (length=1)
'firstname' => string 'Tim' (length=3)
'lastname' => string 'Coetzee' (length=7)
'pword' => string 'xyz' (length=4)
'email' => string 'someone#gmail.com' (length=17)
What I want to do
I simply want to be able to call a $_SESSION super global as such $_SESSION['email'] or $_SESSION['userID'] The way I want to access the session vars is EXACTLY as you should do it according to docs, thus I believe my
problem is in my controller() or the way im setting the session data() as can be viewed below
Problem
Lets say I want to display the userID from above var_dump() info in the view just as a test I do the following... echo $_SESSION['userID'];
The above leads to error
Message: Object of class stdClass could not be converted to string
Okay sure enough however what is the object name I should call to get say firstname ?
I tried this as per official docs
echo $this->session->firstname AND echo $this->user_data('userID');
which resulted in same error.
I realize the $_SESSION data seems to be saved in a multi-dimensional array so I tried a foreach() as such
foreach ($_SESSION as $sessions)
{
foreach ($sessions as $value)
{
echo $value;
}
}
which gives me the error:
Message: Invalid argument supplied for foreach()
However after two more similar errors by the last iteration it returns the values of all the sessions, so Im guessing im doing something wrong in the loop.
Code Follows Below
Users_model.php
public function login($username, $password)
{
// Validate
$this->db->where('username', $username);
$this->db->where('pword', $password);
$stmnt = $this->db->get('users');
if($stmnt->num_rows() == 1){
return $stmnt->row(1);
} else {
return false;
}
}
Controller.php
public function login(){
$data['title'] = 'Sign In';
$this->form_validation->set_rules('username', 'Username', 'required');
$this->form_validation->set_rules('password', 'Password', 'required');
if($this->form_validation->run() === FALSE){
$this->load->view('templates/header');
$this->load->view('users/login', $data);
$this->load->view('templates/footer');
} else {
// Get username
echo $username = $this->input->post('username');
// Get and encrypt the password
echo $password = $this->input->post('password');
// Login user
$user_id = $this->users_model->login($username, $password);
if($user_id){
// Create session
$user_data = array(
'username' => $username,
'userID' => $user_id,
'logged_in' => true
);
$username = user_data ['username'];
$userID = user_data ['userID'];
$logged_in = user_data ['logged_in'];
$this->session->set_userdata($username );
$this->session->set_userdata($userID );
$this->session->set_userdata($logged_in);
// Set message
//$this->session->set_flashdata('user_loggedin', 'You are now logged in');
redirect('pages/index');
} else {
// Set message
// $this->session->set_flashdata('login_failed', 'Login is invalid');
redirect('users/failed');
}
}
}
$config.php
$autoload['libraries'] = array('form_validation','session', 'pagination');
Any help advice, or constuctive criticism appreciated
Hope this will help you :
if you don't want to change your model query set session like this
$user = $this->users_model->login($username, $password);
if($user)
{
$user_data = array(
'username' => $username,
'userID' => $user->id,
'logged_in' => true
);
$this->session->set_userdata($user_data);
//$this->session->set_flashdata('user_loggedin', 'You are now logged in');
redirect('pages/index');
}
else
{
// Set message
// $this->session->set_flashdata('login_failed', 'Login is invalid');
redirect('users/failed');
}
print individual session key like this :
echo $this->session->userdata('username');
echo $this->session->userdata('userID');
echo $this->session->userdata('logged_in');
and whole session like this :
print_r($this->session->userdata());
Note : for CI Version 3.1.8, access like this :
$username = $this->session->username;
$userid = $this->session->userID;
for more https://www.codeigniter.com/user_guide/libraries/sessions.html#retrieving-session-data
When you echo $_SESSION['userID']; you are trying to display whole array like string, it is immposible.
Also you cannot use two foreach loops because in the first cycle of outer loop there is integer ('__ci_last_regenerate' => int 1526800056) as argument of inner loop, so you get error.
Following your session array structure you can call to fields like that:
echo $_SESSION['userID'][0]['firstname'];
or better:
$name = $this->session->userdata('firstname');
When I'm registering a new user in the Laravel framework, I'm currently doing it like this,
// Creating a new user
$user = new User;
$user->firstname = $data['firstname'];
$user->lastname = $data['lastname'];
$user->email = $data['email'];
$user->password = bcrypt($data['password']);
$user->save();
This works great, and I am able to login to the application. However, I want the user to have an option to change their passwords in their settings page. Doing this, i used the same technique, using
$newPass = bcrypt($response->new_password);
and updating the user field. However, after doing this, I'm not able to login? I'm using the built in authentication service in laravel for the registration/login.
What am I doing wrong here? and should i do it another way?
I also tried to bcrypt my current password, and i got an completely different hash than the one stored in the database.
This so confusing..
Updated with controller code,
// Validation
$this->validate($request, [
'email' => 'email',
'password' => 'min:8|confirmed',
'current_password' => 'required',
]);
// Getting the user ID
$userId = Auth::id();
// Dummy hack check, change later.
if(!Auth::attempt(['id' => $userId, 'password' => $request->current_password]))
{
return redirect('settings')->with('alert','current password is wrong.');
}
// Everything is validated and ok to proceed
if($request->email)
{
$data['email'] = $request->email;
}
if($request->password)
{
$data['password'] = bcrypt("helloworld");
}
$user = User::where('id',$userId)->update($data);
dd($data);
Dump data for the inputs,
+request: ParameterBag {#40 ▼
#parameters: array:5 [▼
"_token" => "JQIIuCjiKQmbK0X5zCM6czYD1vIoh4PGjLO4qrFm"
"email" => "testing#gmail.com"
"password" => "thisisnewpass"
"password_confirmation" => "thisisnewpass"
"current_password" => "helloworld"
]
}
This code is closer to how Laravel handles resetting a user's password internally. Give it a try.
// Getting the User
$user = Auth::user(); // Gets the currently logged in User
$credentials = [
'id' => $user->id,
'password' => $request->input('current_password')
];
// Make sure current password is correct
if (!Auth::validate($credentials)) { // Checks the User's credentials
return redirect('settings')->with('alert','current password is wrong.');
}
// Change the password
if ($request->has('password')) {
$user->password = bcrypt($request->input('password'));
}
// Save any changes
$user->save();
It looks like you're using the same form to update the User's email address too, so update the code to fit your needs.
Storing the password in an new variable seems to fix the issue (not sure why?) however, this is the code that made everything work,
// Validation
$this->validate($request, [
'email' => 'email',
'password' => 'min:8|confirmed',
'current_password' => 'required',
]);
// Getting the user ID
$userId = Auth::id();
$newPassword = $request->password;
// Dummy hack check, change later.
if(!Auth::attempt(['id' => $userId, 'password' => $request->current_password]))
{
return redirect('settings')->with('alert','Wrong password.');
}
// Everything is validated and ok to proceed
if($request->email)
{
$data['email'] = $request->email;
}
if($request->password)
{
$data['password'] = bcrypt($newPassword);
}
// Getting, and checking if the current password is corrent.
$user = User::where('id',$userId)->update($data);
echo $newPassword . "<br><br>";
dd($data);
If there is any explanations that i don't see, please let me know why. However, it's working now.
For Laravel in year 2017, this is how we roll:
//create a setter method in your controller
public function setPasswordAttribute( $password ) {
if ( $password !== null ) {
if ( is_null(request()->bcrypt) ) {
$this->attributes['password'] = bcrypt($password);
} else {
$this->attributes['password'] = $password;
}
}
}
Check this link they all are talking about placing it in model but it works inside my own controller.
I have a good amount of experience with MVC but can't seem to figure what is going wrong here.
I'm trying to update the user's model but for some reason what should be an update is attempting to execute as an insert.
Edit: I'm using this starter site for Laravel which uses Ardent
$user = User::find(Auth::user()->id);
$user->recipient_id = "xxxxxxxxx";
if ($user->save()) {
return true;
} else {
print_r($user->errors()->all()); die();
}
The above outputs
Array (
[0] => The username has already been taken.
[1] => The email has already been taken.
[2] => The password confirmation does not match.
)
Any help would be really appreciated! I have a feeling its something trivial...
Actually while validating it uses rules of the User Model class.
This happens because use of these lines in models.
public $autoHydrateEntityFromInput = true; // hydrates on new entries' validation
public $forceEntityHydrationFromInput = true; // hydrates whenever validation is called
What you have to do is to change the rules dynamically.
$user = User::find(Auth::user()->id);
$user->recipient_id = "xxxxxxxxx";
$user::$rules['username'] = 'required|regex:/^[a-zA-Z\- ]+$/|unique:users,username,'.$user_id;
$user::$rules['email'] = 'required|email|unique:users,email,'.$user_id;
$user::$rules['password'] = 'required';
//this will ignore current username and email
if ($user->save()) {
return true;
} else {
print_r($user->errors()->all()); die();
}
I am completing my login function for my application and I'm receiving the trying to get property of non object on a few lines. The first one is shown below that does a function call to the is_user_locked method using the object property lock_date inside the user_data object. I understand that this means that at this point their is no user_data to work with so it can not use the properties. I'm curious to know how should I account for this so that I don't abuse using too many nested if statements.
if (count($user_data) == 0) {
$output = array('content' => 'The user was not found in the database!', 'title' =>
'User Not Found');
}
if ($this->is_user_locked($user_data->lock_date)) {
$output = array('content' => 'This user account is currently locked!', 'title' =>
'Account Locked');
}
Any ideas on why this could be? Any and all suggestions would be helpful.
I'm curious to know how should I account for this so that I don't
abuse using too many nested if statements.
How about something like this ?
if( $user_data ) {
// $user_data contains something so let's proceed
if ($this->is_user_locked($user_data->lock_date)) {
$output = array('content' => 'This user account is currently locked!', 'title' => 'Account Locked');
}
} else {
// Nothing in $user_data so throw Exception or display error
$output = array('content' => 'The user was not found in the database!', 'title' =>
'User Not Found');
}
See this link.
if($var): same as $var == NULL.
What seems to be happening is $user_data->lock_date should be $user_data['lock_date']. I'm not 100% sure by the code you posted but it seems you're just referencing an array element incorrectly.
Terinary operators can be used to avoid if statements
$user_data === null ? "it's null" : "otherwise it's not";
i am a huge fan of negative if checks. the idea is that if you do not get what you expect, you immediately exit. this can be getting back a result, or doing a true false check. Of course you are first going to validate the user name using CI form validation. so for example in your model, the method that checks for the user name - if the result is 0, just have it return false. Then in your controller:
// Validate the user name and other form info
// if validation passes, grab the username,
// note the TRUE, that tells CI to run it through XSS clean
$username = $this->input->post( 'username', TRUE ) ;
// if we did NOT get a user back from model, immediately go to new method
if ( ! $user = $this->users_m->_findUser($username) ) {
$this->_userNotFound(); }
// similar, if the user account is locked, go to new method
// if you return an array from model this would be $user['lock_date']
elseif ($this->isUserLocked($user->lock_date) == TRUE) {
// DO NOT try and write messages etc here. put all that in a separate method
$this->_userAccountLocked(); }
else {
// you have a $user and the user is not locked
// its tempting to write a bunch of stuff here
// do not do that. keep it clean, and go to separate method
$this->_displayAccount($user) ; }
Note that i put an underscore before all the method names - CI will automatically make those private.
Also note the Camel case for method names -- versus underscores. some people prefer it.
You could do this:
if (count($user_data) == 0) {
$output = array('content' => 'The user was not found in the database!', 'title' =>
'User Not Found');
} else if ($this->is_user_locked($user_data->lock_date)) {
$output = array('content' => 'This user account is currently locked!', 'title' =>
'Account Locked');
}
Which is pretty much identical to your initial code, but with an else thrown in.
Greetings,
I am setting up a pretty standard registration form with password field.
The problem is, after a failed submission (due to empty field, incorrect format etc), the controller reloads the registration page, but with the password field containing the hashed value of the previously entered password. How do I make it empty after each failed submission?
View:
echo $form->password('Vendor.password', array('class' => 'text-input'));
Controller:
Security::setHash('sha1');
$this->Auth->sessionKey = 'Member';
$this->Auth->fields = array(
'username' => 'email',
'password' => 'password'
);
Help is very much appreciated, thanks!
You may run into another problem down the road with cakePHP password validation.
The problem is that cake hashes passwords first, then does validation, which can cause the input to fail even if it is valid according to your rules. This is why the password is returned to the input field hashed instead of normal.
to fix this, instead of using the special field name 'password', use a different name like 'tmp_pass'. This way, cakePHP Auth won't automatically hash the field.
Here's a sample form
echo $form->create('Vendor', array('action' => 'register'));
echo $form->input('email');
echo $form->input( 'tmp_pass', array( 'label' => 'Password','type'=>'password' ));
echo $form->end('Register');
In your Vendor model, don't assign validation rules to 'password' instead assign these rules to 'tmp_pass', for example
var $validate = array('email' => 'email', 'password' => ... password rules... );
becomes
var $validate = array('email' => 'email', 'tmp_pass' => ... password rules... );
Finally, in your Vendor model, implement beforeSave().
First, see if the data validates ('tmp_pass' will be validated against your rules).
If successful, manually hash tmp_pass and put it in $this->data['Vendor']['password'] then return true. If unsuccessful, return false.
function beforeSave() {
if($this->validates()){
$this->data['Vendor']['password'] = sha1(Configure::read('Security.salt') . $this->data['User']['tmp_pass']);
return true;
}
else
return false;
}
this?
password('Vendor.password', array('class' => 'text-input','value'=>''))
In your controller:
function beforeRender() {
parent::beforeRender();
$this->data['Vendor']['password'] = '';
}