Is there a way to display error messages underneath the input fields of a form if a field didn't pass validation? Can I somehow process form in the same action (User/index in my case) that the form is displayed and then send those error messages to view? What I have is : index.volt:
<div class="loginForm">
<form action=<?= $form->getAction(); ?> method="POST">
<label for="username">Username: </label>
<?= $form->render('username'); ?>
<br/>
<label for="password">Password: </label>
<?= $form->render('password'); ?>
<br>
<?= $form->render('login'); ?>
</form>
</div>
LoginForm.php:
<?php
use Phalcon\Forms\Form,
Phalcon\Forms\Element\Text,
Phalcon\Forms\Element\Password,
Phalcon\Forms\Element\Submit,
Phalcon\Validation\Validator\PresenceOf,
Phalcon\Validation\Validator\StringLength;
class LoginForm extends Form {
public function initialize()
{
$this->setAction('login');
$username = new Text('username');
$username->addValidator(new PresenceOf(array (
'message' => 'Can\'t be empty'
)));
$password = new Password('password');
$password->addValidator(new PresenceOf(array (
'message' => 'Can\'t be empty'
)));
$submit = new Submit('login', array('value' => 'Login'));
$this->add($username);
$this->add($password);
$this->add($submit);
}
}
And UserController.php:
<?php
class UserController extends \Phalcon\Mvc\Controller
{
/**
* login form
* #var LoginForm
*/
private $_loginForm;
public function initialize()
{
$this->_loginForm = new LoginForm();
}
public function indexAction()
{
$this->view->setVar('form', $this->_loginForm);
}
public function loginAction()
{
if($this->request->isPost()) {
if (!$this->_loginForm->isValid($this->request->getPost())) {
foreach ($this->_loginForm->getMessages() as $message) {
echo $message. '<br />';
// redirect to User/index and pass error messages to view to display them to a user
}
}
}
}
}
EDIT:
Or it would be even better to process this form on the same action that it is displayed. How can I do this?
First, what you have provided in your index.volt isn't volt content. See here how to configure Volt and use the Volt language in your views.
What you're asking for is called flashing messages in Phalcon.
Unfortunately, in the current version you can just flash messages based on type(success, error, warning, etc.) but you can create your own type, so let's fake that the type means the input name.
UserController.php
...
public function loginAction()
{
if($this->request->isPost()) {
if (!$this->_loginForm->isValid($this->request->getPost())) {
$messages = $this->_loginForm->getMessages();
$userMessage = $messages->filter('username');
if(count($userMessage))
$this->flash->message('username', $userMessage[0]);
$passMessage = $messages->filter('password');
if(count($passMessage))
$this->flash->message('username', $passMessage[0]);
return $this->dispatcher->forward(["action" => "index"]);
} else {
//Login
}
}
index.volt
<div class="loginForm">
<form action="{{form.getAction()}}" method="POST">
<label for="username">Username: </label>
{{form.render('username')}}<br/>
{{ flash.has('username') ? flash.output('username') : '' }}
<label for="password">Password: </label>
{{form.render('password')}}<br>
{{ flash.has('password') ? flash.output('password') : '' }}
{{form.render('login')}}
</form>
</div>
Related
would like some advice/help on how to connect form controller to post form method in my CI site. I want to data submitted from one viewer to another. Thank you for the help!!
Here is the controller Im using (Form.php), took if from another site:
Form.php
<?php
class Form extends CI_Controller {
public function __construct() {
parent::__construct();
}
// Show form in view page i.e view_page.php
public function form_show() {
$this->load->view("addEdit");
}
// When user submit data on view page, Then this function store data in array.
public function data_submitted() {
$data = array(
'file_name' => $this->input->post('file'),
'title' => $this->input->post('title')
);
// Show submitted data on view page again.
$this->load->view("profile", $data);
}
}
?>
Its to connect to this code:
addEdit.php
<form method="post" action="postAction.php" enctype="multipart/form-data">
<div class="form-group">
<label>Image</label>
<?php if(!empty($imgData['file_name'])){ ?>
<img src="uploads/images/<?php echo $imgData['file_name']; ?>">
<?php } ?>
<input type="file" name="image" class="form-control" >
</div>
<div class="form-group">
<label>Title</label>
<input type="text" name="title" class="form-control" placeholder="Enter title" value="<?php echo !empty($imgData['title'])?$imgData['title']:''; ?>" >
</div>
Back
<input type="hidden" name="id" value="<?php echo !empty($imgData['id'])?$imgData['id']:''; ?>">
<input type="submit" name="imgSubmit" class="btn btn-success" value="SUBMIT">
</form>
When I first tried to make it work I got this error:
404 Page Not Found
The page you requested was not found.
http://culturedkink.com/index.php/register/postAction.php(the url)
postAction.php is the form Im trying to get the data to work from
The end result is to have info submitted from addEdit.php be seen on profile.php with the help of postAction.php
make routes for it first.
config/routes.php
$route['add'] = 'Controller_name/data_submitted';
$route['edit/(:any)'] = 'Controller_name/data_submitted/$1';
where is your add/edit button put this there
for add
Add New
for edit button
$row['id'] is an example i m giving. you can get data by name and id..whatever you want.
Update
//controller
public function data_submitted($id=0) {
$data=array();
$data['dataDetails']=$this->get_profile_data_by_id($id);
$data['view'] = 'folder_name/addEdit';
if ($id > 0) {
$profileArray = [
'file_name' => $this->input->post('file'),
'title' => $this->input->post('title')
];
if ($this->User_model->editById($id, $profileArray)) {
$id = $id;
}
}
else{
$profileArray = [
'file_name' => $this->input->post('file'),
'title' => $this->input->post('title')
];
if ($this->User_model->add($id, $profileArray)) {
$id = $id;
}
}
$this->load->view("profile", $data);
}
form view page
<?php echo isset($dataDetails) ? "Update" : "Add"; ?>
First check your form method and action. Your action does not exist. First check how CI works with form. The action should have a method declared in a controller. The url looks like this,
When you submit the form the data will be submitted in this method. Whatever you need to do with this form data you can do that in this method.
in a form i'm working on, it will check if username was empty on registration and prompt to input a username before a user ads a comment.
i tired adding unique in my rules in my comment class, but it doesn't validate on ajax post
class Comment extends CActiveRecord
{
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
return array(
array('username', 'unique','className'=>'User','attributeName'=>'username','message'=>"Username already exists"),
);
}
in my view
echo '<div class="form-group">
'.$form->labelEx($user,'username', array('class'=>'col-md-3 control-label')).'
<div class="col-md-9">
'.$form->textField($user,'username',array('class'=>'form-control input-md')).'
'.$form->error($user,'username').'
</div>
</div>';
//the output looks like this
/*<label class="col-md-3 control-label" for="User_username">Username</label>
<div class="col-md-9">
<input class="form-control input-md" name="User[username]" id="User_username" type="text" value="" />
<div class="errorMessage" id="User_username_em_" style="display:none"></div>
</div>*/
in my controller
public function actionCreate()
{
/** #var Comment $comment */
$comment = Yii::createComponent($this->module->commentModelClass);
// Uncomment the following line if AJAX validation is needed
$a=new User;
$b=new Comment;
$this->performAjaxValidation(array($a,$b));
//end of Ajax validation
.....
.....
.....
}
/**
* Performs the AJAX validation.
* #param CModel the model to be validated
*/
protected function performAjaxValidation($model)
{
if(isset($_POST['ajax']) && $_POST['ajax']==='ext-comment-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
}
the return Json is
{"Comment_username":["Nick Name cannot be blank."],"Comment_title":["Review Title cannot be blank."]}
any idea what i'm doing wrong?
problem solved.
had to add
array('username', 'unique'),
in my User class and NOT in my comment class
I have following routes
Route::controller('users', 'UsersController');
Controllers
class UsersController extends BaseController {
protected $layout = "layouts.login";
public function __construct() {
$this->beforeFilter('csrf', array('on'=>'post'));
$this->beforeFilter('auth', array('only'=>array('getDashboard')));
}
public function getRegister() {
$this->layout->content = View::make('users.register');
}
public function logout() {
Auth::logout();
return Redirect::to('users/login')
->with('message', 'Good Bye')
->withInput();
}
public function getLogin() {
$this->layout->content = View::make('users.login');
}
public function postSignin() {
if (Auth::attempt(array('email'=>Input::get('email'), 'password'=>Input::get('password'),'role'=>'admin'))) {
return Redirect::to('mix/dashboard')->with('message', 'You are now logged in!');
}
else {
return Redirect::to('users/login')
->with('message', 'Your username/password combination was incorrect')
->withInput();
}
}
public function postCreate() {
$validator = Validator::make(Input::all(), User::$rules);
if ($validator->passes()) {
// validation has passed, save user in DB
$user = new User;
$user->firstname = Input::get('firstname');
$user->lastname = Input::get('lastname');
$user->email = Input::get('email');
$user->password = Hash::make(Input::get('password'));
$user->save();
return Redirect::to('users/login')->with('message', 'Thanks for registering!');
} else {
// validation has failed, display error messages
return Redirect::to('users/register')->with('message', 'The following errors occurred')->withErrors($validator)->withInput();
}
}
}
view
<div class="login-body">
<h2>SIGN IN</h2>
<form method="post" action="{{Request::root()}}/users/Signin">
<div class="control-group">
<div class="email controls">
{{ Form::text('email', null, array('class'=>'input-block-level', 'placeholder'=>'Email Address', 'data-rule-required'=>'true' ,'data-rule-email'=>'true')) }}
</div>
</div>
<div class="control-group">
<div class="pw controls">
{{ Form::password('password', array('class'=>'input-block-level', 'placeholder'=>'Password','data-rule-required'=>'true')) }}
<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
</div>
</div>
<div class="submit">
<div class="remember">
<input type="checkbox" name="remember" class='icheck-me' data-skin="square" data-color="blue" id="remember"> <label for="remember">Remember me</label>
</div>
{{ Form::submit('Login', array('class'=>'btn btn-primary'))}}
{{ Form::close() }}
<div class="forget">
<span>Forgot password?</span>
</div>
</div>
Whenever i try to login it shows tokenmismatch exception error and shows following lines of filter.php
Route::filter('csrf', function()
{
if (Session::token() != Input::get('_token'))
{
throw new Illuminate\Session\TokenMismatchException;
}
});
I have been clueless past three days...
worst is that this error automatically came , it was working fine earlier .. i did not make any changes at all !
It was client side issue
I just deleted cookies and then it start working.
You probably add the crsf filter in the /users/Signin route. You have several options:
Fistly, you can remove the crsf filter from the route.
Second, you should add the csrf token to your form input (after the <form ...> line)
{{ Form::token(); }}
Or you can change your Form declaration using the Form macro with also include the csrf token.
{{ Form::open(array('url' => 'users/Signin' ) ); }}
I hope it helps you.
Avoid having csrf on your GET routes since they don't have a token and will throw TokenMismatchException. With that said you could look at this snippet of code you could add in your controller to avoid these exceptions:
`class UserController extends BaseController {
/**
* Instantiate a new UserController instance.
*/
public function __construct()
{
$this->beforeFilter('auth', array('except' => 'getLogin'));
$this->beforeFilter('csrf', array('on' => 'post'));
$this->afterFilter('log', array('only' =>
array('fooAction', 'barAction')));
}
}
`
As you can see the CSRF filter is only being applied on the POST method and the auth one is only being applied on the getLogin controller method.
i have form like this
my form
<?php
$error = $model->getErrors();
print_r($error);
<form method="post" action="<?php echo Yii::app()->getBaseUrl(true).'/index.php/admin/user/resetpassword'?>" enctype="multipart/form-data">
<div class="row">
<label>Old Password</label><input type="password" name="oldpassword" value="<?php echo $model->email; ?>"/><span><?php if(isset($error['email'])) echo $error['email'][0]; ?></span>
</div>
<div class="row">
<label>New Password</label><input type="password" name="newpassword"/><span><?php if(isset($error['password'])) echo $error['password'][0]; ?></span>
</div>
<div class="row">
<label>Repeat Password</label><input type="password" name="repeatpassword" value="<?php echo $model->employeeid; ?>"/><span><?php if(isset($error['employeeid'])) echo $error['employeeid'][0]; ?></span>
</div>
<?php echo CHtml::submitButton($model->isNewRecord ? 'Reset Password' : 'Save'); ?>
</form>
my model class is
class User extends CActiveRecord
{
public $oldpassword;
public $newpassword;
public $repeatpassword;
/**
* #return string the associated database table name
*/
public function tableName()
{
return 'user';
}
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('email, password, employeeid, designation, manager, profilepic', 'required','except'=>'resetpassword'),
array('email','email'), array('profilepic','file','types'=>'jpg,jpeg,png','allowEmpty'=>true,'on'=>'update'),
array('email,employeeid','unique'),
array('newpassword, repeatpassword, oldpassword','required','on'=>'resetpassword'),
array('repeatpassword','compare','compareAttribute'=>'newpassword','on'=>'resetpassword'),
array('email, password, employeeid, designation, manager, profilepic', 'safe', 'on'=>'search'),
);
}
my controller function
public function actionResetPassword()
{
$model = new User('resetpassword');
if(Yii::app()->request->isPostRequest)
{
if($model->validate())
$this->redirect(array('resetpassword','msg'=>'Password successfully changed..'));
}
$this->render('resetpassword',array('model'=>$model));
}
it always giving error say "oldpassword,repeatpassword,newpassword required" even though have entered value..
can anybody help me pls
Thanks in advance
it's because you are not assigning form value to model variable...
try this in your controller
if(Yii::app()->request->isPostRequest)
{
$model->oldpassword=$_POST['oldpassword']; //will set to model variable
$model->newpassword=$_POST['newpassword'];
$model->repeatpassword=$_POST['repeatpassword'];
if($model->validate())
$this->redirect(array('resetpassword','msg'=>'Password successfully changed..'));
}
hope it may solve your problem
As mentioned by Kalpit above, you are not assigning form inputs to your model instance.
You may also solve this problem like this..
$model = new User;
if(isset($_POST['resetpassword']))
{
$model->attributes=$_POST['resetpassword'];
if($model->save())
// successfully saved, do something here
}
I'm trying to build a registration system with CodeIgniter. I have a controller called Register with the following code:
class Register extends CI_Controller {
public function index()
{
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$this->form_validation->set_error_delimiters('<span class="error">', '</span>');
$this->form_validation->set_rules('username', 'username', 'required|min_length[3]|max_length[12]|trim');
$this->form_validation->set_rules('password', 'password', 'required|min_length[2]|md5');
$this->form_validation->set_rules('email', 'email', 'required|valid_email|trim');
$this->form_validation->set_rules('artist', 'artist', 'max_length[32]|trim');
$this->form_validation->set_rules('captcha', 'CAPTCHA', 'required|trim');
$this->load->view('header');
if(!$this->form_validation->run())
{
$this->load->view('register_form');
}
else
{
$this->load->view('register_done');
}
$this->load->view('footer');
}
}
So far so good. If I go to the register page I get the registration form displayed. If I send the form and it passes the form validation checks, I get the success page, if the form has errors, I get the form back with some error messages.
Now what I want to do is the database stuff. I have some idea of how I can get the POST values from the registration form into my database, but no clue how I can check if a username or email already exists, and if so, display that error on the registration form. Here's my registration form view:
<?php $this->load->helper('form'); ?>
<?php echo form_open('register'); ?>
<ul id="register">
<ul>
<h3>Account information</h3>
<li>
<label for="username">Choose a username</label>
<input type="text" name="username" value="<?php echo set_value('username'); ?>" />
<span class="desc">The name you'd like to be known by</span>
<?php echo form_error('username'); ?>
</li>
<li>
<label for="password">Pick a password</label>
<input type="password" name="password" />
<span class="desc">The best passwords are random and more than 6 characters long</span>
<?php echo form_error('password'); ?>
</li>
<li>
<label for="email">Enter your valid email address</label>
<input type="text" name="email" value="<?php echo set_value('email'); ?>" />
<span class="desc">We'll send you an activation email</span>
<?php echo form_error('email'); ?>
</li>
</ul>
<ul>
<h3>About you</h3>
<li>
<label for="band">Who's your favorite artist?</label>
<input type="text" name="artist" value="<?php echo set_value('artist'); ?>" />
<span class="desc">Don't put Lady GaGa.</span>
<?php echo form_error('artist'); ?>
</li>
</ul>
<ul>
<h3>Security question</h3>
<li>
<label for="captcha">Enter the letters you see in the image</label>
<?php $this->load->helper('captcha');
$cap = create_captcha(array('img_path' => './captcha/', 'img_url' => 'http://localhost/captcha/', 'img_width' => 200, 'img_height' => 30));
$data = array('captcha_time' => $cap['time'], 'ip_address' => $this->input->ip_address(), 'word' => $cap['word']);
$query = $this->db->insert_string('captcha', $data);
$this->db->query($query);
echo $cap['image']; ?>
<input type="text" name="captcha" />
<?php echo form_error('captcha'); ?>
</li>
</ul>
<ul>
<h3 class="submit">
<input type="submit" value="Register" />
</h3>
</ul>
</ul>
<?php echo form_close(); ?>
As you can see, I'm taking advantage of the form_error() function of CI to display form errors right under the field, and I would like the "username already exists" error to also be displayed under the username field.
Can anyone provide some help? Even a nudge in the right direction?
Thanks!
I would strongly urge you to think about using another library that already does this very well: TankAuth. TankAuth is easily modifiable and offers email confirmation, very secure password hashing, a solid database schema, and very clean code.
There's no reason to reinvent the wheel, especially when it comes to something that's very hard to get right like user authentication.
EDIT:
For example, here's everything TankAuth provides security-wise that you'd have to code yourself (if you cared about security) - how much time would that take?
Using phpass library for password hashing (instead of unsafe md5).
Counting login attempt for bruteforce preventing (optional). Failed login attempts determined by IP and by username.
Logging last login IP-address and time (optional).
CAPTCHA for registration and repetitive login attempt (optional).
Unactivated accounts and forgotten password requests auto-expire.
You need to create a model for your controller.
Your model would look like this:
class Register_model extends CI_Model {
function register_user()
{
$data['username'] = $this->input->post('username');
$data['password'] = sha1($this->input->post('password'));
... (your other post data) ...
$this->db->insert('users', $data);
}
}
In your controller you will call the model this way:
$this->load->model('Register_model');
and the method goes here:
else
{
$this->Register_model->register_user();
$this->load->view('register_done');
}
If you want to check if the username is available, you simply put SELECT query on the first lines of the register_user() method (function).
To do the check you should have functions in your model that can look up those types of things for you:
class Model{
function getUserByEmail($email);
function getUserByUsername($username);
...
}
Then in your controller you can call these methods
...
$result = $model->getUserByEmail($_POST['email']); // You'll need to sanitize your POST
if(count($result) > 0){
// Sent error about email already existing and flag to not insert/update user
}
...
The easiest solution in CodeIgniter is to use a callback function as one of the rules in your form validation.
I've used this method myself to check the username and e-mail.
Here's the docs for it.
defined('BASEPATH') OR exit('No direct script access allowed');
class User extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->helper('form');
// Load session library
$this->load->library('session');
// Load database
$this->load->model('User_model');
}
public function index()
{
$this->load->view('index');
}
public function project()
{
$this->data['posts'] = $this->User_model->getPosts(); // calling Post model method getPosts()
$this->load->view('tables', $this->data);
// $this->load->aview('project');
}
public function get_project()
{
$this->User_model->get_project($data);
}
public function signin()
{
$data = array(
'email' => $this->input->post('email'),
'password' => $this->input->post('password')
);
$this->User_model->signin($data);
}
public function logout()
{
$this->session->unset_userdata($_SESSION['email']);
// $this->session->sess_destroy();
redirect('User');
}
public function signup()
{
$data = array(
'name' => $this->input->post('name'),
'phone' => $this->input->post('phone'),
'email' => $this->input->post('email'),
'password' => $this->input->post('password')
);
if($this->User_model->signup($data))
{
echo "no insert";
}
else
{
$this->load->view('index', $data);
}
}
}
<?php
Class User_model extends CI_Model {
function __construct() {
parent::__construct();
$this->load->library('session');
}
public function signup($data)
{
$this->db->insert('user_signup',$data);
}
public function getPosts()
{
$this->db->select("*");
$this->db->from('user_data');
$query = $this->db->get();
return $query->result();
}
public function signin($data)
{
$this->db->where('email',$data['email']);
$this->db->where('password',$data['password']);
$query=$this->db->get('user_signup');
if($query->num_rows()==1){
$_SESSION['email'] = $data['email'];
$this->load->view('popup',$data);
return true;
}
else{
echo "no";
return false;
}
}
}