I'm using CakePHP 3.
I have an accounts table. Each Account belongs to a Country. Countries table is internationalized using Translate Behavior, so it can store countries names for each language.
class CountriesTable extends Table
{
public function initialize(array $config)
{
$this->table('countries');
$this->displayField('name');
$this->primaryKey('id');
$this->addBehavior('Translate', ['fields' => ['name']]);
}
Note that "name" field is internationalized through the Translate behavior, so it's not present in the countries table.
Then in the AccountsController I want to get the list of the countries using the active language:
....
$countries = $this->Accounts->Countries->find('list', ['limit' => 200]);
.....
The problem is that it's not getting the translations from the i18n table as expected. I already have coded the maintentance actions for the internationalized countries table, and everything is working OK, but this simple find('list') is not working.
One more detail: in the Mysql logs I see it has launched this query. Note that the countries table has only two fields: id and code, but the displayField is name.
SELECT Countries.id AS `Countries__id`, Countries.code AS `Countries__code` FROM countries Countries LIMIT 200
btw, it's getting really difficult to switch from 2.x to 3.x.
I found the problem after a lot of investigating. If my case, accounts table is not internationalized, but the related table countries it is.
The problem is that I didn't set the locale in the Accounts controller. After putting this line before the finds, everything worked fine:
I18n::locale('spa');
So I guess that if you don't stablish the locale using I18n, Translate behavior won't work at all. I should load it in AppController to make it application wide available.
Thanks a lot for your help!!
Related
I'm having some difficulty getting results from a hasMany relationship in my view file. I'm not getting any errors from the debug console so I'm not sure where I'm tripping up.
I think that maybe I'm not referencing correctly in the view file (I'm not really sure how to write a foreach function for this), if I'm not setting it up correctly in the table file, etc.
2 tables: "Clinicas", "Tratamientos" (services)
Goal: On a Clinic's profile page, I need to show the information for that Clinic (location, phone number, etc.) & list all of the services associated with that clinic.
ClinicasTable.php
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('clinicas');
$this->setDisplayField('name');
$this->setPrimaryKey('clinic_id');
$this->addBehavior('Timestamp');
$this->hasMany('Tratamientos', [
'foreignKey' => 'clinic_id',
'joinType' => 'INNER'
]);
}
ClinicasController.php
public function view($id = null)
{
$clinica = $this->Clinicas->get($id, [
'contain' => ['Tratamientos']
]);
$this->set(compact('clinica'));
}
view.php
<?php foreach($clinica as $tratamiento): ?>
<?= h($clinica->tratamiento->name)?>
<?php endforeach;?>
I've had a look at the documentation for associations but can't figure out how to get to data from my tables. I could always just do an ajax query through php functions, but I'd really like to do it right using CakePHP. Any help would be much appreciated!!!
Even though iterating is pretty much just basic PHP, the example in the book could be a little more helpful and show iterating over and using the associated data, even though it should already give you a good idea where you data lives.
You are obtaining a single entity (an instance of Clinica), so you cannot and should not iterate over it. What your code will do is iterate over all public properties of the entity object, which is not what you want, and won't do anything in your case, as by default entities do not have any concrete public properties.
The data of the association will be found on the association property of the Clinica entity, which, unless specifically configured otherwise via the association's property option, is the plural, underscored, lowercased variant of the association name, so for Tratamientos that would be tratamientos.
It should be noted that you really should stick to US english here for namings, as all the inflector magic around naming conventions is designed to work with that, names in other languages can easily cause mismatches/problems when they cannot be inflected properly!
Long story short, you iterate the $clinica object's tratamientos property, that's where the hasMany associated data lives:
<?php foreach($clinica->tratamientos as $tratamiento): ?>
<?= h($tratamiento->name)?>
<?php endforeach;?>
If you are unsure about a data structure, debug it: debug($clinica)
[edit] solved, see: https://stackoverflow.com/a/32638610/221650
Some associated data is not coming through, although it's in the contain clause.
I can get $project->Participants if I set a belongsToMany relationship in the Projects table, relating to Participants through ProjectParticipants, but that way I still can't reach other tables associated with ProjectParticipants even with $project->participants->_joinData->other_related_table
How would I do to get ProjectParticipants and Participants with the same query?
Code:
// Database: Projects <--1:N-- ProjectParticipants --M:1--> Participants
// ProjectController:
$project = $this->Projects->get($id, ['contain'=>[
'ProjectParticipants.Participants']);
// ProjectsTable:
$this->hasMany('ProjectParticipants', [
'foreignKey' => 'project_id']);
// ProjectParticipantsTable:
$this->belongsTo('Participants', [
'foreignKey' => 'participant_id']);
It's a very complicated many to many relationship.
//projectTable
$this->belongsToMany('Participants');
//praticipantsTable
$this->belongsToMany('Projects');
It's well explained in the Bookmark Tutorial.
Sorry, it's working fine, I hadn't noticed there was a custom Entity\Project::_getParticipants() that was returning a Collection.
A simple debug on that object showed everything alright, but then when running it through a foreach, the associations disappeared.
I just started my project with cakephp3.0. I startet with the Users. I put a function isAuthorized in the UsersController which should validate if the User is permitted to view other users, to edit other users and so on.
I created a table "userprivileges" where all possible privileges, which can be assigned to a user are listed.
The table is "userprivileges" is:
id | controller | function
Next I want to group the priviliges into roles.
I created following table: "userprivilegeroles"
id | role
Next I created the BTM-Table: "userprivileges_userprivilegeroles"
id | userprivilegerole_id | userprivilegerole_id
The User is linked to the userprivilegeroles table, so I need to search if the requested controller/function is view-able for the user.
I tried like this:
$this->loadModel('Userprivilegeroles');
$userprivilegeroles = $this->Userprivilegeroles->find('all', [
'conditions' => [
'Userprivileges.controller' => $this->request->controller,
'Userprivileges.function' => $this->request->action],
'contain' => ['Userprivileges']
]);
Now this fails with following error:
Userprivilegeroles is not associated with Userprivileges.
There is a little more description, where I can search for the problem prompted to the 500 page.
The class for the specified table does not exist.
The Table was created with a typo: TableRegistry::get('Atricles');
The class file has a typo in the name or incorrect namespace: class Atricles extends Table
The file containing the class has a typo or incorrect casing: Atricles.php
The Table was used using associations but the association has a typo: $this->belongsTo('Atricles')
The table class resides in a Plugin but no plugin notation was used in the association definition.
Lets go for it one by one:
The class for the specified table does not exist.
It does:
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class UserprivilegerolesTable extends Table
{
public function initialize(array $config){
$this->belongsToMany('Userprivileges', [
'joinTable' => 'userprivileges_userprivilegeroles',
'className' => 'Userprivileges'
]);
}
}
Next
The Table was created with a typo: TableRegistry::get('Atricles');
No.
The class file has a typo in the name or incorrect namespace: class Atricles extends Table
no.
The file containing the class has a typo or incorrect casing: Atricles.php
no. its in src/Model/Table/Userprivilegeroles.php
The Table was used using associations but the association has a typo: $this->belongsTo('Atricles')
See above. I don't see a typo.
The table class resides in a Plugin but no plugin notation was used in the association definition.
As described, I called it from the UsersController.
Can anyone help me finding, why the association doesn't work as expected? Maybe I am to much stuck in the cakephp 2.0 ORM, but I am almost sure that I did the association like described in the cookbook.
I've searched already and found some other issues with the belongstomany association. But they all handle problems with saving data. I want to search data, so I see no connection there.
Actually the filename is incorrect, filenames must match classnames (PSR-4), so it should be UserprivilegerolesTable.php. The warning notes may need some fixing or further explanation, as they are a little misleading by not using the Table suffix.
Once you've fixed that you'll stumble over the next problem, contained belongsToMany and hasMany associations cannot be used in conditions, as they are retrieved in a separate query, you'll have to use matching() instead.
Cookbook > Database Access & ORM > Query Builder > Filtering by Associated Data
How to filter by conditions for associated models?
Using Cakephp 2.5.3 ... I have the following tables:
transactions (belongs to methods and deliveries)
id
delivery_id
method_id
methods (has many transactions)
id
name
deliveries (has many transactions)
id
date
In my delivery view I would like to see the method name for each delivery.
foreach ($deliveries as $delivery) {
echo $method['name'];
}
( a similar unanswered question is
here:)
I am (obv.) very new to Cakephp, What approach should I take to go about this? Thanks!
=========UPDATE==============
I ended up adding methods to the deliveries controller
$this->set('methods', $this->Method->find('all', array('recursive' => -1)));
And looped through the methods in my (read only) view :
//filtered method array for
$method['id'] == $delivery['Transaction']['0']['method_id'])
// got method name
$button_text = $method['name'];
It works fine but can anyone tell me if this may cause problems for me down the line?
use has many assotiations in Transaction model as -
public $hasMny = array('Method', 'Delivery');
then fetch them -
$this->set(
'methods',
$this->Method->find('all', array('contain' => array('Method', 'Delivery')))
);
you will get all the related result together.
I have the following model class:
class Property extends AppModel
{
var $name = 'Property';
var $hasMany = array(
'Inventory' => array(
'className' => 'Inventory',
'foreignKey' => 'property_id'
)
);
}
My database schema is set so that the id fields are all set to CHAR(36) so that CakePHP generates UUIDs for each entity. When I attempt to perform a find on my Property entity, it doesn't seem to be adding the necessary join to retrieve any related Inventories. Does anyone have any experience with this issue?
Thanks!
UUIDs will have nothing to do with it, I have a very similar model setup and use UUIDs everywhere.
You technically don't need those className and foreignKey declarations in there, as you seem to be following the CakePHP convention :)
I'd remove those lines, check your database for actual inventories with product IDs. If not, post the find()s you're doing.
The answer turns out to be somewhat stupid.
I'd migrated this from a CakePHP 2.0 install to a CakePHP 1.3 install (couldn't update PHP on the server I was using), and all of my model classes still had uppercase first characters. Changing the file from Property.php to property.php fixed it.