Problem with Associations - Linking Tables Together

Hi!, I want to do this: http://book.cakephp.org/3.0/en/orm/associations.html
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.
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;

/**
 * Users 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('id', 'valid', ['rule' => 'numeric'])
            ->allowEmpty('id', 'create');

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

        /*$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;
    }
}

And 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('complejo', $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.'));
        }
    }
    $users = $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.'));
        }
    }
    $users = $this->Complejos->Users->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']);
}
}

Finally, index.ctp from Complejo Template:

<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><?= $this->Paginator->sort('descripcion', 'Descripción') ?></th>
            <th><?= $this->Paginator->sort('nombreUsuario', 'Nombre Usuario') ?></th>
            <th><?= $this->Paginator->sort('contrasenia', 'Contraseña') ?></th>
            <th><?= $this->Paginator->sort('direccion', 'Direccion') ?></th>
            <th><?= $this->Paginator->sort('latitud', 'Latitud') ?></th>
            <th><?= $this->Paginator->sort('longitud', 'Longitud') ?></th>
            <th><?= $this->Paginator->sort('telefono', 'Telefono 2') ?></th>
            <th><?= $this->Paginator->sort('telefono2', 'Telefono 1') ?></th>
            <th><?= $this->Paginator->sort('vestuario', 'Vestuario') ?></th>
            <th><?= $this->Paginator->sort('asador', 'Asador') ?></th>
            <th><?= $this->Paginator->sort('requiereSenia', '¿Requiere Seña?') ?></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('ciudad') ? $this->Html->link($complejo->ciudad->nombreCiudad, ['controller' => 'Ciudades', 'action' => 'view', $complejo->ciudad->idCiudad]) : '' ?></td>
            <td><?= h($complejo->descripcion) ?></td>
            <td><?= h($complejo->nombreUsuario) ?></td>
            <td><?= h($complejo->contrasenia) ?></td>
            <td><?= h($complejo->direccion) ?></td>
            <td><?= h($complejo->latitud) ?></td>
            <td><?= h($complejo->longitud) ?></td>
            <td><?= h($complejo->telefono) ?></td>
            <td><?= h($complejo->telefono2) ?></td>
            <td><?= h($complejo->vestuario) ?></td>
            <td><?= h($complejo->asador) ?></td>
            <td><?= h($complejo->requiereSenia) ?></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>

Index of Ciudad and Complejos is working right. The problem is in the column “Ciudad” from Complejo column is empty and I want to show the ciudad name

Thanks!

check your variables in your view file

have you solved your problem? I am stuck with similar problem