Linking and displaying data from tables in cake php 3 - php

I am trying to display the names from the types table in my jobs/index.ctp
not sure how to echo this, so far I have written this
but it is not working but also not giving any error message
class Jobs extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('jobs');
$this->setDisplayField('title');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Categories', [
'foreignKey' => 'category_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Types', [
'foreignKey' => 'type_id',
'joinType' => 'INNER'
]);
}
class Types extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('types');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->hasMany('Jobs', [
'foreignKey' => 'type_id'
]);
}
<?php
foreach ($jobs as $jobs):
?>
<li>
<div class="type"><span style="background:"> <?php echo $jobs['types']['name']; ?> </span></div>
<div class="description">
<h5><?php echo $jobs['title']; ?> (<?php echo $jobs['city']; ?> , <?php echo $jobs['postcode']; ?>)</h5>
<h6><strong>company Name: <?php echo $jobs['company_name']; ?></strong></h6>
<h6>Date Posted:<span id="list_date"> <?php echo $this->Time->Format($jobs['created'], "d MMMM y") ?> </span></h6>
It all works apart from this line <?php echo $jobs['types']['name'] ;?>

First off, your foreach loop should be foreach ($jobs as $job). Note the singular $job for the variable that tracks each particular job.
Following on that singular note, since Jobs belongTo Types, there is only a single type for each job, not multiple. As a result, the value you're looking for is
$job['type']['name'] ($job->type->name will likely also work). This all assumes that you've correctly used containment when loading the record; hence why I asked for that code to be shown too.
If Jobs had many Types, then you'd have $job['types'] (or $job->types), which would be an array of Type entities that you could iterate over.

For displaying the associated table data you need 3 things:
Association in Table,
$this->belongsTo('Types', [
'foreignKey' => 'type_id',
'joinType' => 'INNER'
]);
In controller (JobsController) specify the associated table using contain,
public function index() {
$jobs = $this->Jobs->find('all')->contain(['Types']);
//set jobs variable to make it available in .ctp file
}
In Jobs/index.ctp file
<?php echo $job['types']['name'] ;?>

Related

Saving an Association with CakeDC Users

I am using CakeDC Users and as part of the registration I would like the registrant to choose some checkbox values that correspond to another Model in the application. I am able to get the form to load the choices just fine, but I am unable to get it to save to the join table even though I have added all of the associations and accessibilities where it would seem relevant. The form is displaying in a similar way to other areas where I am saving the same type of association with a different model.
TypesTable.php
{
public function initialize(array $config): void
{
//$this->addBehavior('Timestamp');
$this->setDisplayField('type');
$this->setPrimaryKey('id');
$this->belongsToMany('Words');
$this->belongsToMany('Users');
$this->belongsTo('Languages', [
'foreignKey' => 'language_id',
'joinType' => 'INNER',
]);
}```
UsersTable.php (in the plugin folders)
```class UsersTable extends Table
{
...
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('users');
$this->setDisplayField('username');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->addBehavior('CakeDC/Users.Register');
$this->addBehavior('CakeDC/Users.Password');
$this->addBehavior('CakeDC/Users.Social');
$this->addBehavior('CakeDC/Users.LinkSocial');
$this->addBehavior('CakeDC/Users.AuthFinder');
$this->hasMany('SocialAccounts', [
'foreignKey' => 'user_id',
'className' => 'CakeDC/Users.SocialAccounts',
]);
$this->hasMany('Types', [
'foreignKey' => 'user_id', 'targetForeignKey' => 'type_id',
'joinTable' => 'types_users']);
}```
In order for a "belongsToMany" association to work in this instance, both *Table.php files must have the relations listed as belongsToMany. Don't forget to make the field accessible in the Entities as well.
One also needs to place the associated array in the patchEntity function in the RegisterBehavior.php file.
UserTable.php (in CakeDC users)
public function initialize(array $config): void
{
...
$this->belongsToMany('Types', [
'foreignKey' => 'user_id', 'targetForeignKey' => 'type_id',
'joinTable' => 'types_users']);
}
TypesTable.php (in app)
class TypesTable extends Table
{
public function initialize(array $config): void
{
....
$this->belongsToMany('Users');
$this->belongsTo('Languages', [
'foreignKey' => 'language_id',
'joinType' => 'INNER',
]);
}
RegisterBehavior.php
$user = $this->_table->patchEntity(
$user,
$data,
['validate' => $validator ?: $this->getRegisterValidators($options), 'associated' => ['Types']]
);

Cannot search based on multiple id in find query in Cakephp 3

I have two tables category and product. I want to get details of product whose id are passed in conditions array of find query. The problem is when i pass condition as an array, it returns
Cannot convert value to integer
Secondly, if i debug it by passing only one id it returns category record, but it should return product record. Please help to solve my issue.
My code is as follows:
public function display()
{
$ids = array(1,2,3,4,5);
$c_List = $this->Products->Categories->find('all',array('conditions'=>array('Categories.category_id'=>$ids)));
$data = $c_List->toArray();
debug($data);
die();
}
Model - ProductsTable.php
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('products');
$this->setDisplayField('product_id');
$this->setPrimaryKey('product_id');
$this->belongsTo('Products', [
'foreignKey' => 'product_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Categories', [
'foreignKey' => 'category_id',
'joinType' => 'INNER'
]);
}
Model - CategoriesTable.php
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('categories');
$this->setDisplayField('category_id');
$this->setPrimaryKey('category_id');
$this->belongsTo('Categories', [
'foreignKey' => 'category_id',
'joinType' => 'INNER'
]);
}
When you are finding the records based on an array of ids, use IN in the condition clause.
public function display()
{
$ids = array(1,2,3,4,5);
$c_List = $this->Products->Categories->find('all',array('conditions'=>array('Categories.category_id IN'=>$ids)));
$data = $c_List->hydrate(false)->toArray();
pr($data);
die();
}

In CakePHP, how to have a Table belongsToMany OtherTable hasMany AnotherTable

I am creating a tool that allows to generate dynamic forms. There are several tables in question:
Form [the Form master table]
FormField [JoinTable to Field]
Field [the fields available for inclusion in Form]
FieldValidation [The table containing relation data between the FormField and the Validation option]
Validation [The available Validation options]
For the FieldValidation - this could in effect be a hasMany from Field, but I am unsure of whether I need to set up this relation from the Field table, or from the join table FieldValidation. The Validation table literally just includes the definitions for the validation options. This does not actually need to be a belongsToMany relation from the FormField/Field table. A hasMany is fine if that simplifies things.
Is this even possible?
Form -> [FormField] -> Field -> [FieldValidation] -> Validation
I have never done this before - so if there is a better way to approach this, I am all ears. My main concern is being able to select Form, contain Field's, and then contain the Validation for each field selected. Obviously, multiple validation rules can be selected per field.
A little late, but I did resolve this issue.
ERD Diagram of Physical Relationship in DB
Model: UsersTable
class UsersTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('users');
$this->displayField('username');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsToMany('Projects', [
'foreignKey' => 'user_id',
'targetForeignKey' => 'project_id',
'through' => 'ProjectsUsers'
]);
$this->hasMany('ProjectsUsers', [
'foreignKey' => 'user_id'
]);
}
}
Model: ProjectsTable
class ProjectsTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('projects');
$this->displayField('name');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsToMany('Users', [
'foreignKey' => 'project_id',
'targetForeignKey' => 'user_id',
'through' => 'ProjectsUsers'
]);
$this->hasMany('ProjectsUsers', [
'foreignKey' => 'project_id'
]);
}
}
Model: ProjectsUsersTable - this is the model for the JOIN table (through)
class ProjectsUsersTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('projects_users');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Users', [
'foreignKey' => 'user_id'
]);
$this->belongsTo('Projects', [
'foreignKey' => 'project_id'
]);
$this->hasMany('ProjectsUsersPermissions', [
'foreignKey' => 'projects_users_id'
]);
}
}
Model: ProjectsUsersPermissions - this is the relation to the join table
class ProjectsUsersPermissionsTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('projects_users_permissions');
$this->displayField('role');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('ProjectsUsers', [
'foreignKey' => 'projects_users_id'
]);
}
}
Then the controller find action
$this->Projects->find()
->where(
[
'Projects.id' => $projectId
]
)
->contain(
[
'Users', // through belongsToMany
'ProjectsUsers' => [ // through hasMany [joinTableModel]
'ProjectsUsersPermissions' // through hasMany
]
]
)
->first();
This may be overkill for this scenario, and it is not my exact implementation - so don't think I am just doing unnecessary joins/contains. In my real life scenario, this works perfectly.
Hope this helps someone!

How to list objects in a hasMany relation in CakePHP 3?

I'm struggling with getting the data of a hasMany relation in CakePHP 3. I'm working on a basic forum and my current problem refers to the relation between categories and topics. A category contains of several topics, while each topic belongs to one single category. For both the categories and topics I used the bake mechanism and added the relation to the tables. This is the initialize method for the CategoriesTable class:
public function initialize(array $config) {
parent::initialize($config);
$this->table('categories');
$this->displayField('name');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->hasMany('Topics', [
'foreignKey' => 'category'
]);
}
And here's the same for the TopicsTable:
public function initialize(array $config) {
parent::initialize($config);
$this->table('topics');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Categories', [
'foreignKey' => 'category'
]);
}
Now I want to list the topics of one category like this (Categories\view.cpt):
<h1><?= $category->name ?></h1>
<table>
<?php foreach ($topics as $topic): ?>
<tr>
<td>
<?= $topic->name ?>
</td>
</tr>
<?php endforeach; ?>
</table>
How do I get the list of all topics related to the currently selected category?
Categories controller:
$topics = $this->Category->Topic->find('list', [
'keyField' => 'id',
'valueField' => 'Topic.category'
])
->where(['category' => $category]);
http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#finding-key-value-pairs
Thanks to bill for the hint. Here's my view method in the categories controller:
public function view($id = null) {
$category = $this->Categories->get($id, [
'contain' => []
]);
$this->set('category', $category);
$this->set('_serialize', ['category']);
$topics = $this->Categories->Topics->find()->where(['category' => $id]);
$this->set('topics', $topics);
}

CakePHP 3 join table associations

Alright, I have some issues understanding how the associations are working, particularly belongsTo here is my setup:
Articles can have multiple Categories
Categories can belong to multiple Articles
so in my database i have 3 tables:
articles, categories and a join table articles_categories
Table/ArticlesTable.php:
public function initialize(array $config)
{
$this->addBehavior('Timestamp');
$this->table('articles');
$this->belongsTo('Users');
$this->belongsToMany('Categories', [
'through' => 'ArticlesCategories',
'alias' => 'Categories',
'foreignKey' => 'article_id',
'joinTable' => 'articles_categories',
'targetForeignKey' => 'category_id'
]);
}
Table/CategoriesTable.php:
public function initialize(array $config)
{
$this->table('categories');
$this->displayField('name');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsToMany('Articles', [
'through' => 'ArticlesCategories',
'alias' => 'Articles',
'foreignKey' => 'category_id',
'joinTable' => 'articles_categories',
'targetForeignKey' => 'article_id'
]);
}
Table/ArticlesCategoriesTable.php:
public function initialize(array $config)
{
$this->belongsTo('Articles');
$this->belongsTo('Categories');
}
Now inside in the view action CategoriesController.php i can overview a particular category and i need to retrieve some articles related to that category.
What is the right way to do such a thing? Here is what i have:
public function view($id = null)
{
$category = $this->Categories->find('all',['limit'=>1])->where(['Categories.id' => $id])->contain(['Articles']);
$this->set(['category'=> $category]);
}
It kinda does the job but I'd also need to be able to limit the number of related articles..
you can modify the query object used to load the associated models:
$category = $this->Categories->find('all',['limit'=>1])
->where(['Categories.id' => $id])
->contain(['Articles' => function($q) {
$q->limit(10);
return $q;
}
]);
edit: or you can do
$category = $this->Categories->get($id,
[
'contain' => [
'Articles' => function($q) {
$q->limit(10);
return $q;
}
]);
or maybe if you want the Articles without the Category data you can use matching
$articles = $this->Categories->Articles->find()
->matching('Categories', function ($q) use $id{
return $q->where(['id' => $id])
->limit(10);
I did not tested the last one but I think something like that should work
But as you can see the complexity is more o less the same

Categories