Federick Jons Federick Jons - 6 months ago 11
PHP Question

Cakephp empty Associations on Linking Tables Together

I want to do this: http://book.cakephp.org/3.0/en/orm/associations.html1
but it's not working
the cell in my complejo table is empty when I want to show the name of the another model (ciudad name). I want to show the name, not the Id of Ciudad.
Here you can see the empty column:
Click Me

So.. This is my code:

ComplejosTable.php

<?php
namespace App\Model\Table;

use App\Model\Entity\Complejo;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;

/**
* Complejo Model
*
* @property \Cake\ORM\Association\BelongsTo $Ciudades
*/
class ComplejosTable extends Table
{

/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);

$this->table('complejo');
$this->displayField('idComplejo');
$this->displayField('nombre');
$this->displayField('descripcion');
$this->displayField('nombreUsuario');
$this->displayField('contrasenia');
$this->displayField('direccion');
$this->displayField('latitud');
$this->displayField('longitud');
$this->displayField('telefono');
$this->displayField('telefono2');
$this->displayField('vestuario');
$this->displayField('asador');
$this->displayField('estacionamiento');
$this->displayField('requiereSenia');


$this->belongsTo('Ciudades', [
'foreignKey' => 'ciudadFK',
'joinType' => 'INNER'
]);
}

/**
* Default validation rules.
*
* @param \Cake\Validation\Validator $validator Validator instance.
* @return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
$validator
->add('id', 'valid', ['rule' => 'numeric'])
->allowEmpty('id', 'create');

$validator
->requirePresence('nombre', 'create')
->notEmpty('nombre');

$validator
->requirePresence('nombreUsuario', 'create')
->notEmpty('nombreUsuario');

$validator
->requirePresence('contrasenia', 'create')
->notEmpty('contrasenia');

$validator
->requirePresence('direccion', 'create')
->notEmpty('direccion');

$validator
->requirePresence('latitud', 'create')
->notEmpty('latitud');

$validator
->requirePresence('longitud', 'create')
->notEmpty('longitud');

$validator
->requirePresence('vestuario', 'create')
->notEmpty('vestuario');

$validator
->requirePresence('asador', 'create')
->notEmpty('asador');

$validator
->requirePresence('estacionamiento', 'create')
->notEmpty('estacionamiento');

$validator
->requirePresence('requiereSenia', 'create')
->notEmpty('requiereSenia');

return $validator;
}

/**
* Returns a rules checker object that will be used for validating
* application integrity.
*
* @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
* @return \Cake\ORM\RulesChecker
*/
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['ciudadFK'], 'Ciudades'));
return $rules;
}
}


CiudadesTable.php

<?php
namespace App\Model\Table;

use App\Model\Entity\Ciudad;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* Ciudades Model
*
* @property \Cake\ORM\Association\HasMany $Complejos
*/
class CiudadesTable extends Table
{

/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('ciudad');
$this->displayField('nombreCiudad');
$this->primaryKey('idCiudad');
//$this->addBehavior('Timestamp');

$this->hasMany('Complejos', [
'foreignKey' => 'ciudadFK'
]);
}

/**
* Default validation rules.
*
* @param \Cake\Validation\Validator $validator Validator instance.
* @return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
$validator
->add('idCiudad', 'valid', ['rule' => 'numeric'])
->allowEmpty('idCiudad', 'create');

$validator
->requirePresence('nombreCiudad', 'create')
->notEmpty('nombreCiudad');

/*$validator
->add('email', 'valid', ['rule' => 'email'])
->requirePresence('email', 'create')
->notEmpty('email');

$validator
->requirePresence('password', 'create')
->notEmpty('password');*/

return $validator;
}

/**
* Returns a rules checker object that will be used for validating
* application integrity.
*
* @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
* @return \Cake\ORM\RulesChecker
*/
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->isUnique(['nombreCiudad']));
return $rules;
}
}


Index.ctp of Complejos

<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('Nuevo Complejo'), ['action' => 'add']) ?> </li>
<li><?= $this->Html->link(__('Listar Complejos'), ['controller' => 'Users', 'action' => 'index']) ?></li>
</ul>
</nav>
<div class="posts index large-9 medium-8 columns content">
<h3><?= __('Complejos') ?></h3>
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th><?= $this->Paginator->sort('idComplejo', 'Nº Complejo') ?></th>
<th><?= $this->Paginator->sort('nombre', 'Nombre Complejo') ?></th>
<th><?= $this->Paginator->sort('ciudadFK', 'Ciudad') ?></th>
<th class="actions"><?= __('Acciones') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($complejos as $complejo): ?>
<tr>
<td><?= $this->Number->format($complejo->idComplejo) ?></td>
<td><?= h($complejo->nombre) ?></td>
<td><?= $complejo->has('ciudades') ? $this->Html->link($complejo->ciudad->nombreCiudad, ['controller' => 'Ciudades', 'action' => 'view', $complejo->ciudad->idCiudad]) : '' ?></td>
<td class="actions">
<?= $this->Html->link(__('Ver'), ['action' => 'view', $complejo->id]) ?>
<?= $this->Html->link(__('Editar'), ['action' => 'edit', $complejo->id]) ?>
<?= $this->Form->postLink(__('Eliminar'), ['action' => 'delete', $complejo->id], ['confirm' => __('Desea eliminar el complejo # {0}?', $complejo->nombre)]) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="paginator">
<ul class="pagination">
<?= $this->Paginator->prev('< ' . __('atrás')) ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next(__('siguiente') . ' >') ?>
</ul>
<p><?= $this->Paginator->counter() ?></p>
</div>
</div>


Finally, ComplejosController.php

<?php
namespace App\Controller;

use App\Controller\AppController;

/**
* Complejos Controller
*
* @property \App\Model\Table\ComplejosTable $Complejos
*/
class ComplejosController extends AppController
{

/**
* Index method
*
* @return void
*/
public function index()
{


$this->paginate = [
'contain' => ['Ciudades']
];
$this->set('complejos', $this->paginate($this->Complejos));
$this->set('_serialize', ['complejos']);
}


/**
* View method
*
* @param string|null $id Complejo id.
* @return void
* @throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function view($id = null)
{
$complejo = $this->Complejos->get($id, [
'contain' => ['Ciudades']
]);
$this->set('complejo', $complejo);
$this->set('_serialize', ['complejo']);
}

/**
* Add method
*
* @return void Redirects on successful add, renders view otherwise.
*/
public function add()
{
$complejo = $this->Complejos->newEntity();
if ($this->request->is('complejo')) {
$complejo = $this->Complejos->patchEntity($complejo, $this->request->data);
if ($this->Complejos->save($complejo)) {
$this->Flash->success(__('El complejo se ha guardado con éxito.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('El complejo no se ha guardado. Por favor intente de nuevo.'));
}
}
$ciudades = $this->Complejos->Ciudades->find('list', ['limit' => 200]);
$this->set(compact('complejo', 'ciudades'));
$this->set('_serialize', ['complejo']);
}

/**
* Edit method
*
* @param string|null $id Post id.
* @return void Redirects on successful edit, renders view otherwise.
* @throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function edit($id = null)
{
$complejo = $this->Complejos->get($id, [
'contain' => []
]);
if ($this->request->is(['patch', 'complejo', 'put'])) {
$complejo = $this->Complejos->patchEntity($complejo, $this->request->data);
if ($this->Complejos->save($complejo)) {
$this->Flash->success(__('El complejo se ha guardado con éxito.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('El complejo no se ha guardado. Por favor intente de nuevo.'));
}
}
$ciudades = $this->Complejos->Ciudades->find('list', ['limit' => 200]);
$this->set(compact('complejo', 'ciudades'));
$this->set('_serialize', ['complejo']);
}

/**
* Delete method
*
* @param string|null $id Post id.
* @return \Cake\Network\Response|null Redirects to index.
* @throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function delete($id = null)
{
$this->request->allowMethod(['complejo', 'delete']);
$complejo = $this->Complejos->get($id);
if ($this->Complejos->delete($complejo)) {
$this->Flash->success(__('El complejo se ha eliminado.'));
} else {
$this->Flash->error(__('El complejo no se ha podido eliminar. Por favor intente de nuevo.'));
}
return $this->redirect(['action' => 'index']);
}
}


Thanks for helping me!

Answer

I put an answer in your duplicate question

Linking tables together between two models in Cakephp

Change Ciudad for Ciudade

<td><?= $complejo->has('ciudade') ? $this->Html->link($complejo->ciudade->nombreCiudad, ['controller' => 'Ciudades', 'action' => 'view', $complejo->ciudade->id]) : '' ?></td>

To prevent this errors I suggest you use english language, in your example, the model shoud named Cities and then you can do $complejo->has('city')