I have such projects table structure
CREATE TABLE IF NOT EXISTS `projects` (
`project_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`description` text NOT NULL,
`url` varchar(255) NOT NULL,
`create_time` datetime DEFAULT NULL,
`create_user_id` int(11) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`update_user_id` int(11) DEFAULT NULL,
PRIMARY KEY (`project_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
when I try to create new record with next form
Rules in model:
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('title, description, url', 'required'),
array('create_user_id, update_user_id', 'numerical', 'integerOnly'=>true),
array('title, url', 'length', 'max'=>255),
array('create_time, update_time', 'safe'),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('project_id, title, description, url, create_time, create_user_id, update_time, update_user_id', 'safe', 'on'=>'search'),
);
}
I have received error
CDbCommand failed to execute the SQL statement: SQLSTATE[22007]:
Invalid datetime format: 1292 Incorrect datetime value: '' for column
'create_time' at row 1. The SQL statement executed was: INSERT INTO
projects (title, description, url, create_time,
create_user_id, update_time, update_user_id) VALUES (:yp0, :yp1,
:yp2, :yp3, :yp4, :yp5, :yp6)
Why? How can I tell Yii that datetime fields are not required and can contain default value if not entered.
Try this, and as this is self contained behavior inside Yii itself, it should work :
In the Rules model add this :
public function behaviors(){
return array('CTimestampBehavior'=>array(
'class' => 'zii.behaviors.CTimestampBehavior',
'createAttribute' => 'create_time',
'updateAttribute' => 'update_time',
'setUpdateOnCreate' => true,
));
}
U may try something like this after u click on the button Create it gets to some action
Take it for example actionCreate()
In actionCreate u do like as shown
public function actionCreate()
{
$model=new Project;
if(isset($_POST['Project']))
{
$model->attributes=$_POST['Project'];
$model->create_time=new CDbExpression('NOW()');
$model->save(false);
$this->redirect(array('view','id'=>$model->id));
}
$this->render('create',array(
'model'=>$model,
));
}
doesn't this work?
public function beforeSave()
{
if($this->isNewRecord)
{
$this->create_time=null;
$this->update_time=null;
}
return parent::beforeSave();
}
Related
I have a roles table. Looks like this:
CREATE TABLE `roles` (
`role` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`permissions` longtext COLLATE utf8_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `roles`
ADD PRIMARY KEY (`role`),
ADD UNIQUE KEY `role` (`role`);
Now cake is not recognizing it as a "normal" field, so it doesn't give out any input field.
I fixed my view with this:
// src/Template/Admin/Roles/add.ctp
echo $this->Form->control('name', ['class' => 'form-control']);
And now the workaround in my controller:
// src/Controller/Admin/RolesController.ctp
$roleData = $this->request->getData();
$roleData['role'] = strtolower($roleData['name']);
unset($roleData['name']);
$role = $this->Roles->patchEntity($role, $roleData);
if ($this->Roles->save($role)) {
$this->Flash->success(__('The role has been saved.'));
}
It saves the entry, but doesn't fill up anything in the database row role. Am I missing something?
If you are using patchEntity then you cannot assign non assignable fields and your primary key is more than likely not an assignable key by default. You can change it in the entity which should allow the form to show it will allow patch entity to work correctly.
namespace App\Model\Entity;
use Cake\ORM\Entity;
class Role extends Entity
{
protected $_accessible = [
'role' => true,
'permissions' => true,
'*' => false,
];
}
https://book.cakephp.org/3.0/en/orm/saving-data.html#changing-accessible-fields
https://book.cakephp.org/3.0/en/orm/entities.html#mass-assignment
In RolesTable.php there should be something like this:
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('roles');
$this->setPrimaryKey('role');
}
so CakePHP would use 'role' as PrimaryKey.
I am trying to save multiple translations for column name in a single form submit but it always result in an exception 'name' doesn't have a default value. Below given is my implementation according to cakephp's latest documentation.
Table Structure for words
CREATE TABLE `words` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`slug` varchar(255) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `slug` (`slug`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Table word_i18n structure that hold all the translations for table words
CREATE TABLE `word_i18n` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`locale` varchar(6) NOT NULL,
`model` varchar(255) NOT NULL,
`foreign_key` int(10) NOT NULL,
`field` varchar(255) NOT NULL,
`content` mediumtext,
PRIMARY KEY (`id`),
KEY `locale` (`locale`),
KEY `model` (`model`),
KEY `row_id` (`foreign_key`),
KEY `field` (`field`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Added the translation behavior to the WordsTable
public function initialize(array $config)
{
parent::initialize($config);
$this->table('words');
$this->displayField('name');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->addBehavior('Translate', [
'fields' => ['name'],
'translationTable' => 'word_i18n',
]);
}
/**
* Validation Rules
*/
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmpty('id', 'create');
$validator
->requirePresence('name', 'create')
->notEmpty('name');
$validator
->notEmpty('slug')
->add('slug', 'unique', ['rule' => 'validateUnique', 'provider'=> 'table']);
return $validator;
}
Word Entity with Translation Trait
class Word extends Entity
{
use TranslateTrait;
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* #var array
*/
protected $_accessible = [
'*' => true,
'id' => false
];
}
Controller Method to render and handle the submission
public function add()
{
I18n::locale("en"); // Sets the default locale
$word = $this->Words->newEntity();
if ($this->request->is('post')) {
$word = $this->Words->patchEntity($word, $this->request->data, ['translations' => true]);
//debug($word);die;
if ($this->Words->save($word)) {
$this->Flash->success(__('The word has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The word could not be saved. Please, try again.'));
}
}
$this->set(compact('word'));
$this->set('_serialize', ['word']);
}
And at last the form to submit data
<?= $this->Form->create($word); ?>
<fieldset>
<legend><?= __('Add Word') ?></legend>
<?php
echo $this->Form->input('_translations.en.name',['class'=>"form-control ui-flat", "label" => __("Name [{0}]", ["English"])]);
echo $this->Form->input('_translations.ja.name',['class'=>"form-control ui-flat", "label" => __("Name [{0}]", ["Japanese"]) ]);
echo $this->Form->input('_translations.ko.name',['class'=>"form-control ui-flat", "label" => __("Name [{0}]", ["Korean"])]);
echo $this->Form->input('_translations.zh.name',['class'=>"form-control ui-flat", "label" => __("Name [{0}]", ["Chinese"])]);
echo $this->Form->button(__('Submit'),array('class'=>"btn btn-success ui-flat pull-right"));
?>
</fieldset>
<?= $this->Form->end() ?>
Everything is implement to the cakephp's documentation but always got an validation error for fields name is _required This field is required
And if remove the _translations.en from the name first form field and submits it passes the validation but leads to an sql error Field 'name' doesn't have a default value.
You’ll need to remember to add _translations into the $_accessible fields of your entity as well.
https://book.cakephp.org/3.0/en/orm/behaviors/translate.html
To save the multiple translations at same time just make sure translated columns does not exists in the table.
Here we have to remove the name from the table words.
And also remove the validation rule requirePresense for the translated column.
I am having some trouble trying to fetch associated models when selecting fields. My version of CakePHP is 3.0beta2.
Three MYSQL tables that are relevant to this question:
users:
`id` int(11) NOT NULL,
`username` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`role` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
... (more information)
-
presets:
`id` int(11) NOT NULL,
`name` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`user_id` int(11) NOT NULL,
... (more information)
-
favorites:
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`preset_id` int(11) NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
My associations are defined as shown below:
// From FavoritesTable.php
public function initialize(array $config) {
$this->belongsTo('Users');
$this->belongsTo('Presets');
}
// From PresetsTable.php
public function initialize(array $config) {
$this->belongsTo('Users');
$this->hasMany('Favorites');
}
// From UsersTable.php
public function initialize(array $config) {
$this->hasMany('Presets');
$this->hasMany('Favorites');
}
What I'm trying to achieve is:
Load all the user information for the currently logged in user
Load all the favorites that this user has
Create a new field that transforms the created field (a timestamp) into a date
For each favorite, load the associated preset data
This is the code that I use to do that:
// From UsersController.php
public function favorites() {
$userId = $this->Auth->user('id');
$user = $this->Users->find('all')
->where(['id' => $userId])
->contain([
'Favorites' => function($q) {
return $q
->select(['id', 'preset_id', 'user_id', 'created', 'date' => 'DATE(created)'])
->order(['Favorites.created' => 'DESC']);
},
'Favorites.Presets',
])
->first();
$this->set('user', $user);
}
The problem is: when I use the select method as in the code above, the Favorites.Presets association is not loaded, so $user['favorites'][0]['preset'] is always null.
But if I comment out the select method (thus selecting all fields and not retrieving DATE(created), the association is loaded and I can access the information from the presets table.
Could this be a bug or am I doing something wrong?
Thanks for the help!
I think you need to call ->autoFields(true) after select(). This is required if you expect all other fields to be selected. This could probably be seen as a bug, try opening a ticket in github.
I've been trying to make an insert into the database whenever a user register, but I always got an SQL[23000] error and I realized that inside my database, there was a relationship to a different table and that is why I was getting an error. I'm used to creating a model and crud through Gii but this is the first time where I encountered an error because of relationships between tables. I think the problem is that I need to be able to insert into two models and I'm not completely sure how I should do that.
First things first, I'll show my schema:
CREATE TABLE IF NOT EXISTS `system_users` (
`party_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(200) NOT NULL,
`password` varchar(255) NOT NULL,
`date_last_login` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`status` varchar(50) NOT NULL DEFAULT 'Pending for Approval',
`date_created` datetime NOT NULL,
`date_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`user_role` varchar(255) NOT NULL,
`isLogin` int(1) NOT NULL,
PRIMARY KEY (`party_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=219 ;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `system_users`
--
ALTER TABLE `system_users`
ADD CONSTRAINT `system_users_ibfk_1` FOREIGN KEY (`party_id`) REFERENCES `parties` (`id`);
---------------------------------------
CREATE TABLE IF NOT EXISTS `parties` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`party_type_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `party_type_id` (`party_type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=200 ;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `parties`
--
ALTER TABLE `parties`
ADD CONSTRAINT `parties_ibfk_1` FOREIGN KEY (`party_type_id`) REFERENCES `party_types` (`id`);
After this, I generated a model using Gii and I called it SystemUsers.php and I also generated the crud into the systemUsers under view.
Now problem is, every time I select "Create," it throws me an error that it cannot somehow find the parties id.
Just in case, here is the code of my model SystemUsers.php:
<?php
class SystemUsers extends CActiveRecord
{
/**
* Returns the static model of the specified AR class.
* #param string $className active record class name.
* #return SystemUsers 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 'system_users';
}
/**
* #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('username, password, date_last_login, date_created, user_role, isLogin', 'required'),
array('isLogin', 'numerical', 'integerOnly'=>true),
array('username', 'length', 'max'=>200),
array('password, user_role', 'length', 'max'=>255),
array('status', 'length', 'max'=>50),
array('date_modified', 'safe'),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('party_id, username, password, date_last_login, status, date_created, date_modified, user_role, isLogin', '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(
'party_id' => array(self::BELONGS_TO, 'system_users', 'party_id'),
'party_id' => array(self::HAS_ONE, 'parties', 'id'),
);
}
/**
* #return array customized attribute labels (name=>label)
*/
public function attributeLabels()
{
return array(
'party_id' => 'Party',
'username' => 'Username',
'password' => 'Password',
'date_last_login' => 'Date Last Login',
'status' => 'Status',
'date_created' => 'Date Created',
'date_modified' => 'Date Modified',
'user_role' => 'User Role',
'isLogin' => 'Is Login',
);
}
/**
* 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('party_id',$this->party_id,true);
$criteria->compare('username',$this->username,true);
$criteria->compare('password',$this->password,true);
$criteria->compare('date_last_login',$this->date_last_login,true);
$criteria->compare('status',$this->status,true);
$criteria->compare('date_created',$this->date_created,true);
$criteria->compare('date_modified',$this->date_modified,true);
$criteria->compare('user_role',$this->user_role,true);
$criteria->compare('isLogin',$this->isLogin);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
}
You have to implement a multi-step form and a single fatty controller which does all pluming working for you e.g adding/updating all three entities . please see this thread
as u have foreign key Constraints then you have have entry in parent table
system_users -> depends on parties
and
parties -> depends on party_types
so to insert the record in system_user you must have a record in Parites and similarly to insert the record in parties you must have a record in party_types
so first insert the record in party_type and for that party_type create record in Parties and then for that party_id create the record in system_user
I'm trying to create a user and all the values are not inserting into the database. The systems_user table has a relation to a parties table as the party_id is the primary key of the sytems_user. Nothing is being inserted. Not even an error, it just goes back to the "create" page. Here is my schema:
--
-- Table structure for table `system_users`
--
CREATE TABLE IF NOT EXISTS `system_users` (
`party_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(200) NOT NULL,
`password` varchar(255) NOT NULL,
`date_last_login` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`status` varchar(50) NOT NULL DEFAULT 'Pending for Approval',
`date_created` datetime NOT NULL,
`date_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`user_role` varchar(255) NOT NULL,
`isLogin` int(1) NOT NULL,
PRIMARY KEY (`party_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=221 ;
--
-- Constraints for table `system_users`
--
ALTER TABLE `system_users`
ADD CONSTRAINT `system_users_ibfk_1` FOREIGN KEY (`party_id`) REFERENCES `parties` (`id`);
-------------------------------------
-- Table structure for table `parties`
--
CREATE TABLE IF NOT EXISTS `parties` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`party_type_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `party_type_id` (`party_type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=200 ;
--
-- Constraints for table `parties`
--
ALTER TABLE `parties`
ADD CONSTRAINT `parties_ibfk_1` FOREIGN KEY (`party_type_id`) REFERENCES `party_types` (`id`);
Where have I gone wrong? Why is it not inserting?
EDIT
Rules for SystemUser Model:
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('username, password, date_last_login, date_created, user_role, isLogin', 'required'),
array('isLogin', 'numerical', 'integerOnly'=>true),
array('username', 'length', 'max'=>200),
array('password, user_role', 'length', 'max'=>255),
array('status', 'length', 'max'=>50),
array('date_modified', 'safe'),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('party_id, username, password, date_last_login, status, date_created, date_modified, user_role, isLogin', 'safe', 'on'=>'search'),
);
}
Rules for Parties:
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('party_type_id', 'required'),
array('party_type_id', 'length', 'max'=>10),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('id, party_type_id', 'safe', 'on'=>'search'),
);
}
EDIT Controller actionCreate()
A little background: as you can see from below, the conditions inside the if statement is only asking if the SystemUsers is set because the create come from the SystemUser form. My goal is to get the party_id of the system_user and insert it into the Parties table which is a different model from the SystemUsers that i'm using. So far when I run this, nothing happens.
public function actionCreate()
{
$parties = new Parties;
$model= new SystemUsers;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if (isset($_POST['SystemUsers']))
{
$parties->attributes = (HOW can I put the party_id from $model here?);
$model->attributes = $_POST['SystemUsers'];
$valid = true;
$valid &= $parties->validate();
$valid &= $model->validate();
if($valid)
{
$parties->id = $model->getPrimaryKey();
$parties->save(); /* First save parties. */
$model->save();
}
}
$this->render('create',array(
'model'=>$model,
'parties'=>$parties,
));
Yii doesn't insert not-safe values in database, I had this problem before, if you make all attributes safe, you will be fine. your attributes now are safe only in search scenario ( 'on'=>'search' ) . for making all attributes safe in all scenarios, remove 'on'=>'search' from both model rules.
You placed $parties->id = $customers->getPrimaryKey(); after $parties->save();.
if you want to save $parties->id too, place it before save()
Remove redirect line, I think your save() method cannot show errors because of that.
update :
What about this ?
if (isset($_POST['SystemUsers'])) {
$model->attributes = $_POST['SystemUsers'];
if($model->save()){ // save() does validation in itself
$parties->id = $model->getPrimaryKey();
$parties->save();
}
}