Похоже, эхо PHP появляется не в порядке - PullRequest
0 голосов
/ 14 июня 2019

Я работаю над личным проектом, создавая некоторые базовые функциональные возможности для работы с PHP-компонентами, чтобы их можно было создавать аналогично компонентам в React. Я столкнулся с каким-то странным поведением, когда если я рендерил компонент внутри строки, используя строковую интерполяцию, он появляется перед тем местом, в котором он вызывается в коде. Я могу заставить разметку отображать правильно, выполняя каждый шаг в виде отдельной строки кода, но я хотел бы иметь возможность включать эти компоненты в строки. Почему этот рендеринг может происходить не по порядку? Любая идея будет принята с благодарностью.

Я пытался вернуть включенные компоненты вместо их эхо, но (возможно, из-за использовавшихся двойных кавычек?) Они вообще не рендерится при этом. Я также объединил компоненты вместе в виде строк. Это не работает. Если я пишу отдельные строки кода и заканчиваю их точкой с запятой после каждого, я получаю ожидаемый результат.

Вот что я хотел бы иметь:

    echo "
        <section class='videoInfo'>
            <h1>{$props[$video]->getProperty(VIDEO_PROP::TITLE)}</h1>
            <div class='secondary'>
                <span class='viewCount'>{$props[$video]->getProperty(VIDEO_PROP::VIEWS)} views</span>
                {$loader::render(COMPONENT::OPINION_CONTROLS)}
                {$loader::render(COMPONENT::VIDEO_DETAILS)}
            </div>
        </section>
    ";

Я также попробовал это, что приводит к тому же искаженному выводу, что и выше:

    echo "
        <section class='videoInfo'>
            <h1>{$props[$video]->getProperty(VIDEO_PROP::TITLE)}</h1>
            <div class='secondary'>
                <span class='viewCount'>{$props[$video]->getProperty(VIDEO_PROP::VIEWS)} views</span>" .
                $loader::render(COMPONENT::OPINION_CONTROLS) .
                $loader::render(COMPONENT::VIDEO_DETAILS) .
            "</div>
        </section>
    ";

Это работает правильно, но более громоздко написать:

    echo "
        <section class='videoInfo'>
            <h1>{$props[$video]->getProperty(VIDEO_PROP::TITLE)}</h1>
            <div class='secondary'>
                <span class='viewCount'>{$props[$video]->getProperty(VIDEO_PROP::VIEWS)} views</span>";
                $loader::render(COMPONENT::OPINION_CONTROLS);
                $loader::render(COMPONENT::VIDEO_DETAILS);
        echo "</div>
        </section>
    ";

Я ожидаю, что выходной HTML будет отражать отраженную строку. Таким образом, окончательный результат должен выглядеть следующим образом:

<section class="videoInfo">
            <h1>Second Test</h1>
            <div class="secondary">
                <span class="viewCount">86 views</span>
        <!-- includes javascript for handling like/dislike buttons -->
        <script src="assets/js/opinions.js"></script>
        <div class="controls">

            <button class="opinion far fa-thumbs-up" onclick="like(this, 60)">
                <span class="text">0</span>
            </button>


            <button class="opinion far fa-thumbs-down" onclick="dislike(this, 60)">
                <span class="text">0</span>
            </button>

        </div>

        <!-- includes javascript for handling edit/subscribe buttons -->
        <script src="assets/js/videoInteractions.js"></script>
        <section class="details">
            <nav>

            <a href="profile.php?username=testman">
                <img src="assets/images/generic_profile.png" class="profilePic">
            </a>

            </nav>
            <div class="uploadInfo">
                <span class="uploader">
                    <a href="profile.php?username=testman">
                        testman
                    </a>
                </span>
                <span class="uploadDate">
                    Published on Jun 4, 2019
                </span>
            </div>

            <button class="subscribe " onclick="subscribe(&quot;chan123&quot;, &quot;testman&quot;, this)">
                <span class="text">Subscribe 0</span>
            </button>

            <section class="description">
                Testing view incrementing
            </section>
        </section>
    </div>
        </section>

Это действительно вывод, который я получаю, если выполняю каждый шаг в виде отдельной строки кода. Однако, если я использую интерполяцию или конкатенацию строк, компоненты загружаются не по порядку. Фактически загруженные компоненты появляются перед разделом videoInfo!



            <button class="opinion far fa-thumbs-up" onclick="like(this, 60)">
                <span class="text">0</span>
            </button>


            <button class="opinion far fa-thumbs-down" onclick="dislike(this, 60)">
                <span class="text">0</span>
            </button>


            <nav>

            <a href="profile.php?username=testman">
                <img src="assets/images/generic_profile.png" class="profilePic">
            </a>

            </nav>
            <div class="uploadInfo">
                <span class="uploader">
                    <a href="profile.php?username=testman">
                        testman
                    </a>
                </span>
                <span class="uploadDate">
                    Published on Jun 4, 2019
                </span>
            </div>

            <button class="subscribe " onclick="subscribe(&quot;chan123&quot;, &quot;testman&quot;, this)">
                <span class="text">Subscribe 0</span>
            </button>

            <section class="description">
                Testing view incrementing
            </section>

            <h1>Second Test</h1>
            <div class="secondary">
                <span class="viewCount">87 views</span>


            </div>

Компоненты вывода сами по себе отражают строки. Они выглядят так:

(opinionControls)

    echo "
        <!-- includes javascript for handling like/dislike buttons -->
        <script src='assets/js/opinions.js'></script>
        <div class='controls'>
            $likeButton
            $dislikeButton
        </div>
    ";

(videoDetails)

    echo "
        <!-- includes javascript for handling edit/subscribe buttons -->
        <script src='assets/js/videoInteractions.js'></script>
        <section class='details'>
            <nav>
                $profileButton
            </nav>
            <div class='uploadInfo'>
                <span class='uploader'>
                    <a href='profile.php?username=$uploader'>
                        $uploader
                    </a>
                </span>
                <span class='uploadDate'>
                    Published on $formattedDate
                </span>
            </div>
            $interactButton
            <section class='description'>
                {$props[$video]->getProperty(VIDEO_PROP::DESCRIPTION)}
            </section>
        </section>
    ";

Вложенные эхо как-то всплывают из эха верхнего уровня? Я пытаюсь обернуть голову вокруг этого поведения.

Я пытался отрегулировать вложенные компоненты, заставляя их возвращать строки вместо эха, но мне не повезло заставить их визуализироваться таким образом. Я пробовал одинарные кавычки и двойные кавычки вокруг возвращаемых строк. Вот так:

    return '
        <!-- includes javascript for handling like/dislike buttons -->
        <script src=\'assets/js/opinions.js\'></script>
        <div class=\'controls\'>
            $likeButton
            $dislikeButton
        </div>
    ';

и

    return "
        <section class='videoInfo'>
            <h1>{$props[$video]->getProperty(VIDEO_PROP::TITLE)}</h1>
            <div class='secondary'>
                <span class='viewCount'>{$props[$video]->getProperty(VIDEO_PROP::VIEWS)} views</span>
                {$loader::render(COMPONENT::OPINION_CONTROLS)}
                {$loader::render(COMPONENT::VIDEO_DETAILS)}
            </div>
        </section>
    ";

Функция $ loader :: render () довольно проста. Он вызывает функцию, которая вызывает include () для компонента, который был загружен немного раньше в приложении. Соответствующие функции ComponentLoader следующие:

    // Load component into static primedComponents array as a key, with its value its props
    public static function primeComponentWithProps(string $includesPath, array $props)
    {
        self::$primedComponents[$includesPath] = $props;
    }
    // Extract component and props from static array, then include it on the page
    public static function render(string $includesPath)
    {
        $props = self::$primedComponents[$includesPath];
        $args = [$includesPath, $props];

        self::loadComponentWithProps(...$args);
        // remove the component from the array of primed components once it has been rendered
        unset(self::$primedComponents[$includesPath]);
    }

    /** used to import components that require props */
    public static function loadComponentWithProps(string $includesPath, array $props)
    {
        // extract($props);     // using extract() would allow props to be accessed directly by key names--but currently we are using a props array and accessing values by key to make it clearer what is going on in components which consume props
        include($includesPath);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...