codeigniter4 / CodeIgniter4

Open Source PHP Framework (originally from EllisLab)
https://codeigniter.com/
MIT License
5.4k stars 1.9k forks source link

Bug: [Parser] Cascading Data causes ErrorException #7096

Closed fraigo closed 1 year ago

fraigo commented 1 year ago

PHP Version

7.4

CodeIgniter4 Version

4.2.11

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

macOS, Linux

Which server did you use?

apache

Database

No response

What happened?

The following code example extracted from https://codeigniter4.github.io/userguide/outgoing/view_parser.html#cascading-data triggers an exception

ErrorException foreach() argument must be of type array|object, string given SYSTEMPATH/View/Parser.php at line 318

<?php

$template = '{name} lives in {location}{city} on {planet}{/location}.';

$data = [
    'name'     => 'George',
    'location' => ['city' => 'Red City', 'planet' => 'Mars'],
];

return $parser->setData($data)->renderString($template);
// Result: George lives in Red City on Mars.

Parser::parsePair(string $variable, array $data, string $template) expects an list of items with key/value pairs for the $data parameter. In this case $data is ['city' => 'Red City', 'planet' => 'Mars'].

It works fine with loop substitutions like in this example https://codeigniter4.github.io/userguide/outgoing/view_parser.html#loop-substitutions It does not work with the above example or in any 'nested' substitution like this example https://codeigniter4.github.io/userguide/outgoing/view_parser.html#nested-substitutions

Steps to Reproduce

Run this code from a controller:

<?php
$parser = \Config\Services::parser();

$template = '{name} lives in {location}{city} on {planet}{/location}.';

$data = [
    'name'     => 'George',
    'location' => ['city' => 'Red City', 'planet' => 'Mars'],
];

return $parser->setData($data)->renderString($template);

Expected Output

George lives in Red City on Mars.

Anything else?

Backtrace:

SYSTEMPATH/View/Parser.php : 318 — CodeIgniter\Debug\Exceptions->errorHandler SYSTEMPATH/View/Parser.php : 242 — CodeIgniter\View\Parser->parsePair Arguments

$variable: location
$data: Array (
    [city] => Red City
    [planet] => Mars
)
$template: George lives in {location}{city} on {planet}{/location}.
kenjis commented 1 year ago

Thank you for reporting. I sent a PR to fix: #7103

fraigo commented 1 year ago

@kenjis the example under 'Nested substitutions' has the same issue using the same data format for blog_entry value https://codeigniter4.github.io/userguide/outgoing/view_parser.html#nested-substitutions

        $parser = \Config\Services::parser();
        $data = [
            'blog_title'   => 'My Blog Title',
            'blog_heading' => 'My Blog Heading',
            'blog_entry'   => [
                'title' => 'Title 1',
                'body'  => 'Body 1',
            ],
        ];
        return $parser->setData($data)->renderString("<h1>{blog_title} - {blog_heading}</h1>
        {blog_entry}
            <div>
                <h2>{title}</h2>
                <p>{body}</p>
            </div>
        {/blog_entry}");

In both cases, I think adding support for a single object of array/value pairs will allow this simple syntax to be parsed correctly without changing the documentation examples. I've sent a PR to implement this fix: #7109

kenjis commented 1 year ago

@fraigo I fixed the sample code in my PR.

{vars}...{/vars} is for multiple data. Why do you need to set a single data?