Ejuicombobox Throwing Undefined Offset Error On Specific Model Attributes - autocomplete
I downloaded the Editable combo box control with Auto-complete and added the extension. I am having problem with patient_id and problem_definition_id attributes of the model. Works fine for problem_duration_id and some other attributes. When I use them for the combo box I receive the following error:
Following is the code that i have used in my view:
$this->widget('ext.combobox.EJuiComboBox', array(
'model' => $PatientProblem,
'attribute' => 'problem_definition_id',
'id'=>'eeed',
'data'=>Yii::app()->cache->get('PATIENT_PROBLEM'),
// options passed to plugin
'assoc'=>true,
'options' => array(
'allowText' => false,),
// Options passed to the text input
'htmlOptions' => array('size' => 6),
));
Following is the my model:
<?php
/**
* This is the model class for table "patient_problem".
*
* The followings are the available columns in table 'patient_problem':
* #property integer $problem_id
* #property integer $problem_definition_id
* #property integer $patient_id
* #property integer $curr_or_history
* #property integer $patient_visit_id
* #property string $problem_notes
* #property string $chronic
* #property string $alert_on_dashboard
* #property integer $problem_duration_id
* #property integer $create_acc_id
* #property integer $create_user_id
* #property string $create_date
* #property integer $create_acc_assign_id
* #property integer $update_acc_id
* #property integer $update_user_id
* #property string $update_date
* #property integer $update_acc_assign_id
*
* The followings are the available model relations:
* #property Patient $patient
* #property ListOfValues $currOrHistory
* #property PatientVisit $patientVisit
* #property ListOfValues $problemDefinition
* #property ListOfValues $problemDuration
*/
class PatientProblem extends CActiveRecord
{
/**
* Returns the static model of the specified AR class.
* #param string $className active record class name.
* #return PatientProblem the static model class
*/
public static function model($className=__CLASS__)
{
return parent::model($className);
}
/**
* #return string the associated database table name
*/
public function tableName()
{
return 'patient_problem';
}
/**
* #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('problem_definition_id, patient_id, curr_or_history, patient_visit_id, problem_duration_id, create_acc_id, create_user_id, create_acc_assign_id, update_acc_id, update_user_id, update_acc_assign_id', 'numerical', 'integerOnly'=>true),
array('chronic, alert_on_dashboard', 'length', 'max'=>1),
array('problem_notes, problem_reported_date, create_date, update_date', 'safe'),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('problem_id, problem_definition_id, patient_id, curr_or_history, patient_visit_id, problem_notes, problem_reported_date, chronic, alert_on_dashboard, problem_duration_id, create_acc_id, create_user_id, create_date, create_acc_assign_id, update_acc_id, update_user_id, update_date, update_acc_assign_id', 'safe', 'on'=>'search'),
);
}
/**
* #return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'patient' => array(self::BELONGS_TO, 'Patient', 'patient_id'),
'currOrHistory' => array(self::BELONGS_TO, 'ListOfValues', 'curr_or_history'),
'patientVisit' => array(self::BELONGS_TO, 'PatientVisit', 'patient_visit_id'),
'problemDefinition' => array(self::BELONGS_TO, 'ListOfValues', 'problem_definition_id'),
'problemDuration' => array(self::BELONGS_TO, 'ListOfValues', 'problem_duration_id'),
);
}
/**
* #return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'problem_id' => 'Problem',
'problem_definition_id' => 'Problem Definition',
'patient_id' => 'Patient',
'curr_or_history' => 'Curr Or History',
'patient_visit_id' => 'Patient Visit',
'problem_notes' => 'Problem Notes',
'problem_reported_date'=>'Report Date',
'chronic' => 'Chronic',
'alert_on_dashboard' => 'Alert On Dashboard',
'problem_duration_id' => 'Problem Duration',
'create_acc_id' => 'Create Acc',
'create_user_id' => 'Create User',
'create_date' => 'Create Date',
'create_acc_assign_id' => 'Create Acc Assign',
'update_acc_id' => 'Update Acc',
'update_user_id' => 'Update User',
'update_date' => 'Update Date',
'update_acc_assign_id' => 'Update Acc Assign',
);
}
/**
* Retrieves a list of models based on the current search/filter conditions.
* #return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
*/
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('problem_id',$this->problem_id);
$criteria->compare('problem_definition_id',$this->problem_definition_id);
$criteria->compare('patient_id',$this->patient_id);
$criteria->compare('curr_or_history',$this->curr_or_history);
$criteria->compare('patient_visit_id',$this->patient_visit_id);
$criteria->compare('problem_notes',$this->problem_notes,true);
$criteria->compare('problem_reported_date',$this->problem_reported_date,true);
$criteria->compare('chronic',$this->chronic,true);
$criteria->compare('alert_on_dashboard',$this->alert_on_dashboard,true);
$criteria->compare('problem_duration_id',$this->problem_duration_id);
$criteria->compare('create_acc_id',$this->create_acc_id);
$criteria->compare('create_user_id',$this->create_user_id);
$criteria->compare('create_date',$this->create_date,true);
$criteria->compare('create_acc_assign_id',$this->create_acc_assign_id);
$criteria->compare('update_acc_id',$this->update_acc_id);
$criteria->compare('update_user_id',$this->update_user_id);
$criteria->compare('update_date',$this->update_date,true);
$criteria->compare('update_acc_assign_id',$this->update_acc_assign_id);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
/* The code till this line is Gii generated. All the code beyond this point is cutom code. */
public function beforeSave(){
$retval=false;
if ($this->isNewRecord){
//Handling duplicate Entries for Problem in one visit.
$criteria = new CDbCriteria;
$criteria->compare('problem_definition_id', $this->problem_definition_id);
$criteria->compare('patient_id', $this->patient_id);
$criteria->compare('patient_visit_id', $this->patient_visit_id);
$PatientProblem = $this->model()->findAll($criteria);
if (count($PatientProblem)==0){
$retval=true;
$this->setAttribute('create_date',date("Y-m-d H:i:s"));
$this->setAttribute('create_user_id',Yii::app()->user->id);
$this->setAttribute('create_acc_id',Yii::app()->user->assigner_account_id);
$this->setAttribute('create_acc_assign_id',Yii::app()->user->acc_assign_id);
}
else{
$errorMsg='';
$criteria = new CDbCriteria;
$criteria->compare('mCode','VISIT_PROBLEM_EXISTS');
$criteria->compare('mLang',Yii::app()->user->account_lang);
$SysMsgs=SystemMessages::model()->findAll($criteria);
if (count($SysMsgs)>0){
$errorMsg='"'.$this->problemDefinition->group_display_val.'"'.$SysMsgs[0]->mDesc.' Code['.$SysMsgs[0]->mId.']';
}
else{
$errorMsg=$this->problemDefinition->group_display_val.' already recorded.';
}
throw new Exception($errorMsg);
$retval=false;
}
}
else{
$this->setAttribute('update_date',date("Y-m-d H:i:s"));
$this->setAttribute('update_user_id',Yii::app()->user->id);
$this->setAttribute('update_acc_id',Yii::app()->user->assigner_account_id);
$this->setAttribute('update_acc_assign_id',Yii::app()->user->acc_assign_id);
$retval=true;
}
return $retval;
}
public function getProb_def_id(){
return $this->problem_definition_id;
}
public function setProb_def_id($val){
$this->problem_definition_id=$val;
}
public function getProblemFlaged(){
return $this->alert_on_dashboard=='1' ? CHtml::image(Yii::app()->baseUrl .'/images/Flagredicon.png') : '';
}
public function getProblemFlagSrc(){
return $this->alert_on_dashboard=='1' ? Yii::app()->baseUrl .'/images/Flagredicon.png' :'';
}
public function getProblemChronic(){
return $this->chronic=='1' ? CHtml::image(Yii::app()->baseUrl .'/images/tickedS.jpg') : '';
}
public function getProblemDel(){
return ' <a class="delete" title="Delete" onclick="DeletePatProblem('.$this->problem_id.'); return false; " href="#"><img src="/webapp/assets/50005a14/gridview/delete.png" alt="Delete" /></a> <a class="delete" title="Update" onclick="UpdatePatProblem(this,'.$this->problem_id.','.$this->problem_definition_id.','.$this->curr_or_history.',\''.$this->problem_notes.'\','.$this->problem_duration_id.','.$this->chronic.','.$this->alert_on_dashboard.'); return false; " href="#"><img src="/webapp/assets/50005a14/gridview/update.png" alt="Update" /></a>';
}
}
Following is the code of EJuiComboBox.php
<?php
/**
* jQuery combobox Yii extension
*
* Allows selecting a value from a dropdown list or entering in text.
* Also works as an autocomplete for items in the select.
*
* #copyright © Digitick <www.digitick.net> 2011
* #license GNU Lesser General Public License v3.0
* #author Ianaré Sévi
* #author Jacques Basseck
*
*/
Yii::import('zii.widgets.jui.CJuiInputWidget');
/**
* Base class.
*/
class EJuiComboBox extends CJuiInputWidget
{
/**
* #var array the entries that the autocomplete should choose from.
*/
public $data = array();
public $assoc;
/**
* #var string A jQuery selector used to apply the widget to the element(s).
* Use this to have the elements keep their binding when the DOM is manipulated
* by Javascript, ie ajax calls or cloning.
* Can also be useful when there are several elements that share the same settings,
* to cut down on the amount of JS injected into the HTML.
*/
public $scriptSelector;
public $defaultOptions = array('allowText' => true);
protected function setSelector($id, $script, $event=null)
{
if ($this->scriptSelector) {
if (!$event)
$event = 'focusin';
$js = "jQuery('body').delegate('{$this->scriptSelector}','{$event}',function(e){\$(this).{$script}});";
$id = $this->scriptSelector;
}
else
$js = "jQuery('#{$id}').{$script}";
return array($id, $js);
}
public function init()
{
$cs = Yii::app()->getClientScript();
$assets = Yii::app()->getAssetManager()->publish(dirname(__FILE__) . '/assets');
$cs->registerScriptFile($assets . '/jquery.ui.widget.min.js');
$cs->registerScriptFile($assets . '/jquery.ui.combobox.js');
parent::init();
}
/**
* Run this widget.
* This method registers necessary javascript and renders the needed HTML code.
*/
/*
public function run()
{
list($name, $id) = $this->resolveNameID();
if (is_array($this->data) && !empty($this->data)){
$data = array_combine($this->data, $this->data);
array_unshift($data, null);
}
else
$data = array();
echo CHtml::dropDownList(null, null, $data, array('id' => $id . '_select'));
if ($this->hasModel())
echo CHtml::activeTextField($this->model, $this->attribute, $this->htmlOptions);
else
echo CHtml::textField($name, $this->value, $this->htmlOptions);
$this->options = array_merge($this->defaultOptions, $this->options);
$options = CJavaScript::encode($this->options);
$cs = Yii::app()->getClientScript();
$js = "combobox({$options});";
list($id, $js) = $this->setSelector($id, $js);
$cs->registerScript(__CLASS__ . '#' . $id, $js);
}
*/
public function run()
{
list($name, $id) = $this->resolveNameID();
if (is_array($this->data) && !empty($this->data)){
//if $data is not an assoc array make each value its key
if($this->assoc){
$data=$this->data;
}
else{
$data=array_combine($this->data, $this->data);
}
//does the same as array_unshift($data,null) but does not break assoc arrays
$data=array(""=>"")+$data;
}
else
$data = array();
if ($this->hasModel())
echo CHtml::activeDropDownList($this->model,$this->attribute,$data);
else
echo CHtml::dropDownList($name, $this->value, $data);
echo CHtml::textField(null,($this->hasModel()?($data[$this->model->{$this->attribute}]):$data[$this->value]),array('id'=>$id.'_combobox'));
$this->options = array_merge($this->defaultOptions, $this->options);
$options = CJavaScript::encode($this->options);
$cs = Yii::app()->getClientScript();
$js = "combobox({$options});";
list($id, $js) = $this->setSelector($id.'_combobox', $js);
$cs->registerScript(__CLASS__ . '#' . $id, $js);
}
}
Any help would greatly appreciated.
I used to have the same error for EJuiComboBox, too. It happens whenever NO DATA is found to feed the Textfield in the combobox, it is a PHP Error.. I made the following change to the run method of EJuiComboBox to stop it from throwing this PHP error when no data is found
public function run()
{
list($name, $id) = $this->resolveNameID();
if (is_array($this->data) && !empty($this->data)){
//if $data is not an assoc array make each value its key
$data=($this->assoc)?$this->data:array_combine($this->data, $this->data);
//does the same as array_unshift($data,null) but does not break assoc arrays
$data=array(""=>"")+$data;
}
else
$data = array();
if ($data == array()) {
echo "No hay registros";
return;
}
if ($this->hasModel())
echo CHtml::activeDropDownList($this->model,$this->attribute,$data,$this->selectHtmlOptions);
else
echo CHtml::dropDownList($name, $this->value, $data,$this->selectHtmlOptions);
echo CHtml::textField(null,($this->hasModel()?($data[$this->model->{$this->attribute}]):$data[$this->value]),array('id'=>$id.'_combobox'));
$this->options = array_merge($this->defaultOptions, $this->options);
$options = CJavaScript::encode($this->options);
$cs = Yii::app()->getClientScript();
$js = "combobox({$options});";
list($id, $js) = $this->setSelector($id.'_combobox', $js);
$cs->registerScript(__CLASS__ . '#' . $id, $js);
}
Using this method will result in a simple rendering of "No data found!" whenever there are No members in the data for the ComboBox.
I solved the problem. By default, Yii gets the Not Null attribute of a column during runtime from the database, so if a column is marked as Not Null in database, it applies zero (0) as its default value. When "$this->model->{$this->attribute}" was getting executed, it was putting "0" instead of "problem_definition_id" which was throwing error. After making the column to Nullable in database, the error vanished. But since this does not seem a good solution. So after I created the $PatientProblem object, I explicitly set the problem_definition_id to null and it resolved the error.
Related
Symfony ValidatorComponent > AnnotationMapping in FormComponent
Im working on a project where I'm using some Symfony Components. My problem is how to make the Form Component's validation of Forms use AnnotationMapping to find the constraints. SetUp: global $loader; //composer - autoload AnnotationRegistry::registerLoader([$loader, 'loadClass']); $validator = Validation::createValidatorBuilder() ->enableAnnotationMapping() ->getValidator(); $formFactory = Forms::createFormFactoryBuilder() [...] ->addExtension(new ValidatorExtension($validator)) ->getFormFactory(); Entity /** * #ORM\Entity * #ORM\Table(name="..") */ class Conductor extends AbstractEntity { /** * #ORM\Id * #ORM\Column(type="integer") * #ORM\GeneratedValue */ protected $id; /** * #Assert\NotBlank() * #ORM\Column(type="string") */ protected $pattern; [...] } Building the Form $builder = $App->getFormFactory()->createBuilder(FormType::class, $entity_data); foreach ($fields as $field) { $builder->add( $field, null, [ "attr" => array("class" => "..."), ] ); } $builder->getForm(); FormSubmit / Validation if($request->isMethod('POST')) { $formTable = $this->createFormTable( array() ); $form = $formTable->buildForm($entity); $form->submit($this->dataMapper->formDataFromPost()); /* $entity = $this->dataMapper->mapFromPost(); $validator = Validation::createValidatorBuilder() ->enableAnnotationMapping() ->getValidator(); */ if($form->isValid()) { [...] } else { [...] } } Im trying to make the NotBlank() Constraints work. But my form passes the validation in any case. If I use a new validator and validate with it, it will show me the correct Errors. But the Form->isValid() function does not. Maybe it is not configured correctly to use AnnotationMapping? Thank you very much in advance for tipps or solutions! Problem localization The form handleRequest / submit and validation are working as expected! The form does not have any constraints!! -> Mapping the Constraints from Annotation is not happening / working. I did find a similar question: Why does Symfony form not validate my DTO with constraint annotations?
I wasn't able to find a solution to enable the mapping that should happen inside the FormComponent with the ValidatorExtension. But I did find a functional workaround. My approach is to get the Constraints from the readPropertyMetadata function of the validator: use Symfony\Component\Validator\Validation; public function buildForm(AbstractEntity $entity) { $validator = Validation::createValidatorBuilder() ->enableAnnotationMapping() ->getValidator(); $fields = [*ENTITY PRPERTIES*]; $classMeta = $validator->getMetadataFor($entity); foreach ($fields as $field) { $metadata = $classMeta->getPropertyMetadata($field); if(is_array($metadata) && count($metadata) > 0) { $constraints = $classMeta->getPropertyMetadata($field)[0]->constraints; } else { $constraints = []; } $builder->add( $field, null, [ "attr" => array("class" => "..."), "constraints" => $constraints ] ); } } As now the constraints are added to the form the validation finally works as expected.
how to add "target lists" to my custom module
i have create a module and named: Custom_module by Developer Tools --> Module Builder I trired to add "target lists" to Custom_module like module Campaign, but i can not find the way the do that everyone can help you to find the best way to add "target lists" to my module. thanks
You Just need to create a custom sub panel in your custom module. target list is ProspectLists module. Follow this link to create custom module. http://shanedowling.com/sugarcrm-7-custom-subpanels https://developer.sugarcrm.com/2015/05/18/creating-subpanels-with-custom-results-in-sugar-7-5/ 1. Create a new link class This should go into custom/modules//YourNewLink.php and this class will act as the custom functionality that will build your link between the two records. <?php /** * Custom filtered link */ class YourNewLink extends Link2 { /** * DB * * #var DBManager */ protected $db; public function __construct($linkName, $bean, $linkDef = false) { $this->focus = $bean; $this->name = $linkName; $this->db = DBManagerFactory::getInstance(); if (empty($linkDef)) { $this->def = $bean->field_defs[$linkName]; } else { $this->def = $linkDef; } } /** * Returns false if no relationship was found for this link * * #return bool */ public function loadedSuccesfully() { // this link always loads successfully return true; } /** * #see Link2::getRelatedModuleName() */ public function getRelatedModuleName() { return '<Your_Module>'; } /** * * #see Link2::buildJoinSugarQuery() */ public function buildJoinSugarQuery($sugar_query, $options = array()) { $joinParams = array('joinType' => isset($options['joinType']) ? $options['joinType'] : 'INNER'); $jta = 'active_other_invites'; if (!empty($options['joinTableAlias'])) { $jta = $joinParams['alias'] = $options['joinTableAlias']; } $sugar_query->joinRaw($this->getCustomJoin($options), $joinParams); return $sugar_query->join[$jta]; } /** * Builds main join subpanel * #param string $params * #return string JOIN clause */ protected function getCustomJoin($params = array()) { $bean_id = $this->db->quoted($this->focus->id); $sql = " INNER JOIN("; $sql .= "SELECT id FROM accounts WHERE id={$bean_id}"; // This is essentially a select statement that will return a set of ids that you can match with the existing sugar_query $sql .= ") accounts_result ON accounts_result.id = sugar_query_table.id"; return $sql; } 2. Add a new vardef entry for the link field. For this example, I'm going to create the custom link on the contacts module. So this code goes in custom/Extension/modules/Contacts/Ext/Vardefs/your_field_name.php <?php $dictionary["Contact"]["fields"]["your_field_name"] = array( 'name' => 'active_other_invites', 'type' => 'link', 'link_file' => 'custom/modules/<YourModule>/YourNewLink.php', 'link_class' => 'YourNewLink', 'source' => 'non-db', 'vname' => 'LBL_NEW_LINK', 'module' => '<YourModule>', 'link_type' => 'many', 'relationship' => '', ); 3. Add the new link as a subpanel This goes under custom/Extension/modules/Contacts/Ext/clients/base/layouts/subpanels/your_subpanel_name.php <?php $viewdefs['Contacts']['base']['layout']['subpanels']['components'][] = array ( 'layout' => 'subpanel', 'label' => 'LBL_NEW_LINK', 'context' => array ( 'link' => 'your_field_name', ), ); 4. Add the label Under custom/Extension/modules/Contacts/Ext/Language/en_us.new_link.php <?php $mod_strings['LBL_ACTIVE_OTHER_INVITES'] = 'Your New Link'; 5. Quick Repair and Rebuild
Can i get username in a table having no relationship with user table?
I am trying to get the username in business table view which is userbusiness.php. Business table has no relationship with user table, but it has one to many relationship with reviewbusiness table. Furthermore, Reviewbusiness has one to many relationship with user table. Review business has following attributes, user_id,business_id,rating,review. My question is how can i get the username in business view (userbusiness.php) which has no relationship with user table? Here is my business model <?php /** * This is the model class for table "business". * * The followings are the available columns in table 'business': * #property integer $id * #property string $business_name * #property string $image * #property string $business_description * #property string $opening_hours * #property string $closing_hours * #property string $days * #property string $Holiday * * The followings are the available model relations: * #property Address[] $addresses * #property BusinessItems[] $businessItems * #property BusinessPackage[] $businessPackages * #property Facilities[] $facilities * #property ReviewBusiness[] $reviewBusinesses * #property SubCategoryBusiness[] $subCategoryBusinesses */ class Business extends CActiveRecord { /** * #return string the associated database table name */ public function tableName() { return 'business'; } /** * #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('business_name, business_description, opening_hours, closing_hours, days', 'required'), array('business_name', 'length', 'max'=>60), array('image, opening_hours, closing_hours, days, Holiday', 'length', 'max'=>45), array('business_description', 'length', 'max'=>500), // The following rule is used by search(). // #todo Please remove those attributes that should not be searched. array('id, business_name, image, business_description, opening_hours, closing_hours, days, Holiday', 'safe', 'on'=>'search'), array('image', 'file','types'=>'jpg, gif, png', 'allowEmpty'=>true, 'safe' => false,'on'=>'insert,update'), ); } /** * #return array relational rules. */ public function relations() { // NOTE: you may need to adjust the relation name and the related // class name for the relations automatically generated below. return array( 'addresses' => array(self::HAS_MANY, 'Address', 'business_id'), 'businessItems' => array(self::HAS_MANY, 'BusinessItems', 'business_id'), 'businessPackages' => array(self::HAS_MANY, 'BusinessPackage', 'business_id'), 'facilities' => array(self::HAS_MANY, 'Facilities', 'business_id'), 'reviewBusinesses' => array(self::HAS_MANY, 'ReviewBusiness', 'business_id'), 'subCategoryBusinesses' => array(self::HAS_MANY, 'SubCategoryBusiness', 'business_id'), ); } /** * #return array customized attribute labels (name=>label) */ public function attributeLabels() { return array( 'id' => 'ID', 'business_name' => 'Business Name', 'image' => 'Image', 'business_description' => 'Business Description', 'opening_hours' => 'Opening Hours', 'closing_hours' => 'Closing Hours', 'days' => 'Days', 'Holiday' => 'Holiday', ); } /** * Retrieves a list of models based on the current search/filter conditions. * * Typical usecase: * - Initialize the model fields with values from filter form. * - Execute this method to get CActiveDataProvider instance which will filter * models according to data in model fields. * - Pass data provider to CGridView, CListView or any similar widget. * * #return CActiveDataProvider the data provider that can return the models * based on the search/filter conditions. */ public function search() { // #todo Please modify the following code to remove attributes that should not be searched. $criteria=new CDbCriteria; $criteria->compare('id',$this->id); $criteria->compare('business_name',$this->business_name,true); $criteria->compare('image',$this->image,true); $criteria->compare('business_description',$this->business_description,true); $criteria->compare('opening_hours',$this->opening_hours,true); $criteria->compare('closing_hours',$this->closing_hours,true); $criteria->compare('days',$this->days,true); $criteria->compare('Holiday',$this->Holiday,true); return new CActiveDataProvider($this, array( 'criteria'=>$criteria, )); } /** * Returns the static model of the specified AR class. * Please note that you should have this exact method in all your CActiveRecord descendants! * #param string $className active record class name. * #return Business the static model class */ public static function model($className=__CLASS__) { return parent::model($className); } } here is my review business model class ReviewBusiness extends CActiveRecord { /** * #return string the associated database table name */ public function tableName() { return 'review_business'; } /** * #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('user_id, business_id, review, rating', 'required'), array('user_id, business_id, rating', 'numerical', 'integerOnly'=>true), array('review', 'length', 'max'=>500), // The following rule is used by search(). // #todo Please remove those attributes that should not be searched. array('id, user_id, business_id, review, rating', 'safe', 'on'=>'search'), ); } /** * #return array relational rules. */ public function relations() { // NOTE: you may need to adjust the relation name and the related // class name for the relations automatically generated below. return array( 'business' => array(self::BELONGS_TO, 'Business', 'business_id'), 'user' => array(self::BELONGS_TO, 'User', 'user_id'), ); } /** * #return array customized attribute labels (name=>label) */ public function attributeLabels() { return array( 'id' => 'ID', 'user_id' => 'User', 'business_id' => 'Business', 'review' => 'Review', 'rating' => 'Rating', ); } /** * Retrieves a list of models based on the current search/filter conditions. * * Typical usecase: * - Initialize the model fields with values from filter form. * - Execute this method to get CActiveDataProvider instance which will filter * models according to data in model fields. * - Pass data provider to CGridView, CListView or any similar widget. * * #return CActiveDataProvider the data provider that can return the models * based on the search/filter conditions. */ public function search() { // #todo Please modify the following code to remove attributes that should not be searched. $criteria=new CDbCriteria; $criteria->compare('id',$this->id); $criteria->compare('user_id',$this->user_id); $criteria->compare('business_id',$this->business_id); $criteria->compare('review',$this->review,true); $criteria->compare('rating',$this->rating); return new CActiveDataProvider($this, array( 'criteria'=>$criteria, )); } /** * Returns the static model of the specified AR class. * Please note that you should have this exact method in all your CActiveRecord descendants! * #param string $className active record class name. * #return ReviewBusiness the static model class */ public static function model($className=__CLASS__) { return parent::model($className); } } and here in the end is my user model class User extends CActiveRecord { /** * #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('superuser, status, requires_new_password, login_attempts, login_time', 'numerical', 'integerOnly'=>true), array('username, login_ip', 'length', 'max'=>45), array('password, email, activkey', 'length', 'max'=>120), array('salt, validation_key', 'length', 'max'=>255), array('activation_key', 'length', 'max'=>128), array('reset_token', 'length', 'max'=>250), array('profilepic', 'length', 'max'=>450), array('create_at, lastvisit_at, create_time, update_time', 'safe'), // The following rule is used by search(). // #todo Please remove those attributes that should not be searched. array('id, username, password, email, activkey, create_at, lastvisit_at, superuser, status, salt, requires_new_password, login_attempts, login_time, login_ip, activation_key, validation_key, create_time, update_time, reset_token, profilepic', 'safe', 'on'=>'search'), ); } /** * #return array relational rules. */ public function relations() { // NOTE: you may need to adjust the relation name and the related // class name for the relations automatically generated below. return array( 'itemReviews' => array(self::HAS_MANY, 'ItemReview', 'user_id'), 'profiles' => array(self::HAS_ONE, 'Profiles', 'user_id'), 'reviewBusinesses' => array(self::HAS_MANY, 'ReviewBusiness', 'user_id'), ); } /** * #return array customized attribute labels (name=>label) */ public function attributeLabels() { return array( 'id' => 'ID', 'username' => 'Username', 'password' => 'Password', 'email' => 'Email', 'activkey' => 'Activkey', 'create_at' => 'Create At', 'lastvisit_at' => 'Lastvisit At', 'superuser' => 'Superuser', 'status' => 'Status', 'salt' => 'Salt', 'requires_new_password' => 'Requires New Password', 'login_attempts' => 'Login Attempts', 'login_time' => 'Login Time', 'login_ip' => 'Login Ip', 'activation_key' => 'Activation Key', 'validation_key' => 'Validation Key', 'create_time' => 'Create Time', 'update_time' => 'Update Time', 'reset_token' => 'Reset Token', 'profilepic' => 'Profilepic', ); } /** * Retrieves a list of models based on the current search/filter conditions. * * Typical usecase: * - Initialize the model fields with values from filter form. * - Execute this method to get CActiveDataProvider instance which will filter * models according to data in model fields. * - Pass data provider to CGridView, CListView or any similar widget. * * #return CActiveDataProvider the data provider that can return the models * based on the search/filter conditions. */ public function search() { // #todo Please modify the following code to remove attributes that should not be searched. $criteria=new CDbCriteria; $criteria->compare('id',$this->id); $criteria->compare('username',$this->username,true); $criteria->compare('password',$this->password,true); $criteria->compare('email',$this->email,true); $criteria->compare('activkey',$this->activkey,true); $criteria->compare('create_at',$this->create_at,true); $criteria->compare('lastvisit_at',$this->lastvisit_at,true); $criteria->compare('superuser',$this->superuser); $criteria->compare('status',$this->status); $criteria->compare('salt',$this->salt,true); $criteria->compare('requires_new_password',$this->requires_new_password); $criteria->compare('login_attempts',$this->login_attempts); $criteria->compare('login_time',$this->login_time); $criteria->compare('login_ip',$this->login_ip,true); $criteria->compare('activation_key',$this->activation_key,true); $criteria->compare('validation_key',$this->validation_key,true); $criteria->compare('create_time',$this->create_time,true); $criteria->compare('update_time',$this->update_time,true); $criteria->compare('reset_token',$this->reset_token,true); $criteria->compare('profilepic',$this->profilepic,true); return new CActiveDataProvider($this, array( 'criteria'=>$criteria, )); } /** * Returns the static model of the specified AR class. * Please note that you should have this exact method in all your CActiveRecord descendants! * #param string $className active record class name. * #return User the static model class */ public static function model($className=__CLASS__) { return parent::model($className); } }
I think you can get the username simply in this way Yii::app()->user->name; You can also get the user id in this way Yii::app()->user->getId(); see this doc form more info http://www.yiiframework.com/doc/api/1.1/CWebUser/ And for retrive the username for a given userId you can do this way $theUsername = User::model()->find('id=:id',array(':id'=>$yourid))->username;
how to concat rules for the same AR model in Yii
I use Yii MVC. I have to add new columns in a data table very often. I want to use Gii and regenerate the model and keep the chnages that i made; changes like constants, variables, rules, relations, etc ... So, let's take for example the url class model: <?php /** * This is the model class for table "url". * * The followings are the` available columns in table 'url': * #property string $id * #property integer $instance_id * #property integer $website_id * #property string $link * #property string $title * #property integer $created * #property integer $updated * #property integer $status */ class Url extends CActiveRecord { const ACTIVE = 1; /** * Returns the static model of the specified AR class. * #param string $className active record class name. * #return Url the static model class */ public static function model($className = __CLASS__) { return parent::model($className); } /** * #return string the associated database table name */ public function tableName() { return 'url'; } /** * #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('instance_id, website_id, link, title, created, updated, status', 'required'), array('instance_id, website_id, created, updated, status', 'numerical', 'integerOnly' => true), array('link, title', 'length', 'max' => 255), array('link', 'unique'), // The following rule is used by search(). // Please remove those attributes that should not be searched. array('id, instance_id, website_id, link, title, created, updated, status', 'safe', 'on' => 'search'), ); } /** * #return array relational rules. */ public function relations() { // NOTE: you may need to adjust the relation name and the related // class name for the relations automatically generated below. return array( ); } /** * #return array customized attribute labels (name=>label) */ public function attributeLabels() { return array( 'id' => 'ID', 'instance_id' => 'Instance', 'website_id' => 'Website', 'link' => 'Link', 'title' => 'Title', 'created' => 'Created', 'updated' => 'Updated', 'status' => 'Status', ); } /** * Retrieves a list of models based on the current search/filter conditions. * #return CActiveDataProvider the data provider that can return the models based on the search/filter conditions. */ public function search() { // Warning: Please modify the following code to remove attributes that // should not be searched. $criteria = new CDbCriteria; $criteria->compare('id', $this->id, true); $criteria->compare('instance_id', $this->instance_id); $criteria->compare('website_id', $this->website_id); $criteria->compare('link', $this->link, true); $criteria->compare('title', $this->title, true); $criteria->compare('created', $this->created); $criteria->compare('updated', $this->updated); $criteria->compare('status', $this->status); return new CActiveDataProvider($this, array( 'criteria' => $criteria, )); } } when I will regenerate the model, the const and the rule with unique will be lost so, I created a new model class, UrlM, that extends the url model class, and this class keps all my enhancements: <?php class UrlM extends Url { const ACTIVE = 1; public function rules() { return array( array('link', 'unique'), ); } public function relations() { return array( ); } } how do i concat the rules from the url model class with the rules from the urlm model class? the same answer should aply for future enhancements, like relations
Each function of the parent class - like rules(), relations() etc., returns array. So you may use call to the parent::rules() and then just join "array". public function rules() { $myParentRules=parent::rules(); $myConcatRules=$myParentRules + array( array('link', 'unique'), ); return $myConcatRules; }
array_merge will help you. public function rules() { $myRules = array( array('id', 'numerical', 'integerOnly'=>true), ); return array_merge(parent::rules(),$myRules); }
Testing symfony 2 forms
I develop new type, but I don't know how I can test it. Assert annotation is not load and validations is not called. Could any one please help me? class BarcodeType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder-> add('price'); } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Bundles\MyBundle\Form\Model\Barcode', 'intention' => 'enable_barcode', )); } public function getName() { return 'enable_barcode'; } } A have following model for storing form data. namepspace Bundles\MyBundle\Form\Model; class Barcode { /** * #Assert\Range( * min = "100", * max = "100000", * minMessage = "...", * maxMessage = "..." * ) */ public $price; } I develop some test like this, the form didn't get valid data but it is valid! (Because annotation is not applied) I try adding ValidatorExtension but I dont know how can I set constructor paramaters function test...() { $field = $this->factory->createNamed('name', 'barcode'); $field->bind( array( 'price' => 'hello', )); $data = $field->getData(); $this->assertTrue($field->isValid()); // Must not be valid }
Not sure why you need to unit-test the form. Cant You unit test validation of Your entity and cover controller with your expected output? While testing validation of entity You could use something like this: public function testIncorrectValuesOfUsernameWhileCallingValidation() { $v = \Symfony\Component\Validator\ValidatorFactory::buildDefault(); $validator = $v->getValidator(); $not_valid = array( 'as', '1234567890_234567890_234567890_234567890_dadadwadwad231', "tab\t", "newline\n", "Iñtërnâtiônàlizætiøn hasn't happened to ", 'trśżź', 'semicolon;', 'quote"', 'tick\'', 'backtick`', 'percent%', 'plus+', 'space ', 'mich #l' ); foreach ($not_valid as $key) { $violations = $validator->validatePropertyValue("\Brillante\SampleBundle\Entity\User", "username", $key); $this->assertGreaterThan(0, count($violations) ,"dissalow username to be ($key)"); } }
Functional test. Given that you generate a CRUD with app/console doctrine:generate:crud with routing=/ss/barcode, and given that maxMessage="Too high" you can: class BarcodeControllerTest extends WebTestCase { public function testValidator() { $client = static::createClient(); $crawler = $client->request('GET', '/ss/barcode/new'); $this->assertTrue(200 === $client->getResponse()->getStatusCode()); // Fill in the form and submit it $form = $crawler->selectButton('Create')->form(array( 'ss_bundle_eavbundle_barcodetype[price]' => '12', )); $client->submit($form); $crawler = $client->followRedirect(); // Check data in the show view $this->assertTrue($crawler->filter('td:contains("12")')->count() > 0); // Edit the entity $crawler = $client->click($crawler->selectLink('Edit')->link()); /* force validator response: */ $form = $crawler->selectButton('Edit')->form(array( 'ss_bundle_eavbundle_barcodetype[price]' => '1002', )); $crawler = $client->submit($form); // Check the element contains the maxMessage: $this->assertTrue($crawler->filter('ul li:contains("Too high")')->count() > 0); } }
Include this line must be in Model and try it after include look like your model. /* Include the required validators */ use Symfony\Component\Validator\Constraints as Assert; namespace Bundles\MyBundle\Form\Model; class Barcode { /** * #Assert\Range( * min = "100", * max = "100000", * minMessage = "min message here", * maxMessage = "max message here" * ) */ public $price; }