Sober Controller "Hello World" in a views/partial

Let’s say I want to print “Hello World” in the header.

I can do it with a static method in the app/controllers/Header.php:

<?php
namespace App;

use Sober\Controller\Controller;

class Header extends Controller
{
    public static function hello()
    {
        return "Hello world.";
    }
?>

And views/partials/header.blade.php:

<header class="">
  <div class="container">
    {{Header::hello()}}
  </div>
</header>

A controller: app/controllers/Header.php:

But with a non-static function:

class Header extends Controller
{
    public function hello()
    {
        return "Hello world.";
    }
}

Returned thus:

Then views/partials/header.blade.php:

<header class="">
  <div class="container">
    {{$hello}}
  </div>
</header>

Nothing is displayed.

Trying to wrap my head around the relationship between blades and controllers in Sober and Blade. Why is the result of a public non-static method is exposed to single.blade.php in the Sober example, but here a static method seems to be required? Does the controller file and/or class need to be named differently?

1 Like

“Header” isn’t an endpoint, or node, or whatever WordPress calls them. In normal (non-Sage) theming WordPress never calls a “Header” template; it calls single.php or page.php, which themselves include header.php and any number of other partials. Sage introduces the theme-wrapper, with app.blade.php, but the principle is the same; WordPress knows its endpoints, and Controller sets up data for those endpoints.

1 Like

So the Controller data is only directly available to blades that match standard wordpress template file names?

I believe that is correct. @withjacoby knows for sure (or we could dig through his code) but that’s how I’ve always used them, and how all of his examples are set up.

If you need something available in your header, you can set it up in app/controllers/app.php; then it’ll be available in every view.

Controller data is available at matching endpoints. Sometimes these correspond to blade names (i.e. single.blade.php), but any blades in use at that endpoint will have access to controller data. For instance, if you @include your header.blade.php in single.blade.php, it will have access to data defined in the Single.php controller.

In other words, there’s no connection between blades and controllers; there just appears to be sometimes because certain blades are loaded at certain endpoints.

2 Likes

Do you mean in the file at app/controllers/app.php or as a method in the App controller class?

Those are equivalent. The App controller is defined in app/controllers/app.php.

Right, but it wouldn’t work to create a new class in the app/controllers/app.php because it wouldn’t register with the autoload, right?

That’s correct. Each controller file should contain only one class (eventually controller will move to autoloading with PSR-4, which I believe requires this). So you’d be creating that method in the App class.

Then, since views/partials/header.blade/php is included in views/app.php, shouldn’t the result of siteName() be exposed there via the variable {{ $siteName }}? Because for me it is not. I also tried a helloWorld App method:

public function helloWorld()
{
    return "Hello World.";
}

But {{ $helloWorld }} doesn’t seem to be yielding expected string.

It’s possible that this functionality was broken by my adaptations to make Sage9 work in Docker.

Oh i see. It is available simply via $helloWorld. No {{ brackets }}.

Controller converts camelCase to snake_case, so $helloWorld is available as $hello_world.

It’s being converted to snake case. Try $hello_world. Use @debug in your view to see what’s being passed on.

The new version of Controller will have PSR4, and you will be able to specify templates overrides from the Controller file.

1 Like

Thanks @alwaysblank!

The new debugger is going to have even more information, so that really should be helpful. It’s mostly wrapped up, just a few tests and extra code to add.

3 Likes

@mZoo you may want to look into using traits for the header example above. Controller works on passing data through a filter based on the body class. If you inspect the page, you will see the added classes with -data. These are essentially ‘end points’ that you could use. You can also inherit previous body classes/‘end points’ using protected $tree = true; in the Controller class.

Yes. Body classes. For example app-data index-data home-data front-page-data. Cool.

It looks like the Tree Module is useful where you want to have a controller endpoint that is “down the tree” in template hierarchy inherit (or override) methods from a higher controller, for example controller/Single-{post-type}.php would have access to methods in controller/Single.php.

I’m having trouble seeing how that would be applicable in this case.

A Hello World example–in case it’s useful to anyone–within header.blade.php or any blade that is @include()ed in app.blade.php.

Two files: app/controllers/app.php:

<?php

namespace App;

use Sober\Controller\Controller;

class App extends Controller
{
    ... other methods ...

    public function helloWorld()
        {
            return "Hello World.";
        }
} 

The method name, helloWorld will be converted to “snake case” or hello_world, and to a variable: $hello_world.

Blade at views/partials/header.blade.php:

<!-- THIS FILE MUST BE INCLUDED IN app.blade.php -->
$hello_world
<!-- Use following line to see what variables are exposed in this blade -->
@debug

Will look in front end like this:

Hello World.

Controller Debugger:

  • $post » object
  • $site_name » string
  • $hello_world » string

If you wanted to say “Hello Universe” in various controllers you could create a trait:

File app/controllers/partials/helloUniverse:

<?php

namespace App;

trait helloUniverse
{
    public function helloUniverse()
    {
        return "Hello Universe.";
    }

}

?>

Then in any controller class you can add the single line:

use helloUniverse

And within blades at that endpoint (app, front-page, single, etc), which includes blades included in the blades at those endpoints, you will find that $hello_universe is exposed for use.

Just wanted to note that @include isn’t the only way to get blades into that correct flow: you can also @extends a blade into layouts/app.blade.php using @section. i.e. the following would also work:

// views/partials/header.blade.php
@extends('layouts.app')
@section('content')
    $hello_world
    @debug
@endsection

Anyway, glad you figured it out! :slight_smile:

1 Like