cakephp 3 contain same model twice with different conditions without association - cakephp

I have three tables ServerScans, QueuedJobs, ReportMalware
ReportMalware has a column type which contain values like mail, abc.
I am querying ServerScans as
$scan = $this->ServerScans->get($id, [
'contain' => [
'QueuedJobs',
'QueuedJobs.ReportMalware',
],
]);
and in view separating malware report in two groups using for loop as
<h2>Mail report</h2>
<?php foreach($scan->queued_jobs->report_malware as $m): ?>
<?php if ($m->type == 'mail'): ?>
<?= $m->comment ?>
<?php endif; ?>
<?php endforeach;?>
<h2>Abc report</h2>
<?php foreach($scan->queued_jobs->report_malware as $m): ?>
<?php if ($m->type == 'abc'): ?>
<?= $m->comment ?>
<?php endif; ?>
<?php endforeach;?>
Which will take more time for execution.
What I want is to keep it in contain like
$scan = $this->ServerScans->get($id, [
'contain' => [
'QueuedJobs',
'QueuedJobs.ReportMalware.mail',
'QueuedJobs.ReportMalware.abc',
],
]);
Is there a way to achieve this and contain same model twice based on some filter criteria?

Yes, you can do so. See the docs here.
The same table can be used multiple times to define different types of
associations. For example consider a case where you want to separate
approved comments and those that have not been moderated yet:
Here is the example taken from the official documentation:
class ArticlesTable extends Table
{
public function initialize(array $config)
{
$this->hasMany('Comments')
->setConditions(['approved' => true]);
$this->hasMany('UnapprovedComments', [
'className' => 'Comments'
])
->setConditions(['approved' => false])
->setProperty('unapproved_comments');
}
}

Related

set value in controller to associated model befor save in cakephp

I have 'seller_businessestable andseller_business_categories` table. I am using a single form to save values to sellers and seller_businesses.
The form is like
<?= $this->Form->create() ?>
<?= $this->Form->input('company_name') ?>
<?= $this->Form->input('logo', ['type' => 'file']) ?>
<?= $this->Form->input('seller_business_categories.category_id') ?>
<?= $this->Form->button('Submit', ['type' => 'submit']) ?>
<?= $this->Form->end() ?>
The seller_business_categories has a column seller_id and I have to save the logged in user id in it.
I know to save value to table seller_businesses in controller like
$seller_business = $this->SellerBusinesses->newEntity();
$seller_business->seller_id = $this->Auth->user('id');
$this->SellerBusinesses->patchEntity($seller_business, $this->request->data, [
'associated' => ['SellerBusinessCategories']
]);
But how to save default value to associated model SellerBusinessCategories within controller ?
You need make relationship
SellerBusinessCategorie.php MODEL
public function initialize(array $config)
{
parent::initialize($config);
$this->table('seller_business_categories');
$this->hasMany('seller_businesses', [
'foreignKey' => 'seller_id'
]);
}
SellerBusinesses.php MODEL
public function initialize(array $config)
{
parent::initialize($config);
$this->belongsTo('seller_business_categories', [
'foreignKey' => 'category_id',
'joinType' => 'INNER'
]);
}
Controller
$seller_business = $this->SellerBusinesses->newEntity();
$seller_business->seller_id = $this->Auth->user('id');
$this->SellerBusinesses->patchEntity($seller_business, $this->request->data]);
NOW TRY..it works

CakePHP Ajax : update list with change in related list

I am working on CakePHP 2.7.8. I want to update related list with change in list using Ajax.
I have a customers table and customer_addresses table in the database and customers and customerAddress models in the project.
There is another controller serviceRequests where I have to select customer and address of the selected customer from a drop down list generated by CakePHP from database.
What I have done-
I have added a function getCustomerAddress in the serviceRequests controller
public function getCustomerAddress(){
$customer_id = $this->request->data['Post']['customer_id'];
$customer_address = $this->CustomerAddress->find('list',array(
'condition' => array('CustomerAddress.customer_id' => $customer_id),
'recursive' => -1
));
$this->set('customerAddresses', $customer_address);
$this->layout = 'ajax';
}
to display the retrieved data, I have a view get_customer_address.ctp
<?php
foreach ($customerAddresses as $key => $value): ?>
<option value="<?php echo $key;?>"><?php echo $value; ?></option>
<?php endforeach; ?>
In the add.ctp view of serviceRequests controller for add function, I have added following script at the last.
<div class="serviceRequests form">
<?php echo $this->Form->create('ServiceRequest'); ?>
<fieldset>
<legend><?php echo __('Add Service Request'); ?></legend>
<?php
echo $this->Form->input('customer_id');
echo $this->Form->input('customer_address_id');
echo $this->Form->input('status');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>
<?php
$this->Js->get('#ServiceRequestCustomerId')->event('change',
$this->Js->request(array(
'controller' => 'serviceRequests',
'action' => 'getCustomerAddress'
), array(
'update' => '#ServiceRequestCustomerAddressId',
'async' => true,
'method' => 'post',
'dataExpression' => true,
'data' => $this->Js->serializeForm(array(
'isForm' => true,
'inline' => true
))
))
);
?>
and to render Js, I have added following code to to last of default.ctp
<!-- script for layout -->
<?php echo $scripts_for_layout; ?>
<!-- Js writeBuffer -->
<?php
if(class_exists('JsHelper') && method_exists($this->Js, 'writeBuffer')) echo $this->Js->writeBuffer ();
// writes cached scripts
?>
But on accessing localhost/serviceRequests/add the ajax call is not working and all customer's name and all customer's addresses are showing in the list.
This is an example of how to implement chained selects with cake http://sandbox.dereuromark.de/sandbox/ajax_examples/chained_dropdowns
- the related article for that example is here http://www.dereuromark.de/2014/01/09/ajax-and-cakephp/

How to add associated data while adding User simultaneously CakePHP 3.x?

I would like to be able to add a membership record at the same time I add a user. I can't seem to get it to work. I want to be able to select the membership level and have that data get sent to the controller where I can add the data, unless there is a way to just select the membership level and it will automatically create a membership record for the user that gets added.
The membership level contains the information for that level of membership and the membership record contains some information from the membership level and is associated to a user.
The add form I believe is where the problem lies, but just in case here are the important snippets of code. I tried to keep it as simple as possible.
Users Table Initialize Function:
public function initialize(array $config)
{
parent::initialize($config);
$this->table('users');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->hasOne('Memberships', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
}
Memberships Table Initialize Function:
public function initialize(array $config)
{
$this->table('memberships');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
$this->hasOne('MembershipLevels', [
'foreignKey' => 'membership_level_id',
'joinType' => 'INNER'
]);
}
Users Controller Add Method:
public function add()
{
$user = $this->Users->newEntity($this->request->data(), [
'associated' => [
'Memberships' => ['associated' => ['MembershipLevels']]
]
]);
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->data(), [
'associated' => [
'Memberships' => ['associated' => ['MembershipLevels']]
]
]);
if ($$this->Users->save($user)) {
$this->Flash->success(__('You have been added.'));
} else {
$this->Flash->error(__('You could not be added. Please, try again.'));
}
}
$membershipLevels = $this->Users->Memberships->MembershipLevels->find('list', ['limit' => 200]);
$this->set(compact('user', 'membershipLevels'));
$this->set('_serialize', ['user', 'membershipLevels']);
}
Add Users Form:
<div class="form">
<h1>Join Now</h1>
<?= $this->Form->create($user); ?>
<fieldset>
<legend><?= __('User Info') ?></legend>
<?= $this->Form->input('full_name', ['required' => false]); ?>
<?= $this->Form->input('username', ['required' => false]); ?>
<?= $this->Form->input('email', ['required' => false]); ?>
<?= $this->Form->input('password', ['required' => false]); ?>
<?= $this->Form->input('password_confirmation', ['type' => 'password', 'required' => false]); ?>
<?php
if ($current_user['role'] === 1 && isset($logged_in)) {
echo $this->Form->input('role', ['type' => 'select', 'options' => ['1' => 'Admin', '2' => 'Editor', '3' => 'Author', '4' => 'Reader'], 'default' => '4']);
}
?>
</fieldset>
<fieldset>
<legend><?= __('Membership Info') ?></legend>
<?= $this->Form->label('Membership Level'); ?>
<?= $this->Form->input('memberships.membership_levels._id', ['options' => $membershipLevels, 'required' => false]); ?>
</fieldset>
<?= $this->Form->button(__('Sign Up'));?>
<?= $this->Form->end();?>
</div>
I changed the code a bit thanks to the comments and answers. The membership levels now show up in the form and I pick a membership level when saving the user, but the membership doesn't get saved as well, just the user. Any further suggestions?
How about start reading the migration guide, or doing the blog tutorial for CakePHP3? Your trial and error approach is time consuming and frustrating. I can't recommend this enough: Always read documentation before shooting in the darkness. There has a lot changed in CakePHP3. This includes the way the dot notation is used. Reading saving associations might help as well.
You don't use any longer the model prefix on the first level.
Model.field
is now just
field
For nested associations it's now
associated_data.field
associated_data.second_level_data.field
Notice that this is inflected and singular or plural depending on the kind of association.
I have updated my code to get the closest I can to getting all the automagic to work.
Key points:
1.) In controller I got the membership levels variable to pass to the view by adding this line. (notice the calling of the users table then memberships and then membershiplevels).
$membershipLevels = $this->Users->Memberships->MembershipLevels->find('list', ['limit' => 200]);
2.) In the view I added:
<?= $this->Form->input('memberships.membership_levels._id', ['options' => $membershipLevels, 'required' => false]); ?>
This is not a complete answer however because I still have to grab the membership level in the controller with a query and then manually save the data from that level to the memberships table.
I can at least populate the membership level input in the form dynamically and submit it.
I had looked over the bookmarker tutorial that I had previously done since it uses associations, but with that tutorial they are able to add the bookmarks_tags record automatically when you add a bookmark and I am not sure if it is due to the functions in the table files or not.

cakephp szajbus uploadpack - image doesn't show because self::$__settings array is empty

I have 2 views, postview.ctp and usercomment.ctp, calling the same comment.ctp element. This element shows image using UploadPack helper. But image on usercomment.ctp doesn't show and has this error message
Notice (8): Undefined index: User [APP\Plugin\upload_pack\Model\Behavior\UploadBehavior.php, line 222]
line 222: $settings = self::$__settings[$modelName][$field];
The self::$__settings in usercomment.ctp is empty , but in postview.ctp it's not empty and the image showed up correctly.
comment.ctp:
<?php echo $this->Html->link($this->upload->image(
$comment['User'],
'User.avatar',
array('style' => 'thumb'),
array('class' => array('img-responsive', 'img-rounded'))
),
array('controller' => 'users',
'action' => 'view',
$comment['User']['id']),
array('escape' => false)
) ?>
And this is code to call comment.ctp on from the both view.
<?php if (!empty($comments)): ?>
<?php foreach ($comments as $comment): ?>
<?php echo $this->element('comment',array('comment' => $comment));?>
<?php endforeach; ?>
<?php endif; ?>
I've checked the $comment array and they're identical. How to fix it?
Load User model on usercomment action in Comment controller.
public function usercomments($id) {
$this->loadModel('User');
if($this->Auth->loggedIn()){
.....

cakephp: how to render related models in the view

My objective is to display records for a related child model (once removed) in the view. My problem is that I receive a 'Notice (8): Undefined index:' error message when I try to output the following query.
Tournaments have many tournamentDetails, and tournamentDetails have many updates. I'm trying to display all the updates for each tournamentDetail that is displayed on the tournaments view.
So my question is how to properly resolve the error message and display the updates for each tournamentDetail on the tournaments view page.
My find data in the 'tournaments' controller view action is:
$updates = $this->Tournament->TournamentDetail->Update->find('all', array( 'tournament_details.tournament_id'=> $this->data['Tournament']['id']));
In the view, I have this code.
<?php foreach ($tournament['Update'] as $update): ?>
<h3>Updates</h3>
<h1><?php echo $update ['title']; ?></h1>
<p><?php echo $update ['body']; ?></p>
<hr/>
<?php endforeach; ?>
This is the same 'foreach' code the I use for the other related child records without problem. I did use the debug() function to investigate but didn't see what I was missing.
The output of the $updates array from the debug function looks like this:
Array
(
[0] => Array
(
[Update] => Array
(
[id] => 1
[title] => first round matches start today
[date] => 2010-03-19
[body] => this tournament's first round matches start today.
[tournament_detail_id] => 4
[homeStatus] => no
)
Is there a special way to display records this deep?
As always, thanks in advance.
Paul
Update: Feb 23/11
After some testing the problem I seem to have is finding and passing the correct value to the $updates variable;
To summarize, I want the $updates variable to hold the current 'tournament_details_id'. This will then display the related update records in the 'tournaments' view.
I'm still a beginner and most likely overlooked the obvious.
Here is the model info:
class Tournament extends AppModel {
var $name = 'Tournament';
var $hasMany = array(
'TournamentDetail' => array(
'className' => 'TournamentDetail',
'foreignKey' => 'tournament_id',)
class TournamentDetail extends AppModel {
var $name = 'TournamentDetail';
var $belongsTo = array(
'Tournament' => array(
'className' => 'Tournament',
'foreignKey' => 'tournament_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
class Update extends AppModel {
var $name = 'Update';
var $belongsTo = array(
'TournamentDetails' => array(
'className' => 'TournamentDetails',
'foreignKey' => 'tournament_detail_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
Controller data:
class TournamentsController extends AppController
function view($slug = null) {
if (!$slug) {
$this->Session->setFlash(__('Invalid Tournament.', true));
$this->redirect(array('action'=>'index'));
}
$this->Tournament->recursive = 1;
$tournament = $this->Tournament->findBySlug($slug);
$updates = $this->Tournament->TournamentDetail->Update->find('all', array('conditions' => array( 'tournament_details_id' => $this->data['TournamentDetails']['id'] )));
$this->set(compact('tournament','updates', $updates ));
Tournament view. This is display the 'tournament details' and (ideally) related tournament detail 'updates'
<h2><?php echo $tournament['Tournament']['name']; ?></h2>
<?php foreach ($tournament['TournamentDetail'] as $tournamentDetail): ?>
<h1><?php echo $tournamentDetail ['title']; ?></h1>
<p><?php echo $tournamentDetail ['body']; ?></p>
<?php endforeach; ?>
<?php foreach ($updates['Update'] as $update): ?>
<h4>Update: <?php echo $update ['date']; ?></h4>
<p> <?php echo $update ['Update'] ['title']; ?></p>
<p><?php echo $update ['Update'] ['body']; ?></p>
<?php endforeach; ?>
I've tested this by adding in the tournament details 'id' as an integer and it pulls up the correct 'update' record. However I seem to have problems configuring the find operation to do the same.
As always I appreciate the help.
Thanks
Paul
Based on your debug output, it seems that your $tournaments variable consists of an array (instead of the associative array) so you might want to use the foreach to access each of those elements:
foreach ($tournaments as $update):
?>
<h3>Updates</h3>
<h1><?php echo $update ['Update']['title']; ?></h1>
<p><?php echo $update ['Update']['body']; ?></p>
<hr/>
<?php endforeach; ?>
It appears that you be using the wrong variable, you talk about the $updates variable but you're using the $tournament variable in your view.
<?php foreach ($updates['Update'] as $update): ?>
<h3>Updates</h3>
<h1><?php echo $update ['title']; ?></h1>
<p><?php echo $update ['body']; ?></p>
<hr/>
<?php endforeach; ?>
Additionally you haven't posted the whole controller method, which includes that find but you might not have sent the data to the view yet either
$this->set(compact('updates'));

Resources