CakePHP 3 - relationship between models - relational-database

I related two models following the official documentation of CakePHP 3 and can not return the values of one of them in view (Template).
The Code:
Work - Entity
namespace App\Model\Entity;
use Cake\ORM\Entity;
class Work extends Entity
{
protected $_accessible = [
'project' => true,
'client' => true,
'filter' => true,
'tech_1' => true,
'tech_2' => true,
'tech_3' => true,
'tech_4' => true,
'job' => true,
'status' => true,
'link' => true,
];
}
WorksImage - Entity
namespace App\Model\Entity;
use Cake\ORM\Entity;
class WorksImage extends Entity
{
protected $_accessible = [
'photo' => true,
'photo_dir' => true,
'work_id' => true,
'work' => true,
];
}
PagesController - Controller:
namespace App\Controller;
use Cake\Core\Configure;
use Cake\Network\Exception\NotFoundException;
use Cake\View\Exception\MissingTemplateException;
class PagesController extends AppController
{
public function portfolio()
{
$this->loadModel('Works');
$this->loadModel('WorksImages');
$works = $this->Works->find('all',['contain' => ['WorksImages'],'limit' => 10, 'order' => ['Works.created' => 'DESC']]);
$this->set(compact('works'));
}
}
WorksTable - Table:
namespace App\Model\Table;
use App\Model\Entity\Work;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class WorksTable extends Table
{
public function initialize(array $config)
{
$this->table('works');
$this->displayField('project');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->hasOne('WorksImages', [
'foreignKey' => 'work_id'
]);
}
WorksImagesTable - Table
namespace App\Model\Table;
use App\Model\Entity\WorksImage;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class WorksImagesTable extends Table
{
public function initialize(array $config)
{
$this->table('works_images');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Works', [
'foreignKey' => 'work_id',
'joinType' => 'INNER'
]);
}
Portfolio - View (Template)
<div class="container">
<div class="span12">
<h1>Portfólio</h1>
<div>
<?php foreach ($works as $work): ?>
<div>
<p><?= 'Conteúdo da tabela Works = ' . $work->project ?></p>
<p><?= 'Conteúdo da tabela WorksImages = ' . $work->work_id ?></p>
</div>
<?php endforeach ?>
</div>
</div>
</div>
I can not return any value from the WorksImagesTable model. During Debugging, I realize that the tables are related, in addition, cake returns no error in the view.
I can not understand what is wrong.
I thank in advance any help.
Thanks.

In the foreach loop (debug($work->works_image)) returned something like this:
object(App\Model\Entity\WorksImage) {
'new' => false,
'accessible' => [
'photo' => true,
'photo_dir' => true,
'work_id' => true,
'work' => true
],
'properties' => [
'id' => (int) 1,
'photo' => 'arteviva.jpg',
'photo_dir' => 'a4cd522c-b7b9-437a-99fc-0eb15827944f',
'work_id' => (int) 1,
'created' => object(Cake\I18n\Time) {
'time' => '2015-05-08T20:25:07+0000',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'modified' => null
],
'dirty' => [],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'WorksImages'
}

Related

How to set selected option in symfony?

Here is my form:
{
$builder
->add('price', ChoiceType::class, [
'label' => false,
'required' => false,
'choices' => [
'0 - 1000 €' => 1,
'1000 - 2000 €' => 2,
'2000 - ∞' => 3,
],
'attr' => [
'class' => 'main-dropdown',
],
])
;
}
So how to pass selected value on twig? Can someone give an advice?
I think you build the form in a separate .with this method you can use of form anywhere you need.
for example, it is your form
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;///To use this field, you must add ChoiceType in form.
class yournameFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('price', ChoiceType::class, [
'label' => false,
'required' => false,
'choices' => [
'0 - 1000 €' => 1,
'1000 - 2000 €' => 2,
'2000 - ∞' => 3,
],
'attr' => [
'class' => 'main-dropdown',
],
])
;
}
}
You can use this form in a controller like an example below
use AppBundle\Form\yournameFormType;
public function newAction()
{
$YourEntityName = ...;
$form = $this->createForm(yournameFormType ::class, $YourEntityName );
// ...
return $this->render('#App/YourNameTwig.html.twig', array(
'form' => $form->createView()
));
}
and at the end Use the form in twig file
{{ form_start(form) }}
.
.
{{ form_widget(form.price) }}
.
.
.
{{ form_end(form) }}
Read more about this

How use a static properties on Gridview -> value

I have the :
class MyClass extends \yii\db\ActiveRecord
public static $myrequested = ['Value1', 'Value2', 'Value3'];
How access value propertie os the myrequested on the gridview ?
[
'attribute' => 'requested_mounth',
'enableSorting' => true,
'value' => ?????
'filter' => Resourcerequest::$myrequested ,
],
if left blank it only returns the position of the array, and I need the value.
(the filter option work fine).
EDIT 1
Example of the array:
myrequested [
0 => 'value1',
1 => 'value2',
2 => 'value3',
]
Add method getRequestedMounth() at class Resourcerequest
public function getRequestedMounthValue()
{
if ($this->requested_mounth === null) {
return null;
}
return self::$myrequested[$this->requested_mounth];
}
Then
[
'attribute' => 'requested_mounth',
'enableSorting' => true,
'value' => function($data) {
return $data->getRequestedMounthValue(); // OR use magic property $data->requestedMounthValue;
},
'filter' => Resourcerequest::$myrequested ,
],
In one of my projects I have used the code below:
['attribute' => 'final_cost',
'format' => 'raw',
'value' => function ($data) use ($staticArray)
{
return $staticArray[$data->id];
},
],

yii2 change database for admin and site panel

I have the following config file
common/main-local.php
return [
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=aishwariya_basic2',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
// 'db' => $db,
'db2' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=aishwariya_basic',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'viewPath' => '#common/mail',
],
// autoloading model and component classes
'import'=> [
'class' => 'yii2-widget-linkpager',
'application.extensions.MyLinkPager.*',
],
],
];
Admincontroller
namespace frontend\controllers;
use Yii;
use frontend\models\Site_login;
use frontend\models\EntryForm_model;
use frontend\models\Asal_page_model;
use frontend\models\Interest_page_model;
use frontend\models\Return_page_model;
use frontend\models\Daily_report_model;
use frontend\models\Changepassword;
use yii\base\InvalidParamException;
use yii\web\BadRequestHttpException;
use yii\web\Controller;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use yii\helpers\ArrayHelper;
use yii\db\Query;
class AdminController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['index', 'signup'],
'rules' => [
[
'actions' => ['index'],
'allow' => true,
'roles' => ['?'],
],
[
'actions' => ['settings','changepassword'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
/**
* #inheritdoc
*/
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
],
];
}
#####Action index code starts here
public function actionIndex()
{
$this->layout = 'admin';
$my2DbConn = Yii::$app->db;
$model = new Site_login();
if ($model->load(Yii::$app->request->post()) )
{
if ($model->validate()) {
$url = Yii::$app->getUrlManager()->getBaseUrl()."/admin/search";
return $this->redirect($url);
}
}
return $this->render('index', ['model' => $model]);
}
Site controller
public function actionInitial()
{
$this->layout = 'site';
$my2DbConn = Yii::$app->db2;
$model=new Initial_model();
if ($model->load(Yii::$app->request->post()))
{
}
return $this->render('initial',['model'=>$model]);
}
I would like to change the database belongs to controller. Please give me some help. I have used two db but it tooks first db file.
You can configure more then a db in config
return [
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=testdb',
'username' => 'demo',
'password' => 'demo',
],
'db2' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=testdb2',
'username' => 'demo2',
'password' => 'demo2',
],
],
];
and obtain your db (this is if you want use direct command in controller and not for activeRecord)
class yourController extends \yii\web\Controller
{
public function actionYourAction()
{
...
$my2DbConn = Yii::$app->db2;
....
}
Or you can manage programmatically with the proper setting
If for your model (like you have in your code ) you want to use a different database connection other than the db component, you should override the getDb() method in your related ActiveRecord MODEL (see the doc .. link at the bottom):
class YourModel extends ActiveRecord // eg: Initial_model
{
// ...
public static function getDb()
{
// use the "db2" application component
return \Yii::$app->db2;
}
}
and not assign $my2DbConn = Yii::$app->db; in controller this is for createCommand (direct sql commend) and not for activeRecord like you need ..
see this guide http://www.yiiframework.com/doc-2.0/guide-db-active-record.html or this reference for related param http://www.yiiframework.com/doc-2.0/yii-db-connection.html

CakePHP 3.x dynamic finder method

I have this problem with a CakePHP 3 application
I am trying to get a category by it's slug and all related articles belonging to that category.
I am using dynamic finder method findBySlug in the Controller but it throws an error in the view.
Here is my code:
public function view($slug = null)
{
if (!$slug) {
throw new NotFoundException(__('Invalid category slug'));
}
$category = $this->Categories->findBySlug($slug, [
'contain' => [
'Articles'
]
]);
$this->set(compact('category'));
}
and the view:
<div class="categories view">
<h2><?= h($category->name); ?></h2>
<?php foreach ($category->articles as $article): ?>
<?php echo $article->title; ?>
<?php endforeach; ?>
Can anyone please provide or point me to a solution ?
Thank you in advance
And this is the debug I am getting in the controller:
object(App\Model\Entity\Category) {
'new' => false,
'accessible' => [
'name' => true,
'slug' => true,
'articles' => true
],
'properties' => [
'id' => (int) 2,
'name' => 'International',
'slug' => 'international.html'
],
'dirty' => [],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'Categories'
}
and here are my models:
class CategoriesTable extends Table
{
public function initialize(array $config)
{
$this->addBehavior('Timestamp');
$this->displayField('name');
$this->hasMany('Articles', [
'className' => 'Articles',
'foreignKey' => 'category_id',
'conditions' => [
'published' => 1
],
'dependent' => true
]);
}
}
class ArticlesTable extends Table
{
public function initialize(array $config)
{
$this->addBehavior('Timestamp');
$this->belongsTo('Users');
$this->belongsTo('Categories', [
'foreignKey' => 'category_id'
]);
}
}
the find() method will always return a Query object. You need to fetch at least one result before trying to get properties from it:
$thisIsAQuery = $this->Categories->findBySlug($slug)->contain(['Articles'])
// I can now fetch the category
$category = $thisIsAQuery->first();
// And now I can get the category name
echo $category->name

CakePHP 3 hasMany will not pass parent ID to associated children

/* ShootsTable.php Meta Table */
public function initialize(array $config)
{
$this->table('shoots');
$this->displayField('title');
$this->primaryKey('id');
$this->hasMany('ShootMeta');
}
/* ShootMetaTable.php Meta Table */
public function initialize(array $config)
{
$this->table('shoot_meta');
$this->displayField('id');
$this->primaryKey('id');
$this->belongsTo('Shoots');
}
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['shoots_id'], 'Shoots'));
return $rules;
}
/* Shoots.php Controller */
public function add()
{
$shoot = $this->Shoots->newEntity(null);
if ($this->request->is('post')) {
$this->Shoots->patchEntity($shoot, $this->request->data,[
'associated' => ['ShootMeta']
]);
$shoot->set('created_by', 1);
debug($shoot);
if ($this->Shoots->save($shoot,['associated' => ['ShootMeta']])) {
$this->Flash->success('The shoot has been saved.');
// return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The shoot could not be saved. Please, try again.');
}
}
$this->set(compact('shoot'));
$this->set('_serialize', ['shoot']);
}
/* Add.ctp Template */
<div class="shoots form large-10 medium-9 columns">
<?= $this->Form->create($shoot); ?>
<fieldset>
<legend><?= __('Add Shoot') ?></legend>
<?php
echo $this->Form->input('title');
echo $this->Form->input('content');
echo $this->Form->input('datetime', ['label' => 'Date/Time Of Shoot']);
echo $this->Form->input('shoot_meta.0.meta_key', ['type' => 'hidden', 'value' => 'photographer_spaces']);
echo $this->Form->input('shoot_meta.0.meta_value',['label' => 'Photographer Spaces', 'type' => 'number']);
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
/* debug($shoots) output */
object(App\Model\Entity\Shoot) {
'new' => true,
'accessible' => [
'created_by' => true,
'title' => true,
'content' => true,
'datetime' => true,
'shoot_meta' => true
],
'properties' => [
'title' => '123',
'content' => '123',
'datetime' => object(Cake\I18n\Time) {
'time' => '2015-03-19T07:04:00+0000',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'shoot_meta' => [
(int) 0 => object(App\Model\Entity\ShootMetum) {
'new' => true,
'accessible' => [
'shoots_id' => true,
'meta_key' => true,
'meta_value' => true,
'shoot' => true
],
'properties' => [
'meta_key' => 'photographer_spaces',
'meta_value' => '123'
],
'dirty' => [
'meta_key' => true,
'meta_value' => true
],
'original' => [],
'virtual' => [],
'errors' => [
'shoots_id' => [
'_required' => 'This field is required'
]
],
'repository' => 'ShootMeta'
}
],
'created_by' => (int) 1
],
'dirty' => [
'title' => true,
'content' => true,
'datetime' => true,
'shoot_meta' => true,
'created_by' => true
],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'Shoots'
}
As you can see, the field shoots_id is required, which I would have thought would be automatically passed down (although at this point it hasn't executed any MySQL).
I feel I may have gone about this the wrong way but have spent 2 full days trying to get it right. One of those days was me trying to work out why after baking it had named a lot of the references to ShootMeta to ShootMetum, I thought it had actually corrupted it.
One of the biggest issues I have is knowing where to use shoot_meta, ShootMeta, shootmeta, shootmetum, ShootMetum etc. It feels like a bit of a minefield!
/Update
A dump of the save object below. It is clearly assigning it, it just seems to not be executing it in the SQL?
'shoot_meta' => [
(int) 0 => object(App\Model\Entity\ShootMetum) {
'new' => false,
'accessible' => [
'shoots_id' => true,
'meta_key' => true,
'meta_value' => true
],
'properties' => [
'meta_key' => 'photographer_spaces',
'meta_value' => '123',
'shoot_id' => '2',
'id' => '3'
],
'dirty' => [],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'ShootMeta'
},
Found it.
It is referring to shoot_id when i debug the save
'shoot_meta' => [
(int) 0 => object(App\Model\Entity\ShootMetum) {
'new' => false,
'accessible' => [
'shoots_id' => true,
'meta_key' => true,
'meta_value' => true
],
'properties' => [
'meta_key' => 'photographer_spaces',
'meta_value' => '123',
'shoot_id' => '2',
'id' => '3'
],
'dirty' => [],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'ShootMeta'
},
for some reason it was using the singular name for the association. Changed in the Shoots.php model.
From
$this->hasMany('ShootMeta');
To
$this->hasMany('ShootMeta',[
'foreignKey' => 'shoots_id'
]);
Remove the validation rule for shoots_id. Validation is for data that is posted from the form, and in this case the foreignKey cannot be posted from the Form. You already have rules in your buildRules() method for making sure that value is passed before saving, so removing the validation is 100% safe.
i have same problem like this to, for now my solution is sending associated data to other function/methode and save it.
eg
**
public function add() {
$kantor = $this->Kantor->newEntity($this->request->data);
if ($this->request->is('post')) {
$kantor = $this->Kantor->patchEntity($kantor, $this->request->data);
$rgndata = $this->request->data['Telpkantor'];
$this->request->session()->write('rgndata', $rgndata);
if ($this->Kantor->save($kantor)) {
$result = $this->Kantor->save($kantor);
$this->addTelpKantor($rgndata, $result->id);
$this->Flash->success('The kantor has been saved.');
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The kantor could not be saved. Please, try again.');
}
}
$reffKota = $this->Kantor->ReffKota->find('list', ['limit' => 200]);
$statusKantor = $this->Kantor->StatusKantor->find('list', ['limit' => 200]);
$pimpinan = $this->Kantor->Pimpinan->find('list', ['limit' => 200]);
$jenisTelp = $this->Kantor->Telpkantor->Jenistelp->find('list', ['limit' => 200]);
$this->set(compact('kantor', 'reffKota', 'statusKantor', 'pimpinan', 'jenisTelp'));
$this->set('_serialize', ['kantor']);
}
public function addTelpKantor($rgndata = null, $kantor_id=null) {
if (!empty($rgndata[0]['noTelp'])) {
$this->loadModel('Telpkantor');
foreach ($rgndata as $rgndata) {
$rgndata['kantor_id'] =$kantor_id;
$rgndatasave = $this->Telpkantor->newEntity($rgndata);
$this->Telpkantor->save($rgndatasave);
}
}
}
**