I am trying to query custom post types that have a relationship with the current post and then display ACF values from the queried posts.
I’m not sure if I worded that correctly but basically I have 2 main post types.
commercial_buildings commercial_listings
I have a relationship ACF that links the two together.
On the commercial_buildings blade template I am querying all commercial_listings that share a relationship with the building.
I have successfully queried all of the correct posts and can display ACF for each listing through get_field( 'acf_field_name', post_id ).
In my single-commercial_buildings.blade.php template I have this code for querying and displaying the content.
<!-- Building Listings WP Query -->
@php
$args = [
'post_type' => 'commercial_listings',
'meta_key' => 'commercial_listing_relationship_building',
'meta_value' => get_the_ID(),
'meta_compare' => 'LIKE'
];
$results = new WP_Query($args);
@endphp
<!-- Display commercial listings available in this building -->
@foreach( $results->posts as $p)
{{ $p->ID }}
<h1>{{ get_field( 'commercial_listing_info_name', $p->ID) }}</h1>
@endforeach()
<!-- Reset WP query -->
@php wp_reset_postdata() @endphp
The way I have everything setup seems to work but In order to access all of my commercial_listing fields I will have to setup variables inside @php tags. This doesn’t seem like the correct way of doing things.
Can I setup my code to be able to work with the WP_Query results inside a @foreach loop like this?
First off, I would put WP_Query out of the view template and into the appropriate controller, to better separate logic from view.
Just this might help you properly define your variables/functions to be used as a @foreach.
So, just to clarify: if set up correctly you will be able to use $commercial_listings variable instead of $results->posts as the controller will make it available when defining it as a function, for example:
public function commercial_listings() {
// your wp_query here + return custom data or just $results
// out of my head:
$args = [
'post_type' => 'commercial_listings',
'meta_key' => 'commercial_listing_relationship_building',
'meta_value' => get_the_ID(),
'meta_compare' => 'LIKE'
];
return new WP_Query($args);
}
If you use something like this in a controller for single-commercial_buildings.blade.php then you can just use $commercial_listings variable to access your wp_query result, for example:
Be careful when defining the function (static or non-static) as it changes how it is available in the template. If static, you would use something like App::yourFunction() if defined in App Controller.
I hope this was useful? If not, let me know If I can help elsewhere.
I was setting up the query logic in a controller but ran into an issue that I can’t figure out.
I setup a controller in \app\Controllers called SingleCommercialBuildings.php
I added the following code to the controller.
<?php
namespace App\Controllers;
use Sober\Controller\Controller;
class SingleCommercialBuildings extends Controller
{
public function getBuildingListings()
{
// setup query arguments
$args = [
'post_type' => 'commercial_listings',
'meta_key' => 'commercial_listing_relationship_building',
'meta_value' => get_the_ID(),
'meta_compare' => 'LIKE'
];
return new WP_Query($args);
}
// Testing
public function sayHello() {
return 'hello';
}
}
The problem I am having is that I cannot access data from the controller in my blade template. At first I thought my query was messed up so I tried passing a simple string with the sayHello() function but that doesn’t come through.
I get an Undefined variable error when I try to add it to the blade template with {{ $say_hello }}.
If I add the sayHello() function to the App.php controller it works.
I ran @debug() inside the blade template to see what data was being passed to it.
This is all the data that I get back
App
Data
postobject
commercial_buildingobject
site_namestringline 12—15
Methods
titleline 17—35
commercial_building is being passed in because I set protected $acf = true; in App.php
In my composer.json I have the controller set to this version "soberwp/controller": "~2.1.0"
I read through the soberwp/controllers documentation on github and couldn’t find a solution.
I tried it on a local test environment and it works as expected. If I had to guess I would say it’s just a naming issue, try to check again, if the names of these two match:
That means that when your existing class is converted to be passed to a filter, it is converted to single-commercial-buildings, which matches nothing. It should be converted to single-commercial_buildings, but in order for that to happen your class must be SingleCommercial_Buildings.
I changed the class name from SingleCommercialBuildings to SingleCommercial_Buildings.
When I just changed the class name I got a Fatal error: Uncaught ReflectionException: Class App\Controllers\SingleCommercialBuildings does not exist in... error.
I fixed this error by also changing the controller filename from SingleCommercialBuildings.php to SingleCommercial_Buildings.php but the data and the sayHello() function doesn’t seem to work on the template.
I used CPT UI to setup my custom post types. Should I set up my post types another way to bypass this issue?
Check the class on your body for the template on the front-end, and make sure that it includes single-commercial_buildings—this value is what Controller is actually matching against.
@withjacoby maybe have some more insight: This is probably about the limit of my familiarity with Controller.
Interestingly enough by making my sayHello() function a static function and calling it with {{ SingleCommercial_Building::sayHello() }} in the blade template I actually get the returned value.
Should I just static functions even if they are not within the loop?
Static methods in Controllers are just namespaced functions. If that’s what you want to do you can, but then there’s no real reason to use Controller: you could just put them anywhere.