I have a MySQL archive table with the following structure:
`histories`
`uid` int(10) unsigned NOT NULL,
`type` varchar(255) NOT NULL,
`param` int(11) NOT NULL,
`param2` varchar(255) NOT NULL,
`time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
ENGINE=ARCHIVE DEFAULT CHARSET=latin1;
I do not want to add an auto-incrementing `id' column. This table's engine is archive and it does exactly what I need it to, with this structure.
I wish to save like this:
$this->History->create();
$this->History->save(['uid' => uid, 'type' => 'deleted_entry', 'param' => $thing_id]);
But CakePHP forces an update, which I don't want and the ARCHIVE engine doesn't support. Cake seems to be looking for a primary key of uid, finding it and deciding that it should update and there seems to be no flag available to force an insert. I do not want to resort to $this->Model->query().
UPDATE:
Set $primaryKey = null in AppModel. $this->create(); will then insert.
class History extends AppModel {
public $primaryKey = null;
}
If you want to do an update after, simply:
$this->History->primaryKey = 'uid'; before the save()
You can tell Cake 2 that you have no primary key by setting the model's $primaryKey property to null:
$this->History->primaryKey = null;
$this->History->create();
$this->History->save(['uid' => uid, 'type' => 'deleted_entry', 'param' => $thing_id]);
Related
The cakephp docs state the following:
You can even create self-associated tables to create parent-child relationships:
class CategoriesTable extends Table
{
public function initialize(array $config)
{
$this->hasMany('SubCategories', [
'className' => 'Categories'
]);
$this->belongsTo('ParentCategories', [
'className' => 'Categories'
]);
}
}
Which sounds good, but the code above doesn't actually do anything by itself. Like the code above looks like it should describe a self-referencing many to many relationship but if you take an existing Table class and just add that to the initialize function, nothing happens. There has to be some associated schema presumably which isn't shown.
So it's not clear how to actually set up a self-referencing relationship.
I've tried this:
CREATE TABLE `categories` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
CREATE TABLE `categories_categories` (
`parent_id` int(11) NOT NULL,
`child_id` int(11) NOT NULL,
PRIMARY KEY (`parent_id`,`child_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
And then baked that... but it's not clear to me how to get that to actually work with models and which models to create and what associations to put in them nor how to get those to be represented by a form element.
I would like to know how to retrieve translation inside a query with cakephp 3.3.
I have already added inside Table:
$this->addBehavior('Translate', ['fields' => ['textContent']]);
This is my query:
$query = $objTable->find('all')
->where(['admin_template_id' => $id])
->contain(['AdminObjects']);
I have already tried this:
$query = $objTable->find('all')
->where(['admin_template_id' => $id])
->contain(['AdminObjects', 'translations']);
But returns me error 500.
My translation table is the same of the cakephp documentation:
CREATE TABLE i18n (
id int 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 text,
PRIMARY KEY (id),
UNIQUE INDEX I18N_LOCALE_FIELD(locale, model, foreign_key, field),
INDEX I18N_FIELD(model, foreign_key, field)
);
How can I fin translation inside a find all query?
Thanks
You may use find method 'translations' instate of 'all'.
try
$query = $objTable->find('translations')
->where(['admin_template_id' => $id])
->contain(['AdminObjects']);
instate of
$query = $objTable->find('all')
->where(['admin_template_id' => $id])
->contain(['AdminObjects']);
officeial Doc Retrieve All Translations
I have exactly the same scripts and exactly same databases running on localhost and on live server. The problem I face is that the date for 'created' is not automatically stored.
Here is the controller action:
function add() {
if (!empty($this->data) ) {
$this->Customer->create();
if ($this->Customer->save($this->data)) {
$this->Session->setFlash(__('Customer was saved'), 'positive_notification');
$this->redirect(array('controller'=>'customers', 'action' => 'index'));
} else {
$this->Session->setFlash(__('Customer was not saved. Please try again'), 'negative_notification');
}
}
}
There is also no function for beforeSave.
And here is the database table:
`customers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`company_id` int(11) NOT NULL,
`customer_nr` varchar(20) DEFAULT NULL,
`name` varchar(60) DEFAULT NULL,
`address` varchar(250) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`phone` varchar(18) DEFAULT NULL,
`post_nr` varchar(6) DEFAULT NULL,
`city` varchar(50) DEFAULT NULL,
`color` varchar(7) NOT NULL,
`created` date DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `company_id` (`company_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=113 ;
Any help is much appreciated.
I think you must use:
$this->request->data //instead of $this->data
But if the created is the only field that is not saved try to debug first the $this->data then try this first to see if its really saving a data:
$this->data["Customer"]["created"] = data("Y-m-d"); // temporarily set to current date just to see if it was saving
$this->Customer->save($this->data)
Then checked if its added on your database. If yes, then you must update your $this->data, it may contain incorrect values or incorrect format of date.
The date is not automatically updating, because you set created to be date instead of datetime.
As stated on "Saving Your Data"
By defining a created and/or modified field in your database table as datetime fields (default null), CakePHP will recognize those fields and populate them automatically whenever a record is created or saved to the database (unless the data being saved already contains a value for these fields).
I hope this will solve your problem.
I've got a Cakephp Project with an 'Addresses' table with the following structure:
CREATE TABLE `addresses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`name` varchar(50) NOT NULL,
`company` varchar(50) NOT NULL,
`address1` varchar(50) NOT NULL,
`address2` varchar(50) DEFAULT NULL,
`city` varchar(40) NOT NULL,
`state` varchar(2) NOT NULL,
`country` varchar(2) NOT NULL,
`zip` varchar(5) NOT NULL,
PRIMARY KEY (`id`)
)
There is a page in this project which asks the user for both a Shipping Address and a Billing Address, and im not certain how to structure the names of the form inputs to allow multiple instances of the same database fields on one page
In the View, I've attempted to use an alias to seperate the two instances of the Address fields
I.E.-
<?=$this->Form->input('Shipaddress.zip', array('label' => 'Zip Code'));?>
...
<?=$this->Form->input('Billaddress.zip', array('label' => 'Zip Code'));?>
then in the view, i tried to seperate the two instances, validate both, and set the appropriate $this->validationError values to properly display the errors to the correct field views
// place in arrays with proper model name ['Address']
$ship_array['Address'] = $this->request->data['Shipaddress'];
$bill_array['Address'] = $this->request->data['Billaddress'];
//Set Data to model, Validate Against model, change model name in validationErrors to match aliased fields, and remove validationErrors for ['Address']
$this->Address->set($ship_array);
$shipping_valid = $this->Address->validates(array('fieldList' => array('name', 'company', 'address1', 'address2', 'city', 'state', 'country', 'zip')));
$this->validationErrors['Shipaddress'] = $this->validationErrors['Address'];
$this->validationErrors['Address'] = array();
//Do it again for Billing Address fields
$this->Address->set($bill_array);
$billing_valid = $this->Address->validates(array('fieldList' => array('name', 'company', 'address1', 'address2', 'city', 'state', 'country', 'zip')));
$this->validationErrors['Billaddress'] = $this->validationErrors['Address'];
$this->validationErrors['Address'] = array();
unfortunately, this doesnt appear to work, and i'm afraid that I've gone too far trying to make this work...
can someone give my a kick in the right direction on how this can be done properly?
Figured out how to do it on my own...
in /app/Model i created 'ShippingAddress.php' and 'BillingAddress.php', Both Extend "Address"
//ShippingAddress.php
<?php
App::uses('Address', 'Model');
class ShippingAddress extends Address {
}
//BillingAddress.php
<?php
App::uses('Address', 'Model');
class BillingAddress extends Address {
}
To prevent the new models from using tables named after them, we edit the parent Address.php and set $useTable so that both extended models use Addresses Table
//Address.php
...
public $useTable = 'addresses';
...
then its just a matter of inserting the two instances of the input fields into the view... no renaming models, no modifying validationErrors, it just works :)
I am new to cakePHP and trying to get my head around the framework to see how to implement my requirements.
My application allows (admin) users to define Forms (parent) and FormElements (child) that later on will be composed on the fly and presented to the end-users.
To start prototyping I baked all the pieces and I can enter rows in both tables as expected.
edit to simplify the question:
The Forms controller already shows a list of Forms and when one is selected (view action), a list of the FormElements for that Form.
But... when I add a new FormElement, I have to select again a Form the Element will be associated to.
Instead I want the FormElements controller/model to know which Form was initially selected and fill the form_id automagically.
Is there a "best practice" approach on how to handle this ?
Just in case its needed:
CREATE TABLE IF NOT EXISTS `forms` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`description` varchar(60) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `form_elements` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`form_id` int(11) NOT NULL,
`name` varchar(40) NOT NULL,
`type` int(11) NOT NULL,
`widget` int(11) NOT NULL,
`mandatory` tinyint(4) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
This happens more often than you think. I had QuestionModel hasMany AnswerModel and wanted to add Answers within my AnswersController. I needed to show QuestionModel name and other attributes of the "parent" object. This is what my add action inside my AnswersController looks like:
public function add($question_id = null) {
$this->Answer->Question->id = $question_id;
if (!$this->Answer->Question->exists()) {
throw new NotFoundException(__('Invalid question'));
}
if ($this->request->is('post')) {
$this->request->data['Answer']['question_id'] = $question_id;
$this->request->data['Answer']['user_id'] = $this->Auth->user('id');
if ($this->Answer->save($this->request->data)) {
$this->Session->setFlashSuccess(__('Your answer has been saved'));
} else {
$this->Session->setFlashError(__('Your answer could not be saved. Please, try again.'));
}
$this->redirect(array('controller'=>'questions','action' => 'view', $question_id));
}
$question = $this->Answer->Question->read();
$this->set('question', $question);
}
You will notice that I am passing the Question.id to the AnswersController add action. Having this allows me to pull the Question from the DB and allows me to be able to redirect the user back to the specific question they were on before they clicked on "Add Answers to this Question".