0

I am developing a web app, trying to keep PHPstan's suggestions in check.

I am having some difficulties with this method:

/**
 * AJAX: deletes a work file
 *
 * @return \Cake\Http\Response|false
 */
public function delete()
{
    $this->autoRender = false;
    $this->viewBuilder()->setLayout('ajax');
    $this->request->allowMethod(['post', 'delete']);

    $data = $this->request->getData();
    $data = is_array($data) ? $data : [$data];

    $workFile = $this->WorkFiles->find('all')
        ->where(['WorkFiles.id' => $data['id']])
        ->contain(['Works'])
        ->first();

    $res = [
        'status' => 'error',
        'message' => __('The file could not be deleted. Please, try again.'),
        'class' => 'alert-error',
    ];

    if ($workFile->work->anagraphic_id == $this->authAnagraphics['id']) { // error #1
        if ($this->WorkFiles->delete($workFile)) { // error #2
            $res = [
                'status' => 'success',
                'message' => __('File successfully deleted.'),
                'class' => 'alert-success',
            ];
        }
    }

    return $this->response->withStringBody((string)json_encode($res));
}

The code itself works, but I'm having two phpstan errors:

  1. [phpstan] Cannot access property $work on array|Cake\Datasource\EntityInterface|null.
  2. [phpstan] Parameter #1 $entity of method Cake\ORM\Table::delete() expects Cake\Datasource\EntityInterface, array|Cake\Datasource\EntityInterface|null given.

Am I doing something wrong?

1
  • 1
    ->first() can return EntityInterface or array or null. phpstan doesn't know which one you have. null->work is not a valid construct, nor is ->delete(null), so it's warning you about that. At the very least, you should be checking for a null return value and issuing an error, or else use ->firstOrFail so an exception is thrown. I'm not sure what circumstances lead to an array being returned here (->hydrate(false) maybe?), your best bet for that might just be to add a PHPDoc comment to clarify that what you have will, in fact, be an entity object. Commented Oct 19, 2022 at 3:59

1 Answer 1

2

Always use inline annotation then here:

/** @var \App\Model\Entity\WorkFile|null $workFile */
$workFile = $this->WorkFiles->find('all')
    ->where(['WorkFiles.id' => $data['id']])
    ->contain(['Works'])
    ->first();

But the comments are right, you are blindly using a possible null value afterwards, as such your code is not written correctly.

Use this instead:

/** @var \App\Model\Entity\WorkFile $workFile */
$workFile = $this->WorkFiles->find('all')
    ->where(['WorkFiles.id' => $data['id']])
    ->contain(['Works'])
    ->firstOrFail();
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.