Associate tables from different database cakephp 3.0 - cakephp-3.0

I have two database with name default and default_history. And tables with name users and wafer_detail_history under default database and order_history under default_history database. want to associate Users table with OrderHistory table.
OrderHistoryTable :-
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('order_history');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->hasMany('WaferDetailHistory', [
'foreignKey' => 'order_id'
]);
$this->belongsTo('Users', [
'foreignKey' => 'created_by',
'joinType' => 'INNER'
]);
}
i used this.
$connection = ConnectionManager::get('default_history');
$this->OrderHistory = TableRegistry::get('OrderHistory');
$this->OrderHistory->setConnection($connection);
$id = 37;
$order_history = $this->OrderHistory->get($id, ['contain' => ['Users']]);
but not able to succeed. getting this error:
Base table or view not found: 1146 Table 'default_history.users'
doesn't exist

I had the same problem few days ago,
You must had 'strategy' => 'select' in your BelongTo to join with the other database
$this->belongsTo('Users', [
'strategy' => 'select'
'foreignKey' => 'created_by',
'joinType' => 'INNER'
]);

Try this on the OrderHistoryTable.php File:
$this->setTable('default_history.order_history');

Related

CakePHP 3 is saying a table doesn't exist in another database when using an ORM query

I have an application in CakePHP 3.5.13 which uses four different databases.
In my config/app.php I have configured two of these as follows:
'Datasources' => [
'default' => [ 'database' => 'sdb5_hub_subdb', ... ],
'db_orgs' => [ 'database' => 'dev_hub_subdb_orgs', ... ]
];
So this means there are 2 databases with the names sdb5_hub_subdb and dev_hub_subdb_orgs.
I'm attempting to do a query which does a join on a table in each database.
I have my Table entities configured as follows:
// src/Model/Table/TblListsSubstancesCommentsTable.php
public function initialize(array $config)
{
$this->belongsTo('Substances', [
'foreignKey' => 'substance_id',
'joinType' => 'INNER'
]);
}
public static function defaultConnectionName()
{
return 'db_orgs';
}
// src/Model/Table/SubstancesTable.php
public function initialize(array $config)
{
$this->belongsTo('TblListsSubstancesComments', [
'foreignKey' => 'substance_id'
]);
}
When I attempt to do the following with the ORM:
$query = $Substances->find()->select(['id' => 'Substances.id'])->distinct();
if ($this->request->getData('org_information')) {
$org_information = $this->request->getData('org_information');
$query = $query->matching('TblListsSubstancesComments', function ($q) use ($org_information) {
return $q->where(['TblListsSubstancesComments.comment LIKE' => '%'.$org_information.'%' ]);
});
}
It's producing an SQL error:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'sdb5_hub_subdb.tbl_lists_substances_comments' doesn't exist
I don't understand this because the table definitely exists. Furthermore my TblListsSubstancesCommentsTable.php has defaultConnectionName() in it to specify that it should use the db_orgs connection. So I assume it must know to go to the second database to load that table? It's like it's looking in the default database and not finding it, but I don't know why, because the Table entity is telling it where it needs to look.

CakePHP show all books whose author is not in the authors table

I can't seem to wrap my head around the CakePHP ORM model...
I have a table Authors (with Author.ID) and a list of books (with Book.AuthorID) - a lot of the books have an AuthorID which doesn't exist in the Authors Table (this is by design and expected)
For statistical reasons I would like to list all Books which have an AuthorID and the AuthorID isn't found in the Authors table.
I could load all books into memory and lookup the id's by hand - but there are ~4000 books. I'd like to do this in a ORM way (left outer join?)
Thanks,
MC
This is a pretty simple task with the orm. As #ndm mentioned in the comments, you can do this with a left join which is the default of the belongsTo association.
In the BooksTable make sure the association is added in the initialization method:
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('books');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->belongsTo('Authors', [
'foreignKey' => 'author_id'
]);
}
In your Books controller (if that is the controller you are doing things in):
$books_without_authors = $this->Books
->find()
->contain(['Authors'])
->where(['Authors.id IS NULL'])
->all();
$books_with_authors = $this->Books
->find()
->contain(['Authors'])
->where(['Authors.id IS NOT NULL'])
->all();
If you are going to be doing this from multiple controllers then the DRY way to do it is as an association:
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('books');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->belongsTo('Authors', [
'foreignKey' => 'author_id'
]);
$this->belongsTo('WithAuthors', [
'className' => 'Authors',
'foreignKey' => 'author_id',
'joinType' => 'INNER'
]);
$this->belongsTo('WithoutAuthors', [
'className' => 'Authors',
'foreignKey' => 'author_id',
'conditions' => ['Authors.id IS NULL']
]);
}
You can then call these in your controller
$with_authors = $this->Books
->find()
->contains(['WithAuthors'])
->all();
$without_authors = $this->Books
->find()
->contains(['WithoutAuthors'])
->all();

Cakephp 3.0 join in three table

I am trying to fetch the data from three table in cakephp 3.0
There is three table
1) size_category
2) sizes
3) sizerelations
Below is the file wise code
Model SizeCategoryTable.php
public function initialize(array $config)
{
parent::initialize($config);
$this->table('size_category');
$this->displayField('sizeCat_Id');
$this->primaryKey('sizeCat_Id');
// used to associate the table with user table (join)
$this->belongsTo('Users', [
'className' => 'Users',
'foreignKey' => 'CreatedBy',
'propertyName' => 'user'
]);
$this->hasMany(
'Sizerelations', [
'className' => 'Sizerelations',
'foreignKey' => 'Scat_Id',
'propertyName' => 'sizerelations'
]
);
}
Controller SizeCategoryController
public function index($id = null)
{
$customQuery = $this->SizeCategory->find('all', array(
'contain' => array(
'Users',
'Sizerelations' => array(
'Sizes' => array(
'fields' => array('id', 'Size_Code')
)
)
)
));
//debug();die();
$this->set('sizeCategory', $this->paginate($customQuery));
$this->set('_serialize', ['sizeCategory']);
}
I am greeting the error of Sizerelations is not associated with Sizes

Rename a table in the controller by query

I try to do a private message application with an user_id who send the message and a post_id who receive the message in the table.
I did the association on my table like this:
$this->belongsTo('receiver', [
'className' => 'Users',
'foreignKey' => 'post_id'
]);
$this->belongsTo('shipper', [
'className' => 'Users',
'foreignKey' => 'user_id'
]);
But now I need to merge these to get one 'interlocutor' in my request:
$messages = $this->Messages->find()->where(['post_id =' => $id])
->orWhere(['user_id =' => $id])->contain(['shipper','receiver']);
I know I have to filter with function in the contain to get only the shipper or the receiver who's not me but I don't know how to merge or simply rename 'shipper' and 'receiver' into 'interlocutor'.
All I did is working, btw.
I'm not that good in english so if you have a better title, let me know it
Thanks for help
I guess you need something like http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#custom-finder-methods
Example:
public function findInterlocutor(Query $query, array $options)
{
$query->contain(['shipper','receiver']);
return $query;
}
Calling it this way:
$messages = $this->Messages->find()->where(['post_id =' => $id])
->orWhere(['user_id =' => $id])->find('interlocutor');
Please let me know if it works...

CakePHP find Queries with aliases SQLSTATE[42S22] Error

I'm having a weird problem with my relationships/aliases in CakePHP and now its preventing me from accessing my data correctly.
I have:
User hasMany CreatorModule (alias for Module)
User HABTM LearnerModule (alias for Module)
Module belongsTo Creator (alias for User)
Module HABTM Learner (alias for User)
And I'm trying to call:
$id = $this->Module->User->findByEmail($email);
$modules = $this->Module->findByUserId($id['User']['id']);
The queries that get generated aren't correct - the table-alias is wrong. I'm not sure which of the above is responsible but I get:
SELECT
`Creator`.`id`,
`Creator`.`email`,
`Creator`.`organization`,
`Creator`.`name`,
`Creator`.`password`,
`Creator`.`verified`,
`Creator`.`vcode`
FROM
`snurpdco_cake`.`users` AS `Creator`
WHERE
`User`.`email` = 'foo#example.com' # <--
LIMIT 1
I figured out that the error is that CakePHP should change 'User' in the WHERE clause to Creator, but doesn't, even if I use the alias. How do I complete this query correctly.
Further, as a related problem, I find that I can no longer use User in my model calls etc now that I have defined aliases. Is there a way around this?
EDIT: As requested, here is my model code defining the aliases:
class User extends AppModel {
public $name = 'User';
public $uses = 'users';
public $hasMany = array(
'OwnedModule' => array(
'className' => 'Module',
'foreignKey' => 'user_id',
'dependent' => true
));
public $hasAndBelongsToMany = array(
'LearnerModule' => array(
'className' => 'Module',
'joinTable' => 'modules_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'module_id',
'unique' => 'keepExisting',
));
//The rest of the Model
}
//Different file, condensed here for spacing
class Module extends AppModel {
public $name = 'Module';
public $belongsTo = array(
'Creator' => array(
'className' => 'User'));
public $hasAndBelongsToMany = array(
'Learner' => array(
'className' => 'User',
'joinTable' => 'modules_users',
'foreignKey' => 'module_id',
'associationForeignKey' => 'user_id',
'unique' => 'keepExisting',
));
//The rest of the Model
}
try
$id = $this->Module->Creator->find('first',
array('conditions' => array('Creator.email' => $email)
);
$modules = $this->Module->findByCreatorId($id['User']['id']);