Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sage 10 Child/Parent Theme Support #450

Open
10 of 12 tasks
ouun opened this issue Nov 26, 2019 · 15 comments
Open
10 of 12 tasks

Sage 10 Child/Parent Theme Support #450

ouun opened this issue Nov 26, 2019 · 15 comments

Comments

@ouun
Copy link
Sponsor

ouun commented Nov 26, 2019

Description

Related to this discussion: https://discourse.roots.io/t/sage-10-as-parent-child-themes/
It would be fantastic to get some feedback ftom @Log1x and @QWp6t

Steps to reproduce

1. Parent Theme:

1.1 Make a new Sage 10 Theme with custom Namespace "Parent" in folder 'parent'
1.2 Add some View Composers variables such as "siteName" and reference it in a blade file
1.3 Add a function my_test_function() to helpers.php
1.4 Activate the theme, it should be working and the variable $siteName is outputted correctly

2. Child Theme

1.1 Make a new Sage 10 Theme and leave the Namespace as "App" in folder child
1.2 Add Template: parent to style.css
1.3 Remove all blade files from ./resources/views/
1.4 Use \Parent\my_test_function() e.g. in a child View Composer
1.5 Autoload parent theme Class in composer.php:

"psr-4": {
      "App\\": "app/",
      "Parent\\": "./../parent/app/"
    }

1.5 Activate the child theme

Expected behavior: [What you expect to happen]

  • Blade views are loaded from parent theme
  • View Composers are loaded from parent theme as well as from child theme (ideally overwriting parent values)
  • Functions from parent theme in helpers.php are available via \Parent\my_test_function()
  • Config via \Roots\config() is loading parent theme value, if child theme value is not set

Actual behavior: [What actually happens]

  • Blade views are loaded from parent theme
  • Undefined variable: siteName errors, the View Composers from the parent theme are missing
  • Call to undefined function errors when calling \Parent\my_test_function()
  • Error if e.g. \Roots\config('app.debug') is not set in child theme as function not checks against parent value

Reproduces how often: [What percentage of the time does it reproduce?]

In the current setup 100%. More tests required.

Versions

Sage 10.0.0-alpha

Additional information

It would be fantastic to get a very short summary how child/parent themes should be set-up with Sage 10.

@ouun
Copy link
Sponsor Author

ouun commented Nov 26, 2019

Regarding Functions from parent theme in helpers.php are available via \Parent\my_test_function() I was able to solve it:

In the functions.php I oversaw that locate_template() is used what checks for files by hierachy (Searches STYLESHEETPATH before TEMPLATEPATH). So as I still had a helpers.php, setup.php, ... in my child/app folder, it loaded the child one and skipped the parent files in parent/app even though they should get included as well (by default).
So this is fixable by renaming either the files. In my case I renamed parent/app to parent/inc so the locate_template() function in the parents function.php will recognize them.

So for now I am only confused what the best way is to autload the View Composers from the parent theme.

Cheers

@ouun
Copy link
Sponsor Author

ouun commented Nov 27, 2019

Well, another issue solved. Quite easy and obvious when now thinking about it:

In the child theme config/view.php you have to (of cause) add the composer Classes:

    'composers' => [
        // App\Composers\Alert::class,
        Parent\Composers\Alert::class,
        Parent\Composers\App::class,
        Parent\Composers\Title::class,
    ],

Furthermore if you have custom ServiceProviders in the parent theme, you need to load them as well in /config/app.php:

 'providers' => [
        Parent\Providers\ThemeServiceProvider::class,
        // App\SomeService\SomeServiceServiceProvider::class,
    ],

So my currently only leftover is that it would be fantastic to get config values via \Roots\config() that fallbaks to parent value if it is not overwritten in the child theme.

@Log1x
Copy link
Sponsor Member

Log1x commented Feb 29, 2020

Putting this on hold until Sage 10 documentation is finished.

@evankford
Copy link
Sponsor

To chime in here from my debugging work, it looks like the current method for adding composers/components from outside the theme directory structure is no longer in config/app.php or config/view.php.

The way I've found to implement composers and components is to implement theme in your child theme's ServiceProvider. Specifically, you'll want to add them into the boot() function as shown in the Laravel documentation for View Composers and manually registering package components. Both of these are a bit clunky, as shown below.

/** ... 
* Inside your ThemeServiceProvider.php file
*/
use Roots\Acorn\ServiceProvider;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\View;

...

 /**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot() {
    // Boot your view composers here. 
    // Note that you have to redefine the 'view' in order for it to use this composer on the correct view partials
    View::composer('view.name', \ParentApp\View\Composers\ViewName::class);

    // Boot your components here. 
    Blade::component('alert', \ParentApp\View\ComposersComponents\Alert::class);

}

This is obviously not great because you have to define your view names, and import all your classes manually. Shouldn't we be able to boot the parent theme's ServiceProvider and bring in all those Composers/Components? Someone with more Laravel/PHP experience may be able to help with that. I have a feeling that if we want a child theme/app to work, we'll need to create a child theme fork.

In the mean time, I hope this helps the poor souls looking to make this work.

@gitgudcameron
Copy link

Does anyone have a working example of a Sage 10 parent / child theme for a noob like myself? :)

@ouun
Copy link
Sponsor Author

ouun commented May 11, 2021

@gitgudcameron you can have a look at this comment: ouun/stage#204 (comment)

@slackday
Copy link

slackday commented Oct 19, 2021

Thanks @evankford I was struggling with how to convert a Sage9 child-theme to Sage10 (after parent theme upgrade).

I'm not 100% familiar with Blade/View/Composers yet but following your example I managed to get it working.

In child theme composer file I put

  "autoload": {
    "psr-4": {
      "App\\": "./../sage/app",
      "Child\\": "app/"
    }
  },

To load the parent theme.

I don't think it makes sense to load all components in boot so I don't mind defining each line. For example to use parents theme App I put

View::composer('*', \App\View\Composers\App::class);

And child theme also uses "site messages" in layouts/app.blade.php.

View::composer('site.messages', \App\View\Composers\Site\Messages::class);

However for all the components I found "componentNamespace" in Laravel documentation which is nice so in the boot function I also put

Blade::componentNamespace('\\App\\View\\Components', 'sage');

and can use the parent themes components in the child theme like so <x-sage::page-section>...</x-sage::page-section>

Hope this helps anyone else making a child theme!

edit

Oh yeah... all the child themes View/Composers are namespaced like so namespace Child\View\Composers;

@waqas-raza-dh
Copy link

Please let me know If I need to open a new issue for this on github?

Is there any proper guide for setting up the child theme with sage 10? I am using sage 10 as my main theme on WordPress and for customizations, I have to create the child theme. I tried following the above discussion to create the child theme and it does not work. Changing the parent theme's namespace to Parent (from App) breaks the connection between composers and views, data does not go to the views.

Child theme is activated.

getting this error

Undefined variable $heroBackground in section-page-header.blade.php
$heroBackground is defined in the Parent\View\Composers\App.php

in the child App.php I have the following code

<?php

namespace App\View\Composers;

use Roots\Acorn\View\Composer;

class App extends Composer
{
}

And in the child theme's App\Providers\ThemeServiceProvider

<?php

namespace App\Providers;

use Roots\Acorn\ServiceProvider;

class ThemeServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //this outputs the correct data from the parent function
        dd((new \Parent\View\Composers\App())->getColorScheme());
    }
}

Any hint about where to go from this point will be much appreciated.

@evankford
Copy link
Sponsor

@waqas-raza-dh

Any hint about where to go from this point will be much appreciated.

If I understand from my troubles with this, it's likely that the child theme is not loading the parent's view composer for section-page-header.blade.php. Usually, that would be a SectionPageHeader.php class file in the App/View/Composers folder/namespace.

I'm sure there's a more elegant way to autoload all the parent's composer classes, but I add the ones I need to the boot function in the child's ThemeServiceProvider

 /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        View::composer('index', \Parent\View\Composers\Index::class);
        View::composer('partials.footer', \Parent\View\Composers\Footer::class);

        ... Whatever else you have here

Surely you could programmatically fetch all parent classes, or maybe I'm doing something wrong and they're supposed to be autoloaded, but this works for me.

@waqas-raza-dh
Copy link

@evankford thank you for clearing things out for me. So, in my Parent view composer App\View\Composers I am passing some common data to all the views so I am able to get the variables like {{$var}} in my parent blade files.
But when I activate my child theme and load the parent view composer in the boot method

View::composer('*', \App\View\Composers\App::class);

it does not make any difference, and I still get the error that variable does not exist.

@evankford
Copy link
Sponsor

@waqas-raza-dh Without knowing more, it's hard to say why that's not loading. I would check:

  1. Is the \App namespace the parent or the child app? In your first example, you used \Parent for the parent app.
  2. If you're correctly referencing the file, you should check that the code is loading at all (a var_dump, or inserting some broken code).
  3. Is your child ThemeServiceProvider loading?

@waqas-raza-dh
Copy link

@evankford I was able to fix the issue. The issue was within the child stylesheet. So, composer files are loading perfectly now and all the data is also coming through. Is there any correct way of importing parent theme's styles and scripts.
Currently I am importing the parent theme's style in my child theme like below

@import "../parent-theme/resources/styles/app.scss";
and when i run the build some css does not load.

@smirnizky
Copy link

Hello everybody! Tell me please is there any detailed guide on how to create child theme for Sage 10 properly? Can you give me the URL of such tutorial if it exists? Is this approach recommended at all?

@QWp6t QWp6t transferred this issue from roots/sage Feb 10, 2023
@Dathix
Copy link

Dathix commented Feb 22, 2023

Hey everyone! I would like to push this discussion further ahead and hopefully, we will come up with a solution that we can incorporate into Acorn and add some official documentation about child themes. I think @ouun has a good starting point here https://github.com/ouun/stage/blob/master/app/Providers/StageServiceProvider.php#L56. I would love to just call attachParentComposers() or even detect the child theme and automatically attach them. What do you guys think, can we make this work a little bit more smooth?

@smirnizky
Copy link

@Dathix I think it's a great idea! I want to take part in this task, but I don't have enough skills to do it. I wounder what Sage core team members think about child theme support in future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants