Sage: Conflict between SoberWP/Controller and $post

Created on 20 Jul 2017  路  6Comments  路  Source: roots/sage

Submit a feature request or bug report


What is the current behavior?

With the addition of SoberWP/Controller, whenever is_singular() resolves to true the App controller receives a $post variable with the current post/page/etc object. However, this overrides the behavior of the shared blade $post variable on subsequent included partials (#1786)

What is the expected or desired behavior?

The included partial $post variable should be pointing to the actual current post defined by the_post().


Bug report

Please provide steps to reproduce, including full log output:

On a clean WP installation:

  • Put a @php(var_dump($post->ID)) inside the single.php or page.php;
  • Create a partial file which prints the $post->ID property as well;
  • Create a custom loop new WP_Query(['post_type' => ['post', 'page'], 'posts_per_page' => -1]) and iterate it while calling the previously created partial;
  • The printed IDs will be the same, even if we're querying for the 'Hello world' post and the 'Sample page'.

Please describe your local environment:

WordPress version: 4.8

OS: MacOS

NPM/Node version: Not relevant

Where did the bug happen? Development or remote servers?

Both

Is there a related Discourse thread or were any utilized (please link them)?

No

Most helpful comment

I've been doing a little research on this, and although I don't have a good solution yet, I wanted to chime in with what I've figured out.

Although the $post variable doesn't function as described above, other functions that return post-specific information _do_ work, i.e. things like get_the_ID() or the_title(). Take the following setup:

// resources/views/single.blade.php
$loop = new WP_Query(['post_type' => ['post', 'page'], 'posts_per_page' => -1]));
while ($loop->have_posts()) : $loop->the_post();
    @include('partials.testing')
endwhile;

// resources/views/partials/testing.blade.php
{{ get_the_title() }}

// Hello world! 
// Sample Page 

This means that if you need $post, you can always just do this inside your loop:

$original_post = $post;
$loop = new WP_Query(['post_type' => ['post', 'page'], 'posts_per_page' => -1]));
while ($loop->have_posts()) : $loop->the_post();
    $post = the_post();
    @include('partials.testing')
endwhile;
$post = $original_post;

You can also pass the variable directly to your include:

@include('partials.testing', ['post' => the_post()]

If you need it a lot, you can write a custom directive that essentially mimics the function of @include, but adds in the correct $post:

// app/lib/setup.php 
sage('blade')->compiler()->directive('includePost', function ($expression) {
    return "<?php echo \$__env->make(
        {$expression}, 
        array_except(
            array_merge(get_defined_vars(), ['post' => get_post()]), 
            array('__data', '__path')
        ))->render(); ?>";
});

// resources/views/single.blade.php
$loop = new WP_Query(['post_type' => ['post', 'page'], 'posts_per_page' => -1]));
while ($loop->have_posts()) : $loop->the_post();
    @includePost('partials.testing')
endwhile;

// resources/views/partials/testing.blade.php
@php(var_dump($post->ID))

// int(1) 
// int(2)

All 6 comments

I've been doing a little research on this, and although I don't have a good solution yet, I wanted to chime in with what I've figured out.

Although the $post variable doesn't function as described above, other functions that return post-specific information _do_ work, i.e. things like get_the_ID() or the_title(). Take the following setup:

// resources/views/single.blade.php
$loop = new WP_Query(['post_type' => ['post', 'page'], 'posts_per_page' => -1]));
while ($loop->have_posts()) : $loop->the_post();
    @include('partials.testing')
endwhile;

// resources/views/partials/testing.blade.php
{{ get_the_title() }}

// Hello world! 
// Sample Page 

This means that if you need $post, you can always just do this inside your loop:

$original_post = $post;
$loop = new WP_Query(['post_type' => ['post', 'page'], 'posts_per_page' => -1]));
while ($loop->have_posts()) : $loop->the_post();
    $post = the_post();
    @include('partials.testing')
endwhile;
$post = $original_post;

You can also pass the variable directly to your include:

@include('partials.testing', ['post' => the_post()]

If you need it a lot, you can write a custom directive that essentially mimics the function of @include, but adds in the correct $post:

// app/lib/setup.php 
sage('blade')->compiler()->directive('includePost', function ($expression) {
    return "<?php echo \$__env->make(
        {$expression}, 
        array_except(
            array_merge(get_defined_vars(), ['post' => get_post()]), 
            array('__data', '__path')
        ))->render(); ?>";
});

// resources/views/single.blade.php
$loop = new WP_Query(['post_type' => ['post', 'page'], 'posts_per_page' => -1]));
while ($loop->have_posts()) : $loop->the_post();
    @includePost('partials.testing')
endwhile;

// resources/views/partials/testing.blade.php
@php(var_dump($post->ID))

// int(1) 
// int(2)

This will be fixed on the next release of Controller, which I'll tag this coming weekend.

There's another fix on this thread so long, https://github.com/soberwp/controller/issues/82

This issue can be closed.

Can the soberwp dependency be updated from 9.0.0-beta.4 to the latest safely?

@rpasillas

I don't think you can update to the latest version safely. I just did, and I get a fatal error

@rpasillas @DragosMocrii use 2.0.1. dev-master is still a working repo. I am going to tag 2.1.0 this week though.

This is fixed on dev-master of Controller, and will be tagged this week. Issue can be closed.

Was this page helpful?
0 / 5 - 0 ratings