Symfony 5.2 add to session array - arrays

I want to add product to my session array but always it overwriting existing product and is only one.
/**
* #Route("/{id}", name="add", methods={"GET"})
*/
public function add(Product $product, Request $request): Response
{
$session= $request->getSession();
$session->set('products', array(
'list' => $product,
));
$this->addFlash('success', 'add');
return $this->render('index.html.twig', [
'product' => $product
]);
}
any suggestion?

You overwrite the session variable each time instead of adding a new product. Try to get the product, add new product, then set the session:
public function add(Product $product, Request $request): Response
{
$session= $request->getSession();
$products = $session->get('products', []);
$session->set('products', array(
'list' => array_merge($products['list'] ?? [], [$product])
));
$this->addFlash('success', 'add');
return $this->render('index.html.twig', [
'product' => $product
]);
}
If you want to have distinct products you may use product['id'] as the key
public function add(Product $product, Request $request): Response
{
$session= $request->getSession();
$products = $session->get('products', []);
$products[$product['id']] = $product;
$session->set('products', products);
$this->addFlash('success', 'add');
return $this->render('index.html.twig', [
'product' => $product
]);
}

Related

Update field in a Column on Laravel

I'm trying to update the status on my tickets table to the value : 2.
Once I can create the comment... (is working.. :) ), I wanted to change the status to 2.
This is my ticket model and the following function:
public function addComment($id,$body,$solved)
{
$this->find($id)->status = 2;
$this->save();
$this->comments()->create([
'ticket_id' => $id,
'body' => $body,
'user_id' => auth()->id()
]);
}
You need to get your object first then you can Update it:
public function addComment($id,$body,$solved)
{
$ticket = $this->find($id);
$ticket->status = 2;
$ticket->save();
$ticket->comments()->create([
'ticket_id' => $id,
'body' => $body,
'user_id' => auth()->id()
]);
}
Try changing your code like this. Maybe this will fix the problem you're having:
public function addComment($id,$body,$solved)
{
$ticket = Ticket::find($id);
$ticket->status = 2;
$ticket->save();
$ticket->comments()->create([
'ticket_id' => $id,
'body' => $body,
'user_id' => auth()->id()
]);
}

Count in contain Cakephp 3

I have a table Post and this has a has-many association with a table Stars.
I can get all the associated data using:
$this->Posts->find()->contain(['Stars']);
That works well.
But I want to count the Stars. I have tried this but its not working:
$this->Posts->find->contain([
'Stars' => function($q) {
return $q->select(['total' => $q->func()->count('Stars.post_id')]);
}
]);
//I've also tried this
...
...$q->select(['total' => "COUNT(Stars.post_id)"]);
...
//Also fail
This does not return the number of associated Stars.
Is there something wrong or should do it some other way?
Thanks
you have to select also the foreign key otherwise cake is not able to join the tables. And you have also to group the result
'Stars' => function($q) {
$q->select([
'Stars.post_id',
'total' => $q->func()->count('Stars.post_id')
])
->group(['Stars.post_id']);
return $q;
}
As here we have used total as virtual field, can be create more like this in same model as:
public function index()
{
$checklist = TableRegistry::get('Checklists');
$query = $checklist->find()
->where('Checklists.is_deleted = 0')
->contain([
'ChecklistTitles' => function($q) {
return $q -> select([
'ChecklistTitles.title',
'ChecklistTitles.checklist_id'
]);
},
'ChecklistTypes' => function($w){
return $w->select(['ChecklistTypes.type']);
},
'AssignedChecklists' => function($e){
$e->select([
'AssignedChecklists.checklist_id',
'completed' => $e->func()
->count('AssignedChecklists.checklist_id'),
])
->group(['AssignedChecklists.checklist_id'])
->where(['AssignedChecklists.is_deleted = 0 AND AssignedChecklists.checklist_status = 2']);
return $e;
}
]);
// ->toArray();
// pr($query);die;
$this->paginate = [
'limit' => 20,
'sortWhitelist' => [
'id', 'checklist_title', 'checklist_type'
]
];
$this->set('query', $this->paginate($query));
$this->set(compact('checklists','query'));
$this->set('_serialize', ['checklists','query']);
}
As here I have calculated completed, I want to calculate cancelled with different where condition, what will be the syntax for it in cakephp3?
Try this:
$total = $this->Posts->find()->contain(['Stars'])->count();
As refereed in the cookbook.

Reverse product list in Laravel

How can I reverse the product list in Laravel?
Below is the code:
public function index() {
$products = Product::with('owner', 'memberInfo')->paginate($this->perPage);
return View::make('layouts.sales', array('products' => $products, 'status' => 'all'));
}
You can use Eloquent's reverse() function for collections.
public function index() {
$products = Product::with('owner', 'memberInfo');
$products = $products->reverse()->paginate($this->perPage);
return View::make('layouts.sales', array('products' => $products, 'status' => 'all'));
}

Saving associated models in Cakephp 3

I have a form that collects data about an Article, and I want to save that data, as well as for a model called Abstract, where an Article hasMany Abstracts. My models look like this:
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class AbstractsTable extends Table
{
public function initialize(array $config)
{
$this->belongsTo('Articles');
}
public function validationDefault(Validator $validator)
{
$validator
->notEmpty('body');
return $validator;
}
}
And
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class ArticlesTable extends Table
{
public function initialize(array $config)
{
$this->addBehavior('Timestamp');
$this->hasMany('Abstracts');
}
public function validationDefault(Validator $validator)
{
$validator ->notEmpty('category')
return $validator;
}
}
My input form has a field named 'abstracts.body', and in my ArticlesController I have this function:
public function add()
{
$data = $this->request->data;
$article = $this->Articles->newEntity($data, [
'associated' => ['Abstracts']
]);
if ($this->request->is('post')) {
$article->user_id = $this->Auth->user('id');
$data['abstracts']['user_id'] = $article->user_id;
$data['abstracts']['approved'] = 0;
$article = $this->Articles->patchEntity($article, $data, [
'associated' => ['Abstracts']
]);
if ($this->Articles->save($article, [ 'validate' => false,
'associated' => ['Abstracts']
]) )
{
$this->Flash->success(__('Your article has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('Unable to add your article.'));
}
$this->set('article', $article);
}
My Abstracts table is pretty straightforward:
CREATE TABLE 'abstracts' ('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 'article_id' INTEGER , 'user_id' INTEGER , 'body' TEXT, 'approved' BOOLEAN )
From debugging I can see that I have the correct 'abstracts' array within my $data (in add()), but it doesn't appear to ever try to save it to the database. Can someone please point out my error? Thanks!
Got it.
I started going wrong here:
My input form has a field named 'abstracts.body'
Because it's a hasMany relationship, I need to have that input be 'abstracts.0.body'
Then the rest of LeWestopher's answer will work-- adding an index to the fields I want to fill in from the Controller, so $data[abstracts][0]['user_id'] => ... and so on. Thanks!
You're post processing your $data['abstracts'] array incorrectly resulting in the association not saving. $data['abstracts'] is expected to be an array of Abstracts. Your issue lies here:
$data['abstracts']['user_id'] = $article->user_id;
$data['abstracts']['approved'] = 0;
You should be able to fix this pretty easily by changing this to:
foreach($data['abstracts'] as $index => $abstract) {
$abstract['user_id'] = $article->user_id;
$abstract['approved'] = 0;
$data['abstracts'][$index] = $abstract;
}
This should correctly iterate over your array of abstracts, set the user_id and approved keys appropriately and then it should save correctly.
CakePHP 3.x Documentation on Saving Associations
EDIT: Very interesting issue indeed. Try it without using patchEntity, and use newEntity by itself instead:
public function add()
{
if ($this->request->is('post')) {
$data = $this->request->data;
// Post process abstracts objects
foreach($data['abstracts'] as $index => $abstract) {
$abstract['user_id'] = $article->user_id;
$abstract['approved'] = 0;
$data['abstracts'][$index] = $abstract;
}
// Build newEntity
$article = $this->Articles->newEntity($data, [
'associated' => ['Abstracts']
]);
// Save our entity with associations
if ($this->Articles->save($article, [
'validate' => false,
'associated' => ['Abstracts']
])) {
$this->Flash->success(__('Your article has been saved.'));
return $this->redirect(['action' => 'index']);
}
// On save fail
$this->Flash->error(__('Unable to add your article.'));
$this->set('article', $article);
}
}
EDIT 2: Your issue looks like it's definitely in your form helper. Your current form helper input creates an $data array that looks like this:
$data = [
'abstracts' => [
'body' => 'example text'
],
'category' => 'Science'
];
Which SHOULD look like:
$data = [
'abstracts' => [
['body' => 'example text'],
['body' => 'Im your second abstract'],
['body' => 'Abstract three!']
],
'category' => 'Science'
];
The issue lies in:
abstracts.body
Which should read as (in array dot notation):
// abstracts.0.body
echo $this->Form->input('abstracts.0.body', [
'label' => 'summary of article',
'maxlength' =>'440',
'rows' => '7'
]);
I believe that should be the last issue you run into.

Unit testing the Auth Component

I am using the following code to test the login action in UsersController
public function testLogin() {
$data = array('User' => array(
'username' => 'hello',
'password' => '411'
)
);
$this->Users = $this->generate('Users',array('components'=> array('Auth','Session')));
$this->Users->Auth->staticExpects($this->once())
->method('user')
->with('id');
$this->testAction('/users/login', array('data' => $data, 'method' => 'post'));
}
and the fixture is-
class UserFixture extends CakeTestFixture {
public $import = array('model' => 'User', 'records' => true, 'connection' => 'fixture');
}
adn action is-
public function login() {
if($this->request->is('post')) {
if($this->Auth->login()) {
$this->redirect($this->Auth->redirect());
} else {
return false;
$this->Session->setFlash(__('Wrong Username Or Password,Please Try Again'));
}
}
}
It always showing
Expectation failed for method name is equal to when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.
What is the problem?Cant find any solution,and the reason also.Please help.
I think your problem mocking the auth component is that in addition to including auth in your components array, you need to specify which methods of Auth to mock, and how to mock them.
The way I deal with AuthComponent in my tests is I create a superclass with a method: _generateMockWithAuthUserId which mocks the Auth component, among other things, the way I need.
I've pasted the code from my superclass below.
class AppControllerTest extends ControllerTestCase {
public function setUp() {
parent::setUp();
$this->User = ClassRegistry::init('User');
}
public function tearDown() {
unset($this->User);
parent::tearDown();
}
public function testPlaceholder(){
// This just here so we don't get "Failed - no tests found in class AppControllerTest"
$this->assertTrue(true);
}
protected function _generateMockWithAuthUserId($contollerName, $UserId){
$this->authUserId = $UserId;
$this->authUser = $this->User->findById($this->authUserId);
$this->controller = $this->generate($contollerName, array(
'methods' => array(
'_tryRememberMeLogin',
'_checkSignUpProgress'
),
'components' => array(
'Auth' => array(
'user',
'loggedIn',
),
'Security' => array(
'_validateCsrf',
),
'Session',
)
));
$this->controller->Auth
->expects($this->any())
->method('loggedIn')
->will($this->returnValue(true));
$this->controller->Auth
->staticExpects($this->any())
->method('user')
->will($this->returnCallback(array($this, 'authUserCallback')));
}
public function authUserCallback($param){
if(empty($param)){
return $this->authUser['User'];
} else {
return $this->authUser['User'][$param];
}
}
}
And then here's a example of a class that inherits from that superclass. Take note of where/how it calls _generateMockWithAuthUserId. Basically, doing that sets up a suitable controller with Auth mocked for the appropriate user id.
<?php
require_once dirname(__FILE__) . DS . 'AppControllerTest.php';
class EmployeeNotesControllerTestCase extends AppControllerTest {
public $fixtures = array(
// your fixtures go here
);
public function setUp() {
parent::setUp();
$this->EmployeeNote = ClassRegistry::init('EmployeeNote');
}
public function tearDown() {
unset($this->EmployeeNote);
parent::tearDown();
}
public function testSupervisorIndexCanNotSeeNotesOnSelf() {
$authUserId = 1;
$this->_generateMockWithAuthUserId('EmployeeNotes', $authUserId);
$this->controller->Session
->expects($this->once())
->method('setFlash');
$result = $this->testAction('supervisor/employee_notes/index/'.$authUserId, array('return' => 'vars', 'method' => 'get'));
$this->assertTrue(empty($result['employeeNotes']));
}
}
Hope that helps.
I have found a solution.it worked.
public function testLogin() {
$data = array('User' => array(
'username' => 'sasa',
'password' => '111'
)
);
$this->Users = $this->generate('Users', array());
$result = $this->testAction('/users/login', array('data' => $data, 'method' => 'post'));
$this->assertEquals($data['User']['username'],$this->Users->Session->read('Auth.User.username'));
$result = $this->testAction('/users/logout');
}

Resources