cakephp render + afterfilter variables are unset - cakephp

I am trying to use render for specific action names in my app.
Actually, here are my condition set in my AppController::afterFilter()
if($this->action == 'parameter') {
$this->render('/Elements/parameter');
}
else if($this->action == 'datagrid') {
$this->render('/Elements/datagrid');
}
And in my controller /samples/parameter :
$this->set('model', Inflector::singularize(Inflector::camelize($this->name)));
$this->set('controller', $this->name);
if($parameter_id) {
$this->set('mode', $mode);
$this->set('parameter', $this->Sample->find('first', array('conditions' => array('Sample.id' => $parameter_id))));
} else {
$this->set('mode', 'add');
$this->set('parameter', array());
}
I know that I have to render AFTER the definition of variables, so I use afterFilter Something I don't understand or missed ?
Infos:
I have set in Samples Controller the function
public function afterFilter(){
parent::afterFilter();
}
Thank you all!

The afterFilter() callback is called after rendering process is done, so calling render() inside it is doing it wrong.
If you want to change the view to be rendered do so in beforeRender(). So do something like
if ($this->action == 'parameter') {
$this->view = '/Elements/parameter';
} elseif ($this->action == 'datagrid') {
$this->view = '/Elements/datagrid';
}

Related

How to unset a laravel session array

Hi I'm trying to remove a product array inside my cart session when the quantity is 1 and user tries to remove it, simply unsets that.
Here is my code:
public function remove($id)
{
if (session('cart')) {
foreach (session('cart') as $product) {
if ($product['id'] == $id) {
if ($product['qty'] == 1) {
} else {
$product['qty'] = $product['qty'] - 1;
}
};
}
Session::put('cart', session('cart'));
return redirect()->back();
}
}
I tried to use Session::forget('cart.'$num) but having some more issues.
Take your session edit it, and then re-set it:
$cart = session('cart');
array_forget($cart, $num);
session()->put('cart', $cart);

validation error messages in BaseController

I have a UsersController'S signup action which gathers validation error messages like
if($user->errors()) {
$error_msg = [];
foreach( $user->errors() as $errors) {
if(is_array($errors)){
foreach($errors as $error) {
$error_msg[] = $error;
}
} else {
$error_msg[] = $errors;
}
}
if(!empty($error_msg)){
$this->Flash->error(__(implode("\n \r", $error_msg)) );
}
}
This kind of error messages I want to use in all controllers. This means I have to repeat the same code in all controllers? Or is there a way to write a central function without passing specific entity?
If you want to get model validation in string you can create a component which can be accessed from the controller
Create a component UtilsComponent.php under src/Controller/Component
<?php
namespace App\Controller\Component;
use Cake\Controller\Component;
class UtilsComponent extends Component
{
public function validationError($validationError)
{
$errorMsg = '';
if ($validationError) {
foreach ($validationError as $errorOn => $error) {
$errorMsg .= strtoupper($errorOn) . ': ' . implode(', ', $error) . "\n";
}
} else {
$errorMsg = 'Error Occurred! Try again';
}
return $errorMsg;
}
}
After that you can use this function anywhere in the controller like this
if ($this->Users->save($user)) {
// Do what you want
} else {
$this->Flash->error(__($this->Utils->validationError($user->errors())));
}
Hope this will help

Pass array from one controller to another. Laravel

I'm trying to pass array from one controller to another. But I have no idea how to that.
I have my Bill Controller with array:
public function store(Request $request, $id,$sid)
{
$selected = array();
if ($request->annual != 0) {
$selected['annual'] = $request->annual;
}
if ($request->registration != 0) {
$selected['registration'] = $request->registration;
}
if ($request->monthly != 0) {
$selected['monthly'] = $request->monthly;
}
if ($request->annual != 0) {
$selected['annual'] = $request->annual;
}
return redirect()->route('invoice', [$sid]);
}
Here, I have passed $sid to another controller PdfController through route.
My Route:
Route::get('sid/{sid}', 'PdfController#invoice')->name('invoice');
PdfController:
class PdfController extends Controller
{
public function invoice($sid)
{
$data = $this->getData();
$date = date('Y-m-d');
$student = Student::where('id',$sid)->first();
$view = \View::make('layouts.bill',compact('data', 'date','student'))->render();
$pdf = \App::make('dompdf.wrapper');
$pdf->loadHTML($view);
return $pdf->stream('invoice');
}
How can I pass array from my BillController to my PdfController? Can anyone help me?
You can use different ways,
Create a cache (Cache::forever) variable and pass it.
Create a database temporary table with model and pass it.
Create a static variable and first set your variable and get again.
If you can tell which data you need to pass, we can help you much better.

How to define a checkbox variable in Cakephp

I have a form in my Plugin elements and what i would like to insert the checkbox value into a table named it_queries and field status_type and its giving me an error Undefined variable: variableValue [APP\Plugin\Feedback\View\Elements\comment_add.ctp, line 37] .I have declared the variable in my controller like this
$this->set('variableValueStatus', 'Pending');
and this is line 37 thats giving me the error
Below is the Controller code
App::uses('FeedbackAppController', 'Feedback.Controller');
class CommentsController extends FeedbackAppController
{
public $components = array('Feedback.Comments');
public function add($foreign_model = null, $foreign_id = null)
{
if (empty($foreign_model) ||
empty($foreign_id) ||
!$this->request->is('post')
)
{
foreach ($_POST['likebutton'] as $pageId => $likeFlag) {
$dbFlag = $likeFlag ? 'Yes' : 'No';
}
return $this->redirect('/');
}
App::uses($foreign_model, 'Model');
$Model = ClassRegistry::init($foreign_model);
if (!($Model instanceof Model))
{
return $this->redirect('/');
}
if ($Model->hasAny(array($Model->primaryKey => $foreign_id)) == false)
{
return $this->redirect('/');
}
if (!isset($this->request->data['Comment']['foreign_model']) ||
!isset($this->request->data['Comment']['foreign_id']) ||
$this->request->data['Comment']['foreign_model'] != $foreign_model ||
$this->request->data['Comment']['foreign_id'] != $foreign_id)
{
return $this->redirect('/');
}
$user_id = null;
if (isset($this->Auth))
{
$user_id = $this->Auth->user('id');
}
$this->request->data['Comment']['foreign_model'] = $Model->name;
$this->request->data['Comment']['foreign_id'] = $foreign_id;
$this->request->data['Comment']['user_id'] = $user_id;
$this->Comment->create();
if (!$this->Comment->save($this->request->data))
{
$this->set('validation_errors', $this->Comment->validationErrors);
return;
}
$this->redirect($this->request->referer().'#comment-'.$this->Comment->id);
}
}
and in the add view in my element here is how i am trying to accessing the variable value
echo $this->Form->checkbox('ItQuery.status_type', array('type' => 'hidden', 'value'=>$variableValueStatus));
If someone can show me how to fix this, that would be awesome
You are only passing the variable down on !post and if foreign model and foreign id are not set.
That will most likely not work in most of the cases.
You should be always passing down a variable if you do not check on it in the view prior to using it.
But it would still be wrong, anyway. You would have to use "default" instead of "value" if you dont want your form to fall back on the old value on POST (which it shouldnt).
Also, it is always better to use $this->request->data to properly fill the form with defaults:
if (!$this->request->is('post')) {
$this->request->data['ItQuery']['status_type'] = 'Pending';
}
See working-with-forms

CakePHP 2.2.4: Redirect not Working When Using Component

It has come to my attention that the redirect controller method is not working part of the time. No message appears when I set debug > 0. I don't echo any code before calling the redirect method so it shouldn't be because of "headers already sent".
Let's take a look at my ArticlesController add action where redirect works in one instance but not in another.
public function add($page = null) {
// Custom component to get if user has required access level
// of page to write an article. If not, setflash to an error message
// specific to user's access level and redirect.
$access_message = $this->CustomPage->AccessMessage(4, $this->viewVars['access']);
if($access_message){
// Flash works but redirect does not
$this->Session->setFlash(__($access_message));
$this->redirect(array('action' => 'index', 'page' => $page));
// Also tried
// $this->redirect(array('controller'=>'articles', 'action' => 'index', 'page' => $page), null, true);
} else
{
if ($this->request->is('post')) {
$this->Article->create();
if ($this->Article->save($this->request->data)) {
// BLAH BLAH save post, do other stuff
// BLAH BLAH save post, do other stuff
// This flash and redirect works
$this->Session->setFlash(__('The article has been saved'));
$this->redirect(array('action' => 'view', 'id' => $article_id, 'page' => $page));
} else {
$this->Session->setFlash(__('The article could not be saved. Please, try again.'));
} // end else if article cannot be saved
} // if method is post
} // end if user has access
} // end add action
It definitely has something to do with the component but I'm not sure what. Maybe since redirect is called right after the component is used, the "$this" is trying to do the redirect method on the component instead of the controller. I tried $this->Article->redirect and reloading the Article model before the redirect but neither of those worked.
My component code is:
public function AccessMessage($required_level, $user_level) {
if(!$user_level && $this->_View->viewVars['access']){
$user_level = $this->_View->viewVars['access'];
}
if(!$required_level || !$user_level || $user_level != $required_level){
$accessModel = ClassRegistry::init('Access');
$access_message = $accessModel->field('access_message', array('Access.id' => $required_level));
}
return $access_message;
}
Edit 1: Ok so I did some digging to find exactly where the problem is stemming from. The USE of the component is not the problem which I thought it was before. If all I have in my component is
public function AccessMessage($required_level, $user_level) {
if(!$user_level && $this->_View->viewVars['access']){
$user_level = $this->_View->viewVars['access'];
}
if(!$required_level || !$user_level || $user_level != $required_level){
$access_message = 1;
}
return $access_message;
}
Then it works. The issue is with these two lines which are correctly implemented because they return the value for $access_message I am expecting, but they are interfering with the ability to redirect. Perhaps headers are already sent out?
$accessModel = ClassRegistry::init('Access');
$access_message = $accessModel->field('access_message', array('Access.id' => $required_level));
Please note I have also tried:
$access_message = ClassRegistry::init('Access')->field('access_message', array('Access.id' => $required_level));
And
$this->loadModel('Access');
$access_message = $this->Access->field('access_message', array('Access.id' => $required_level));
Gists:
component gist: https://gist.github.com/970a951715205c222348
controller gist: https://gist.github.com/2b90e5af2518a81672fb
access model gist: https://gist.github.com/bhndbrwneyes/f333a93f0a21302d832f
You may have space before/after php Opening/Closing tags in controller and models. Remove all the closing tags from all controllers and models and any whitespace before opening tags. Then check the result.
Not an answer yet, but at least there are some variables in your code that may not be defined, or errors that can occur:
public function AccessMessage($required_level, $user_level) {
if(!$user_level && $this->_View->viewVars['access']){
$user_level = $this->_View->viewVars['access'];
}
if(!$required_level || !$user_level || $user_level != $required_level){
$access_message = 1;
}
return $access_message;
}
Variable $access_message will only be defined if a user is not allowed to access the page
An error may occur if the 'access' viewVar is not set at all
Change it to this:
public function AccessMessage($required_level, $user_level) {
$access_message = 0;
if(!$user_level && $this->_View->get('access')){
$user_level = $this->_View->get('access');
}
if(!$required_level || !$user_level || $user_level != $required_level){
$access_message = 1;
}
return $access_message;
}
[updated] saw you did have the $access_message defined on your gist (https://gist.github.com/970a951715205c222348)
However:
This will not work
App::uses('Component', 'Controller', 'ClassRegistry', 'Utility');
App::uses() takes two arguments; the 'class' you would like to use and the location it can be found. The line above should be written as:
App::uses('Component', 'Controller/Component');
App::uses('Controller', 'Controller');
App::uses('ClassRegistry', 'Utility');
But I wonder if ClassRegistry needs to be loaded manually
[update 2] You really have a lot 'weird' things going on in your application, so I wonder if we'll be able to sort that out:
public function add($page = null) {
$access = $this->viewVars['access'];
if($this->CustomPage->AccessMessage(4, $access)){
$this->Session->setFlash(__($this->CustomPage->AccessMessage(4, $access)));
$this->redirect(array('action' => 'index', 'page' => $page));
}
// ......
}
Where is 'viewVars['access']' set?
You're passing 'viewVars['access']' as the second parameter ($user_level) to AccessMessage(), but inside AccessMessage() you're trying to use the same viewVar again if the parameter '$user_level' was not set?
$this->CustomPage->AccessMessage() is called twice once to check if it returned anything, then to use it. Not very efficient
.
public function add($page = null) {
// Where does is $this->viewVars['access'] come from? Where is it set?
$access = empty($this->viewVars['access'])? null : $this->viewVars['access'];
$message = $this->CustomPage->AccessMessage(4, $access);
if ($message) {
$this->Session->setFlash(__($message));
$this->redirect(array('action' => 'index', 'page' => $page));
}
// ......
}
On a further note. you're redirecting the user only if a 'message' was found and not empty, NOT based on the current users permissions, you might consider splitting the two;
In your component:
public function HasAccessLevel($required_level, $user_level) {
if(!$user_level || $user_level != $required_level){
return false;
}
return true;
}
public function AccessMessage($required_level) {
return ClassRegistry::init('Access')->field('access_message', array('Access.id' => $required_level));
}
In your controller:
public function add($page = null) {
// Where does is $this->viewVars['access'] come from? Where is it set?
$access = empty($this->viewVars['access'])? null : $this->viewVars['access'];
if($this->CustomPage->HasAccessLevel(4, $access)){
$this->Session->setFlash(__($this->CustomPage->AccessMessage(4)));
$this->redirect(array('action' => 'index', 'page' => $page));
}
// ......
}
Cake 2: At the top of the component: add
public function initialize(Controller $controller) {
$this->Controller = $controller;
}
inside the function you can redirect like so:
$this->Controller->redirect(array('plugin' => false, 'controller' => 'users', 'action' => 'index'));
If the redirect is called, but you are not redirected I guess you have some permission check in your index() action that prevents the access. Can you confirm or post the whole controller code?

Resources