phpcakephpcakephp-4.x

Redirect only working on some controller actions


A redirect, called by the private function r(), in the edit function works, but not in the delete.

Even commenting out the allowMethod doesn't help.

Any ideas why that would be?

/**
    * Edit method
    *
    * @param string|null $id Task id.
    * @return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise.
    * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
    */
public function edit($id = null)
{
    //get task
    $task = $this->Tasks->get($id, [
        'contain' => ['Users'],
    ]);

    $this->r();
    ...
}

/**
    * Delete method
    *
    * @param string|null $id Task id.
    * @return \Cake\Http\Response|null Redirects to index.
    * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
    */
public function delete($id = null)
{
    $this->request->allowMethod(['post', 'delete']);

    //get task
    $task = $this->Tasks->get($id, [
        'contain' => ['Users'],
    ]);

    $this->r();
    ...
}

private function r()
{
    $this->Flash->error(__('Not enough permissions to edit this task.')); 
    return $this->redirect(['controller' => 'tasks', 'action' => 'view',687]);
}

I modified the Controller class in /vendor to output the $response object.

Debug of headers following edit redirect:

CORE\src\Controller\Controller.php (line 695)
object(Cake\Http\Response) id:0 {
'status' => (int) 302
'contentType' => 'text/html'
'headers' => [
'Content-Type' => [
(int) 0 => 'text/html; charset=UTF-8',
],
'Location' => [
(int) 0 => 'http://localhost:9000/spt/tasks/view/687',
],
]
'file' => null
'fileRange' => [ ]
'cookies' => object(Cake\Http\Cookie\CookieCollection) id:1 {
protected cookies => [ ]
}
'cacheDirectives' => [ ]
'body' => ''
}

Debug of headers following delete redirect:

CORE\src\Controller\Controller.php (line 695)
object(Cake\Http\Response) id:0 {
'status' => (int) 302
'contentType' => 'text/html'
'headers' => [
'Content-Type' => [
(int) 0 => 'text/html; charset=UTF-8',
],
'Location' => [
(int) 0 => 'http://localhost:9000/spt/tasks/view/687',
],
]
'file' => null
'fileRange' => [ ]
'cookies' => object(Cake\Http\Cookie\CookieCollection) id:1 {
protected cookies => [ ]
}
'cacheDirectives' => [ ]
'body' => ''
}

Edit #1

Prior to this post, $this->r(), had logic to determine if it needed to redirect or not:

//code evaluating the need to redirect

//redirect if not editable by user
if($isEditable === false)
{
    $this->Flash->error(__('Not enough permissions to edit this task.')); 
    return $this->redirect(['controller' => 'tasks', 'action' => 'view',$task->id]);
}
else
{
    return null;
}

Edit #2

This seems to work and offer some reusability:

   /**
    * Edit method
    *
    * @param string|null $id Task id.
    * @return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise.
    * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
    */
public function edit($id = null)
{
    //get task
    $task = $this->Tasks->get($id, [
        'contain' => ['Users'],
    ]);

    if($this->r() === false)
    {
        $this->Flash->error(__('Not enough permissions to edit this task.')); 
        return $this->redirect(['controller' => 'tasks', 'action' => 'view',687]);
    }
    
    //rest of controller:action code
}

/**
    * Delete method
    *
    * @param string|null $id Task id.
    * @return \Cake\Http\Response|null Redirects to index.
    * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
    */
public function delete($id = null)
{
    $this->request->allowMethod(['post', 'delete']);

    //get task
    $task = $this->Tasks->get($id, [
        'contain' => ['Users'],
    ]);

    if($this->r() === false)
    {
        $this->Flash->error(__('Not enough permissions to edit this task.')); 
        return $this->redirect(['controller' => 'tasks', 'action' => 'view',687]);
    }
    
    //rest of controller:action code
}

private function r()
{
    //logic to determine $isEditable
    return $isEditable
}

Returning null, stops the processing of the action, the view no longer gets the variables passed and fails.

Assuming that I now have to move the conditional check in the controller instead of the $this->r() and redirect accordingly.


Solution

  • What's working now. Essentially, function returns boolean that is used to redirect.

     /**
        * Edit method
        *
        * @param string|null $id Task id.
        * @return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise.
        * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
        */
    public function edit($id = null)
    {
        //get task
        $task = $this->Tasks->get($id, [
            'contain' => ['Users'],
        ]);
    
        if($this->r() === false)
        {
            $this->Flash->error(__('Not enough permissions to edit this task.')); 
            return $this->redirect(['controller' => 'tasks', 'action' => 'view',687]);
        }
        
        //rest of controller:action code
    }
    
    /**
        * Delete method
        *
        * @param string|null $id Task id.
        * @return \Cake\Http\Response|null Redirects to index.
        * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
        */
    public function delete($id = null)
    {
        $this->request->allowMethod(['post', 'delete']);
    
        //get task
        $task = $this->Tasks->get($id, [
            'contain' => ['Users'],
        ]);
    
        if($this->r() === false)
        {
            $this->Flash->error(__('Not enough permissions to edit this task.')); 
            return $this->redirect(['controller' => 'tasks', 'action' => 'view',687]);
        }
        
        //rest of controller:action code
    }
    
    private function r()
    {
        //logic to determine $isEditable
        return $isEditable
    }