[Solved] Error on no image

I have this code:

                if (empty($row->dogpic)) {
                    echo '<td class="imgtd">' . '&nbsp;' . '</td>';
                } else {
                    echo '<td>';
                    echo $this->Html->link(
                            $this->Html->image('imgdogs/' . $row->dogpic, array(
                                'class' => 'image',
                                'alt' => 'No image'
                            )), array(
                        'controller' => 'Dogs',
                        'action' => 'view', '?' => ['dogid' => $row->dogid]
                            ), array(
                        'class' => 'imgtd',
                        'escape' => false //to allow the image tag within the link
                            )
                    );
                    echo '</td>';
                }

Works with zero errors if there is no image missing.

However if an image is missing I get:

2023-11-06 05:36:25 error: [Cake\Http\Exception\MissingControllerException] Controller class `Img` could not be found. in D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Controller\ControllerFactory.php on line 308
Exception Attributes: array (
  'controller' => 'Img',
  'plugin' => NULL,
  'prefix' => NULL,
  '_ext' => NULL,
)
Stack Trace:
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Controller\ControllerFactory.php:74
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Http\BaseApplication.php:330
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Http\Runner.php:86
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Http\Middleware\CsrfProtectionMiddleware.php:169
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Http\Runner.php:82
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Http\Middleware\BodyParserMiddleware.php:157
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Http\Runner.php:82
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Routing\Middleware\RoutingMiddleware.php:118
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Http\Runner.php:82
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Routing\Middleware\AssetMiddleware.php:78
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Http\Runner.php:82
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Error\Middleware\ErrorHandlerMiddleware.php:115
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Http\Runner.php:82
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Http\Runner.php:67
- D:\xampp\apache\cake5up\vendor\cakephp\cakephp\src\Http\Server.php:103
- D:\xampp\apache\htdocs\cake5\index.php:34
- [main]:

Request URL: /img/imgdogs/baker329.jpg
Referer URL: http://localhost/cake5/dog/index
Client IP: 127.0.0.1

Why the error, I have ‘alt’ => ‘No image’?

Same code tried in laravel and a custom framework with exact image folder doesn’t show any error.

You’re showing a bit of template code but the error doesn’t look related to that.

The error is saying there is a missing Controller

Controller class `Img` could not be found.

This is being thrown from ...cakephp\src\Controller\ControllerFactory.php. That and the stack trace suggest to me that you’re still trying to parse the Request.

Do you have an ImgController? I can see from the link in your template you have a Dogs controller…

I’m not sure how you’re getting a request to an Img controller but it doesn’t look like the template code is playing a role. Maybe some other Controller code is failing and redirecting in an unexpected way?

@dreamingmind I have no idea why “Img”.

But if I have 20 images (this is a foreach loop), with no missing images then no error.

If however I delete one of the images but not the record, I get the error.

Whole thing:


<div id="tbl-container">
    <table id="mytable" class="dogtable">
        <tr>

            <th class="imgtd">id</th>
            <th class="imgtd">Dogpic</th>
            <th class="dname">Name</th>
            <th class="dsex">Sex</th>
            <th class="dogcomment">Comments</th>
        </tr>
        <?php
        if ($query) {
            foreach ($query as $row) {
                echo "<tr>";
                echo "<td class=\"dname\">" . $row->dogid . "</td>";
                if (empty($row->dogpic)) {
                    echo '<td class="imgtd">' . '&nbsp;' . '</td>';
                } else {
                    echo '<td>';
                    echo $this->Html->link(
                            $this->Html->image('imgdogs/' . $row->dogpic, array(
                                'class' => 'image',
                                'alt' => 'No image'
                            )), array(
                        'controller' => 'Dogs',
                        'action' => 'view', '?' => ['dogid' => $row->dogid]
                            ), array(
                        'class' => 'imgtd',
                        'escape' => false //to allow the image tag within the link
                            )
                    );
                    echo '</td>';
                }
                echo "<td class=\"dname\">" . $row->dogname . "</td>";
                echo "<td class=\"dsex\">" . $row->sex . "</td>";
                echo "<td class=\"dogcomment\">" . $row->comments . "</td>";
            }
        }
        ?>
    </table>
</div>

This is a mystery.

You should be able to figure out if the error is really coming from the template code or the controller action that precedes it.

Put the line

debug('made it to the end of the action');

as the last line of that controller method that drives this template.

And put the line

debug('made it into the template')

as the first line of the template.

My guess is that you will see neither debug because something is going wrong before the controller method can finish.

@dreamingmind I don’t install the debug package, but I put

echo 'top';  // at top of controller method

//and

echo 'bottom'; one line before the render command.

Both displayed.

In network tab I get 404 not found on the missing image, so alt isn’t working?

Right. So it’s the request from the browser to get the image…

The reason for that is not jumping out. Are there any clues in the page source from the browser? What does the link tag and its child image tag look like?

@dreamingmind

One of the missing images “view source”:

<td class="dname">1</td><td><a href="/cake5/dogs/view?dogid=1" class="imgtd"><img src="/cake5/img/imgdogs/belle2.jpg" class="image" alt="No image"></a></td>

Error ImgController could not be found.

The images are under \cake5\img\imgdogs.

Since the image is missing, cake is trying to find a controller, but that doesn’t make sense.

This error is starting to ring a bell far back in my memory. I’ve seen it before but haven’t laid my hands on how I solved it yet.

Maybe in the morning the answer will be waiting. Or someone else will know just what the problem is :slight_smile:

@dreamingmind Okay I will work on it more tomorrow.

Just FYI, I retested laravel, exact same conditions, no error on a missing image.

My unconfirmed guess as to how I fixed this:

I made the image src attribute a relative path (relative to webroot). Like:

<img src="img/imgdogs/belle2.jpg" class="image" alt="No image">

There is also this page that may help.

That is the expected and intended behavior, nothing wrong with it. The default application template’s Apache rewrite rules will make Apache directly serve existing physical files, without actually hitting your application code.

In case no physical file exists, the rewrite rules will pass the request to the application, just like any other request, where the app will then try to look up plugin assets or match a route, and throw a 404 if neither exists, which is a signal for the client that no such file exists, neither a physical one, nor one served by application code.

If you don’t want these exceptions to be logged, then you can add the \Cake\Http\Exception\NotFoundException \Cake\Http\Exception\MissingControllerException to the error handler’s skipLog configuration. This should usually be exclusive to the production environment though.

https://book.cakephp.org/5/en/development/errors.html

@ndm in app.php I made the changes:

    'Error' => [
        'errorLevel' => E_ALL,
        'skipLog' => ['Cake\Http\Exception\NotFoundException', 'Cake\Http\Exception\UnauthorizedException'],
        'log' => true,
        'trace' => true,
        'ignoredDeprecationPaths' => [],
    ],

However exact error is still logged.

Edit:

Changed to

'skipLog' => ['Cake\Http\Exception\MissingControllerException'],

That works. But I only need a not found image not logged.

Yeah, sorry, I copy-pasta’d the wrong name, of course it’s MissingControllerException.

There is no such distinction, a missing controller is a missing controller, no matter what kind of resource the client was possibly looking for. Having CakePHP try to guess what the resource might be would open a whole new can of worms that nobody wants do deal with.

You could of course create your own extended error handler that analyzes the request URL and skips exceptions based on that, but I’m not sure that it’s worth the hassle.

Personally I usually just skip MissingController/Action (or MissingRoute in case no fallback routes exist) and most Http exceptions for public apps in production, as otherwise the logs just get clogged with noise by all the bots visiting non-existent/protected endpoints.

@ndm thanks, I’m going with that.