Best Practice / Resources for Blade

Hello there :slight_smile: Iā€™ve started using Sage few weeks back locally, on my development setup where everything works fine, but when I try to deploy on my shared hosting server I get the following error:

:  Uncaught ReflectionException: Class Illuminate\Filesystem\Filesystem does not exist in /home/user/domain.com/wp-content/themes/test/vendor/illuminate/container/Container.php:719
Stack trace:
#0 /home/user/domain.com/wp-content/themes/test/vendor/illuminate/container/Container.php(719): ReflectionClass->__construct('Illuminate\\File...')
#1 /home/user/domain.com/wp-content/themes/test/vendor/illuminate/container/Container.php(598): Illuminate\Container\Container->build('Illuminate\\File...')
#2 /home/user/domain.com/wp-content/themes/test/vendor/illuminate/container/Container.php(567): Illuminate\Container\Container->resolve('Illuminate\\File...')
#3 /home/user/domain.com/wp-content/themes/test/vendor/illuminate/container/Container.php(246): Illuminate\Container\Container->make('Illuminate\\File...', Array)
#4 /home/user/domain.com/wp-content/themes/test/vendor/illuminate/container/Container.php(716): Illuminate\Container\Container->Illuminate\Contain in 

on line 719

Iā€™ve followed the steps outlined in Sage Docs, installed Composer on the server, run the ā€œcomposer installā€ command from theme directory but I still get this error. Iā€™ve tried with my custom theme and clean theme directly from master branch on GitHub repo.

Iā€™ve tried with PHP versions 5.6 and 7.0.

Any help would be greatly appreciated as Iā€™m stuck on this for more than a day now :slight_smile:

1 Like

Iā€™m curious, why involve the controller at all for this example? Seems like it makes it complex, what am I missing? :slight_smile:

How to can a PHP function used in blade?
I defined a custom one in helpers.php - but blade cannot find it.
Do I have to add the helpers.php to composer.json as described in

Without knowing exactly what youā€™re doing (code examples), itā€™s hard to help.

There is nothing special about using PHP functions in Blade.

I guess it should be enough to call your method in blade template this way - App\method()

1 Like

Thanks for all the answers. I got it working by adding a new php file with these helpers to composer.json as described in

1 Like

I recently updated my WP-CLI template compiler plugin to be (marginally) more flexible and powerful:

  • Finds all .blade.php files and compiles them (no more hard-coding template directories)
  • Accepts a directory argument to limit it to a specific theme subdirectory
2 Likes

Would be a bit interesting to see how you guys setup your views. Iā€™m curious how you tackle ACF fields such as a repeater field. I saw there was an example earlier in the thread where have_rows is used in the view.

Iā€™ve been going back and forth with using have_rowsin the view, and setting up the controller to loop all data into an array which then is output in the view. This way I lose the ACF logic from the view, which to me feels a bit cleaner, but also a little bit more work.

How do you do it?

Hey @withjacoby - Really great plugin, cheers!

Iā€™m using it by putting the plugin contents in /app/lib/Sober/Controller/, and then in functions.php adding 'lib/Sober/Controller/controller' to the array_map function (if anybody cares).

Iā€™m including Controller like this

I see @vdrnnā€™s solution above, but is there not a nicer way to handle ACFā€™s repeater field, so that get_row_layout() can be called in a while loop to get a partial for that particular layout?

For example, I have:

@if(have_rows($item_header))
	<div class="page-header">
    @while(have_rows($item_header))
			<div class="{{('full-width' === $item_header_layout) ? 'container-fluid' : 'container'}}">
				<div class="row">
					<div class="page-header-inner {{$item_header_layout}}">
						@php(the_row())
						@php(get_template_part('views/flexibles/' . get_row_layout()))
					</div>
				</div>
			</div>
    @endwhile
	</div>
@endif

But Iā€™ve discovered that the_row() and get_row_layout() (or indeed the while loop) wonā€™t work by using the Controller to put get_field into the $item_header variableā€¦

I tried a variation of the code available here, but this wonā€™t allow me to utilise a particular template partial depending on the ACF field in question.

Any pointers on this would be a huge help!

EDIT:
For now, Iā€™ve decided to not use ACF Repeater / Flexible Content fields with Controller, else Iā€™m looping twice (one in the Controller, then once on the page) ā€“ Iā€™m just using it instead for simple variables.

Great work though! Thanks again :slight_smile:

3 Likes

Hey @joneslloyd,

Thanks so much.

I agree with the way youā€™re doing it now, I do it the same way.

In some cases, if there arenā€™t that many fields I will do the acf loop within Controller and expose an array to loop through. But I think if there are lots of fields then use the acf loop within the view. You can get data within the acf loop using a public static method which also may be useful in some cases, https://github.com/soberwp/controller#using-static-methods

2 Likes

Thanks for the clarification.

Iā€™l check out using static methods as a way of dealing with ACF data.

Cheers

Hi all,

For those using Controller, please note that it is now a Sage dependency.

You can remove the mu-plugin and run composer require soberwp/controller:9.0.0-beta.3 from within the theme directory.

Thatā€™s all thatā€™s needed.

3 Likes

Is it possible you would need to remove composerā€™s type ā€œwordpress-mupluginā€. Despite having run composer clear-cache, It installs in [sage]/wp-content/mu-plugins/ā€¦ folder instead of vendor/soberwp/controller.

So sorry! thatā€™s such an oversight, should be fixed now.

2 Likes

Can you please show an example how you use/not use sober? Iā€™m usually using repeaters and flexible content alot, and it feels very weird and unefficient to loop over these fields in the controller, and then do the same in the view again.

Great tool none the less, thanks! :slight_smile:

1 Like

@intelligence for the most part, I still use the Advanced Custom Fields functions within the views, esp if within a loop. I will use Controller if I need to write some logic into the returned results though.

There are some good examples here though, esp the object syntax being used by @nathobson

Iā€™ll see if I can write up some use-cases/examples down the line. I have been wanting to create nicer documentation with an easier way to consume, so will work on that.

EDIT: I may look at doing a Sober/Controller/Acf helper class. Could be useful and speed up templating when using acf a lot.

2 Likes

That would be awesome. Iā€™m trying to do this right now and struggling a bit.

I was wundering if itā€™s possible to use a Trait used in the Sober controllers in a normal non-blade php file?

Letā€™s say I have a controller TemplateCustom.php where I want to use TraitA:

namespace App;
use Sober\Controller\Controller;


class TemplateCustom extends Controller {
	use TraitA;

	public function controlFields() {
		return (object) array (
			'posts' => TraitA::getPosts()
		);
	}
}

In my TraitA:

namespace App;

trait TraitA {

	/* Get all Posts  */
	public static function getPosts() {
		$postsObj = [];
		$posts   = get_posts([
			'post_type'      => 'post-type',
			'orderby'        => 'title',
			'order'          => 'ASC',
			'posts_per_page' => -1
		]);

		foreach ($posts as $post) {
			$postsObj[] = self::getPost($post->ID);
		}

		return json_decode(json_encode($postsObj));
	}

	/* Get Single Post */
	public static function getPost($id = null) {
		if ($id) {
			$post = get_post($id);
			$data = [
				'title' => get_the_title($id),
				'link'  => get_the_permalink($id),
				'slug'  => $post->post_name
			];

			return json_decode(json_encode($data));
		}
	}
}

and a blade view template-custom.blade.php where I use the returned Trait data:

{{--
  Template Name: Custom Template
--}}

@extends('layouts.app')

@section('content')
	@while(have_posts()) @php(the_post())
		@include('partials.content-post', array(
			'posts' => $control_fields->posts
		))
	@endwhile
@endsection

This works great!
However, I think these traits are only available within the Sober Controllers?

What if I want to re-use the TraitA functions in a normal php class outside the blade controllers & views:

class TraitTest {
	use TraitA;

	public function __construct() {
		add_filter('some_filter', 'populatePosts', 10, 2);
	}

	function populatePosts() {
		$posts = TraitA::getPosts();
		return $posts;
	}
}

new TraitTest;

The above will result in an error:

Fatal error: Trait 'TraitA' not found

Is my Trait approach wrong here?

Any help is welcome, thanks!

1 Like

Canā€™t fully test right now, but my first feeling would be that the Trait is only included from Controller after your custom class is included.

My guess is because you didnā€™t import it and youā€™re not using the correct namespace. From the code you posted, itā€™s not TraitA, itā€™s App\TraitA

3 Likes