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
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 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]);
Let's say I have two tables:
CREATE TABLE drinks (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
morning_drink_id INT,
evening_drink_id INT
);
How can I make those drink_id references valid?
I’ve tried:
adding a view
CREATE VIEW morning_drinks AS SELECT * FROM drinks;
CREATE VIEW evening_drinks AS SELECT * FROM drinks;
adding foreign keys
FOREIGN KEY morning_drink_key (morning_drink_id) REFERENCES drinks(id),
FOREIGN KEY evening_drink_key (evening_drink_id) REFERENCES drinks(id)
bake craches in both cases... Is there a proper way?
public $belongsTo = array(
'Drink' => array(
'className' => 'Drink',
'foreignKey' => 'morning_drink_id'
)
);
this you can add to Users model. And this is how to do it.
edit:
Bake is expecting tables for your two foreign keys, and it’s complaining about them. I got the same error as you when I deleted the ‘morning_drinks’ view, else it created all. Add those two views and try again.
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'm trying to have this query
SELECT * FROM `rentprograms` AS `Rentprogram`
inner join `vehiclerentprograms` as `Vehiclerentprogram` on `Vehiclerentprogram`.`rentprogramid` = `Rentprogram`.`id`
inner join `vehicles` AS `Vehicle` ON `Vehicle`.`id` =`Vehiclerentprogram`.`vehicleid` WHERE `Vehicle`.`id` = 1
Code in CakePHP
$this->Rentprogram->find('all'), array(
'fields'=>array('*'),
'joins' => array(
array(
'table' => 'vehiclerentprograms',
'alias' => 'Vehiclerentprogram',
'type'=>'inner',
'conditions' => array(
'Vehiclerentprogram.rentprogramid' => 'Rentprogram.id',
)
),
array(
'table' => 'vehicles',
'alias' => 'Vehicle',
'type'=>'inner',
'conditions' => array(
'Vehicle.id' => 'Vehiclerentprogram.vehicleid',
)
)
),
);
But it only display the value of Rentprogram. How can i have all the fields related to Rentprogram, Vehicle, Vehiclerentprogram.
There's no value in using an MVC framework and do the dirty joins by hand. You'd better use Cake conventions, which lets you access Cake's libraries and tools which in turn speed up the development process quite a lot. In this case you have to setup models and associations between models (I hope you have heard of has-many, belongs-to, many-to-many and so on).
CakePHP ships with an invaluable DAO layer and a code generator called bake. Once you design the database schema, forget about SQL and think in terms of your business objects. First, create three tables in MySQL (I used a minimal set of fields and deduced the structure from your query):
CREATE TABLE `programs` (
`id` int(11) AUTO_INCREMENT,
`start` datetime DEFAULT NULL,
`end` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `vehicles` (
`id` int(11) AUTO_INCREMENT,
`model` varchar(128) DEFAULT NULL,
`plate` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `vehicle_programs` (
`id` int(11) AUTO_INCREMENT,
`program_id` int(11) DEFAULT NULL,
`vehicle_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
);
Then run the shell script:
Console/cake bake all
and select one table at a time (remember vehicle_programs must be the last one). This will generate all Models, Controllers and Views files for you. Then you can start filling your database with test data. Point your browser to http://host/vehicle_programs and put some vehicle and program in.
Finally I will show you how to retrieve all of the fields in one query. Suppose that you want to show everything when listing vehicle_programs. In the index() method of VehicleProgramsController you have to set $this->VehicleProgram->recursive to 1, so that it fetches related models fields as well. In the view index.ctp you'll now be able to access fields like
<?php
foreach ($vehiclePrograms as $vehicleProgram) {
echo $vehicleProgram['Program']['start'];
echo $vehicleProgram['VehicleProgram']['id'];
echo $vehicleProgram['Vehicle']['plate'];
}
Note if we hadn't set Model->recursive to 1, Cake wouldn't have fetched fields of related models (Vehicle and Program) for us.
Incidentally, I think not setting the fields key at all should do the trick, since Cake reads everything by default. However, the correct solution is using relationships between model classes - when you run bake it puts the following in Model/Vehicle.php:
class Vehicle extends AppModel {
public $hasMany = array(
'VehicleProgram' => array(
'className' => 'VehicleProgram',
'foreignKey' => 'vehicle_id',
'dependent' => false
)
);
}
and symmetric associations in Model/VehicleProgram.php
You can use this method
$this->Rentprogram->find('all'), array(
'fields' => array('Rentprogram.*', 'Vehicle.*', 'Vehiclerentprogram.*'), ...