I have a tables named as ideyalar and persons.
In the registration page users can not create their profile if the username taken before.
And every user can create their ideas. But there I to face the problem that; users CAN CREATE the ideas with the same name.
I want to restrict this. But I don't know how..
If you help me, I'll be glad.
Thanks. Best regards.
P.S: I should use CUniqueValidator, but don't know how..
IdeyalarController code:
public function actionCreate()
{
$model = new Ideyalar;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Ideyalar']))
{
$model->attributes=$_POST['Ideyalar'];
$model->istifade = "1";
$model->idcontact = Yii::app()->user->getId();
if($model->save()){
// if($model->validate()) {
$command = Yii::app()->db->createCommand();
$command->insert ('mqrup', array(
'idperson'=> Yii::app()->user->getId(),
'idideya'=>$model->idideya));
$this->redirect(array('viewm','id'=>$model->idideya));
// }
}
}
$this->render('create',array(
'model'=>$model,
));
}
This is in your model file, not the controller under the method rules you should have the following rule:
array('your_attribute', 'unique'),
So you will have something like
public function rules()
{
return array(
//some rules
array('your_attribute', 'unique'),
);
}
See the wiki for more details
Related
I have a Yii form accept first name, last name and email from user. Using an add more link, users can add multiple rows of those three elements.
For email validation, unique and required are set in model rules and everything works fine. I am using JavaScript to create addition row on clicking add more link.
Problem
On the first row my values are John, Newman, johnnewman#gmail.com and the second row, i'm entering Mathew, Heyden, johnnewman#gmail.com. In this case email address is duplicated. None of the validation rules (require and unique) is capable of validating this. Can some one suggest a better method to validate this ?
Update:
I created a custom validation function and i guess this is enough to solve my problem. Can someone tell me how to access the whole form data / post data in a custom validation function ?
public function uniqueOnForm($attribute){
// This post data is not working
error_log($_REQUEST, true);
$this->addError($attribute, 'Sorry, email address shouldn\'t be repeated');
}
You can try this:
<?php
public function rules()
{
return array(
array('first_name', 'checkUser')
);
}
public function checkUser($attribute)
{
if($this->first_name == $this->other_first_name){
$this->addError($attribute, 'Please select another first name');
}
}
?>
You can also look into this extension
You can write custom validator:
//protected/extensions/validators
class UniqueMailValidator extends CValidator
{
/**
* #inheritdoc
*/
protected function validateAttribute($object, $attribute)
{
$record = YourModel::model()->findAllByAttributes(array('email' => $object->$attribute));
if ($record) {
$object->addError($attribute, 'Email are exists in db.');
}
}
}
// in your model
public function rules()
{
return array(
array('email', 'ext.validators.UniqueMailValidator'),
...
Or better try to use THIS
public function rules(){
return array(
//other rules
array('email', 'validEmail'),
)
}
public function validEmail($attribute, $params){
if(!empty($this->email) && is_array($this->email)){
$isduplicate = $this->isDuplicate($this->email);
if($isduplicate){
$this->addError('email', 'Email address must be unique!');
}
}
}
private function isDuplicate($arr){
if(count(array_unique($arr)) < count($arr)){
return true;
}
else {
return false;
}
}
because you are using tabular input (multiple row) , so make sure input field as an array. might be like this :
<?php echo $form->textField($model, 'email[]'); ?>
I got this code:
public function actionJoin() {
$user = new RUser;
if (isset($_POST['RUser']))
$user->attributes = $_POST['RUser'];
$this->render('join',
array(
'user' => $user
)
);
}
Which will not yet allow user to register. What I want to know is how to send data back to user. I mean, if user form haven't passed verification I have to send some data back, so there is no need for user to re-enter it again.
I can do so with this:
$user->mail = $_POST['RUser']['mail'];
But it's looks like dropping back to plain PHP and not using powers of the framework here.
Addition. Publishing RUser class, if needed:
class RUser extends CFormModel
{
public $mail;
public $alias;
public function safeAttributes()
{
return array(
'mail', 'alias'
);
}
}
Which version of Yii you use.
In Yii 1.1, there are no safeAttributes. You use the followings,
public function rules()
{
return array(
array('mail, alias', 'safe'),
);
}
Below is the relation between three tables I have.
Now, while creating a new user through user/create action, the form takes input for both user table fields and the unit name. The unit name here isn't a dropdown (using that is not an option), but a textfield. If the unit name entered in the form doesn't exist in the unit table, I need to insert it in the unit table and then save the relation/reference in the user_unit table. If it exists I just update the user_unit table. I am able to get it kind of working by declaring the unitname property in the User model and then associating it with the form, then in the controller I check if the unit name entered exists in unit table. If it exists then I update the UserUnit model if it doesn't then I create the unit and then update UserUnit. It works, except that I am not able to associate the unit name to the form when updating the record. The userunit relationship is a HAS_MANY one and I guess that is creating some issue here. Could anyone suggest me how to approach solving it?
Here's the user/create action
$model = new User;
$modeluserunit = new UserUnit;
$user_group=Yii::app()->user->group;
if(isset($_POST['User']))
{
$model->attributes=$_POST['User'];
//$modeluserunit->attributes=$_POST['UserUnit'];
$valid=$model->validate();
if($valid)
{
if($model->save(false))
{
$Userunitmodel = Unit::model()->findByAttributes(array('name'=>$model->unitplaceholder,'groupId'=>$user_group));
if (count($Userunitmodel)!=0)
{
$modeluserunit->UserId = $model->id;
$modeluserunit->unitId = $Userunitmodel->id;
if ($modeluserunit->save())
{
Yii::app()->user->setFlash('success', "User created!");
$this->redirect(array('view','id'=>$model->id));
}
}
else if (count($Userunitmodel)==0)
{
$unitmodel = new Unit;
$unitmodel->name=$model->unitplaceholder;
$unitmodel->communityId=$user_group;
if ($unitmodel->save())
{
$modeluserunit->UserId = $model->id;
$modeluserunit->unitId = $unitmodel->id;
if ($modeluserunit->save())
{ Yii::app()->user->setFlash('success', "User created!");
$this->redirect(array('view','id'=>$model->id));
}
}
}
}
}
}
$this->render('create', array(
'model'=>$model,
'modeluserunit'=>$modeluserunit,
));
The user/update action
$model=$this->loadModelupdate($id);
if(isset($_POST['User']))
{
$model->attributes=$_POST['User'];
if($model->save())
Yii::app()->user->setFlash('success', "User updated!");
$this->redirect(array('view','id'=>$model->id));
}
$this->render('update',array(
'model'=>$model,
));
And the loadModel function
$criteria=new CDbCriteria();
$criteria->compare('t.id',$id);
$criteria->compare('unit.groupId',Yii::app()->user->group);
$model = User::model()->with(array('UserUnits' => array('with' => 'unit')))->find($criteria);
if($model===null)
throw new CHttpException(404,'The requested page does not exist.');
return $model;
The relationship in the User Model
return array(
'userUnits' => array(self::HAS_MANY, 'UserUnit', 'userId'),
);
You should use form model for this purpose. At the end of validation, you just create user, then create new unit with given name, and then create new user_unit feeding freshly created user id and unit id.
Read more Yii Definitive Guide - Model and CFormModel.
Try this at home:
<? /*** stuff for your model User ***/
// store all ids from rela Model
public $selectedIds;
public function relations()
{
return array(
'userUnits' => array(self::MANY_MANY, 'Unit', 'UserUnit(userId, unitId)','index'=>'id'),
);
}
public function afterFind()
{
// "userUnits" is defined in relations()
$this->selectedIds = array_keys($this->userUnits);
parent::afterFind();
}
?>
After your User Model is loaded for update-action, all assigned Groups (ids) are in $selectedIds.
So you can iterate over it and build your ActiveForm Inputs.
I currently have 1 table, Users which looks like this
|**id**|**username**|**password**|**role**|**email**|
I'm using CakePHP's form helper to automatically fill in editable form fields. I'm creating an edit page in which users can change there username/password/email, but should NOT be able to change their role. I'm currently checking to make sure the user hasn't injected a role POST field into the request and was wondering if there is any better way to do this? It's trivial in this scenario with such a small table, but I can see this becoming tiresome on fields/tables with a large amount of columns. My current edit action looks like this.
public function edit($id = null)
{
$this->User->id = $id;
if(!$this->User->exists())
{
throw new NotFoundException('Invalid user');
}
$userToEdit = $this->User->findById($id);
if(!$userToEdit)
{
throw new NotFoundException('Invalid user');
}
if($this->getUserRole() != 'admin' && $userToEdit['User']['owner'] != $this->Auth->user('id'))
{
throw new ForbiddenException("You do not have permission to edit this user");
}
if($this->request->is('post') || $this->request->is('put'))
{
//Do not reset password if empty
if(empty($this->request->data['User']['password']))
unset($this->request->data['User']['password']);
if(isset($this->request->data['User']['role']))
unset($this->request->data['User']['role']);
if($this->User->save($this->request->data))
{
$this->set('success', true);
}
else
$this->set('success', false);
}
else
{
$this->request->data = $this->User->read();
//Prevent formhelper from displaying hashed password.
unset($this->request->data['User']['password']);
}
}
The third parameter of save() method lets you to define the list of fields to save. Model::save() docs
$this->User->id = $this->Auth->user('id');
$this->User->save($this->request->data, true, array('username', 'email'))
In my CakePHP application, I have setup the PersistantValidation plugin to validate my forms on the model level thanks to a kind previous suggestion. The plugin essentially makes it so that you can use model validation on a partial without having it redirect to the underlying page (ie. the register.ctp view or the login.ctp view, for example).
The validation works great for the login form, but it's not working properly on the user registration form for some reason.
The controller looks like this:
function register() {
if(!empty($this->data)) {
$name = $this->data['User']['name'];
$email = $this->data['User']['email'];
$password = $this->Password->generatePassword();
$this->data['User']['password'] = $this->Auth->password($password);
$this->User->create();
if($this->User->save($this->data)) {
$this->Session->setFlash(__('Your account has been created!', true));
$this->redirect(array('controller' => 'users', 'action' => 'offers'));
} else {
$this->redirect($this->referer());
}
}
}
The PresistentValidation component is also properly setup and included, since it works just fine in the login() function in the same controller. When I run this code, nothing happens. There is no redirect away from the partial, which is good, but the errors don't show up. Also, the errors do show up going to the register.ctp view, which means it isn't a problem with the validations themselves.
Does anyone have any ideas?
function register() {
if(!empty($this->data)) {
$this->data['User']['password'] = $this->Auth->password($password);
if($this->User->save($this->data)) {
$this->Session->setFlash(__('Your account has been created!', true));
$this->redirect(array('controller' => 'users', 'action' => 'offers'));
} else {
$this->redirect($this->referer());
}
}
}