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

How to use blade components with this package? #57

Open
nisa6delgado opened this issue Apr 14, 2021 · 12 comments
Open

How to use blade components with this package? #57

nisa6delgado opened this issue Apr 14, 2021 · 12 comments

Comments

@nisa6delgado
Copy link

No description provided.

@Antares84
Copy link

I second this issue. From what I've read in the Laravel docs, you're supposed to be able to use but in doing so it throws the following error:
Target [Illuminate\Contracts\View\Factory] is not instantiable.

Stack Trace:
#0 C:\inetpub*\vendor\illuminate\container\Container.php(845): Illuminate\Container\Container->notInstantiable()
#1 C:\inetpub*
\vendor\illuminate\container\Container.php(717): Illuminate\Container\Container->build()
#2 C:\inetpub*\vendor\illuminate\container\Container.php(655): Illuminate\Container\Container->resolve()
#3 C:\inetpub*
\vendor\illuminate\view\Compilers\ComponentTagCompiler.php(247): Illuminate\Container\Container->make()
#4 C:\inetpub*\vendor\illuminate\view\Compilers\ComponentTagCompiler.php(211): Illuminate\View\Compilers\ComponentTagCompiler->componentClass()
#5 C:\inetpub*
\vendor\illuminate\view\Compilers\ComponentTagCompiler.php(144): Illuminate\View\Compilers\ComponentTagCompiler->componentString()
#6 [internal function]: Illuminate\View\Compilers\ComponentTagCompiler->Illuminate\View\Compilers{closure}()
#7 C:\inetpub*\vendor\illuminate\view\Compilers\ComponentTagCompiler.php(139): preg_replace_callback()
#8 C:\inetpub*
\vendor\illuminate\view\Compilers\ComponentTagCompiler.php(90): Illuminate\View\Compilers\ComponentTagCompiler->compileOpeningTags()
#9 C:\inetpub*\vendor\illuminate\view\Compilers\ComponentTagCompiler.php(76): Illuminate\View\Compilers\ComponentTagCompiler->compileTags()
#10 C:\inetpub*
\vendor\illuminate\view\Compilers\BladeCompiler.php(334): Illuminate\View\Compilers\ComponentTagCompiler->compile()
#11 C:\inetpub*\vendor\illuminate\view\Compilers\BladeCompiler.php(231): Illuminate\View\Compilers\BladeCompiler->compileComponentTags()
#12 C:\inetpub*
\vendor\illuminate\view\Compilers\BladeCompiler.php(150): Illuminate\View\Compilers\BladeCompiler->compileString()
#13 C:\inetpub*\vendor\illuminate\view\Engines\CompilerEngine.php(55): Illuminate\View\Compilers\BladeCompiler->compile()
#14 C:\inetpub*
\vendor\illuminate\view\View.php(139): Illuminate\View\Engines\CompilerEngine->get()
#15 C:\inetpub*\vendor\illuminate\view\View.php(122): Illuminate\View\View->getContents()
#16 C:\inetpub*
\vendor\illuminate\view\View.php(91): Illuminate\View\View->renderContents()
#17 C:\inetpub*\Framework\Blade\BladeController.class.php(125): Illuminate\View\View->render()
#18 C:\inetpub*
\Framework\Core\CoreController.php(18): Blade\BladeController->loadView()
#19 C:\inetpub*\App\Controllers\CMS\Home.php(22): Core\CoreController->view()
#20 C:\inetpub*
\Framework\Bootstrap\Api.php(192): Controllers\CMS\Home->Index()
#21 C:\inetpub***\Public\index.php(38): Bootstrap\Api::__dispatch_routing()
#22 {main}

Any help with this issue would be greatly appreciated.

@MattyRad
Copy link

MattyRad commented Nov 9, 2021

Anonymous components ala 6.x work for me, fyi, like @component('alert'). But I get the same issue for Blade <x- templates. From quick cursory checks, it looks like Blade-x depends on several additional illuminate packages (cache/config, possibly even the entire illuminate/foundation).

@aparx
Copy link

aparx commented Feb 16, 2022

Is there any way this is fixed in the future?

@lexdubyna
Copy link

I was able to set up x- components but it's very verbose (since I am trying to show multifile solution in one post) and probably not correct way to do this.

<?php

use Illuminate\Container\Container;
use Illuminate\Contracts\Foundation\Application as ApplicationContract;
use Illuminate\Contracts\View\Factory as ViewFactoryContract;
use Illuminate\Support\Facades\Facade;
use Illuminate\View\Component;
use Illuminate\View\View;
use Jenssegers\Blade\Blade as JenssegersBlade;

$app = Container::getInstance();
$app->bind(ApplicationContract::class, Container::class);
$app->alias('view', ViewFactoryContract::class);

$blade = new JenssegersBlade(
    ['views'],
    'views/compiled',
    $app
);

$viewFactory = Facade::getFacadeApplication()->get('view');

$blade->compiler()->components([
    'media-image'                       => MediaImage::class,
    'components.anonymous.breadcrumbs'  => 'breadcrumbs' // yes, anonymous components with @props
]);

trait BladeViewComponent
{
    public function view(string $name): View
    {
        global $viewFactory;

        return $viewFactory->make("components.{$name}", $this->extractPublicProperties());
    }

    public function render(): View
    {
        return $this->view($this->template);
    }
}

// Very rough example with some wordpress stuff
final class MediaImage extends Component
{
    use BladeViewComponent;

    public readonly WordPressMediaImage|bool $image;

    private string $template = 'media-image';

    /**
     * @param string $wordpresstitle title of WP image attachment to process
     * @param string $size size parameter for wp image functions
     * @param string $class all the classes to assign to the img tag
     * @param int    $preload if the image needs to be preloaded
     */
    public function __construct(
        public readonly string $wordpresstitle,
        public readonly string $size = 'full',
        public readonly string $class = 'media-image',
        public readonly int $preload = 0
    ) {
        $this->image = $this->getWordPressMediaImage();
    }

    private function getAttachmentIdByTitle(): int|bool
    {
        $attachment = get_posts([
            'numberposts' => 1,
            's'           => trim($this->wordpresstitle),
            'lang'        => pll_current_language('slug'),
            'post_type'   => 'attachment'
        ])[0];

        if (!$attachment || !isset($attachment->ID)) {
            error_log("Media image not found: {$this->wordpresstitle}", 1);
            return false;
        }

        return $attachment->ID;
    }

    private function getWordPressMediaImage(): WordPressMediaImage|bool
    {
        if ($id = $this->getAttachmentIdByTitle()) {
            return new WordPressMediaImage($id, $this->size);
        }

        return false;
    }
}

Then in your blade template you can put this:

<x-media-image wordpresstitle="Background" class="home-bg-img" preload />

And components/media-image.blade.php looks like this:

@if ($image === false)
    <h1>There has been an error loading image "{{ $wordpresstitle }}"</h1>
@else
    @if ($preload)
        @push('preload')
            <link
                rel="preload"
                as="image"
                href="{{ $image->src }}"
                imagesrcset="{{ $image->srcsetWebp ? $image->srcsetWebp : $image->srcset }}"
                imagesizes="{{ $image->sizes }}"
            />
        @endpush
    @endif
    <picture>
        @if ($image->srcsetWebp)
            <source
                srcset="{{ $image->srcsetWebp }}"
                sizes="{{ $image->sizes }}"
                type="image/webp"
            />
        @endif
        <source
            srcset="{{ $image->srcset }}"
            sizes="{{ $image->sizes }}"
            type="{{ $image->metaData['sizes']['medium']['mime-type'] }}"
        />
        <img
            src="{{ $image->src }}"
            width="{{ $image->metaData['width'] }}"
            height="{{ $image->metaData['height'] }}"
            alt="{{ $image->alt }}"
            title="{{ $image->caption }}"
            class="{{ $class }}"
            loading="lazy"
        />
    </picture>
@endif

@lexdubyna
Copy link

Ok, I forked this repo and made some updates to be able to use components (class-based and anonymous)

https://github.com/lexdubyna/blade

@kaspost
Copy link

kaspost commented Apr 16, 2023

@lexdubyna how did you set this up in a WordPress theme? Is it possible to render from a given HTML string (that contains x-components)?

@kaspost
Copy link

kaspost commented Apr 16, 2023

To be more specific, I'm calling the $blade->compileString( $html ); method which throws me the error PHP Fatal error: Uncaught Illuminate\Contracts\Container\BindingResolutionException: Target [Illuminate\Contracts\Foundation\Application] is not instantiable. in E:\github\spring-reveal-plugin\vendor\illuminate\container\Container.php:1089.

This is the complete code used in my WordPress plugin:

<?php 
/*
 * Plugin Name: Spring reveal
 */
require plugin_dir_path( __FILE__  ) . '/vendor/autoload.php';
use Lexdubyna\Blade\Blade;
$blade = new Blade('views', 'cache');

add_action( 'init', function () {
    ob_start();
} );

add_action( 'shutdown', function () {
    global $blade;
    $html = ob_get_clean();
    echo $blade->compileString( $html );
    exit;
}, 0 );

@lexdubyna
Copy link

@kaspost You can check out how I implemented compileString in my forked version of this package:
https://github.com/lexdubyna/blade/blob/master/src/Blade.php#L133
Also, I'm not sure whether it's a good idea to put ob_start and ob_get_clean in two different actions.

@kaspost
Copy link

kaspost commented Apr 18, 2023

@lexdubyna Thank you and I'm using your forked version in composer. I boiled down the code to this bare minimum which still throws me the same error:

<?php 
/*
 * Plugin Name: X Components test
 */
$plugin_dir = plugin_dir_path( __FILE__  );
require $plugin_dir . '/vendor/autoload.php';
use Lexdubyna\Blade\Blade;
$blade = new Blade( $plugin_dir .  '/views', $plugin_dir . '/cache' );
echo $blade->compileString( '<x-test />' );

The folder content is:
plugin.php
/cache
/views/components/test.blade.php
/views/test.blade.php

Is there something I'm missing here?

@Marvellous890
Copy link

@lexdubyna Where do we put our components? I am getting an error that App\View\Components\Alert not found

@lexdubyna
Copy link

@kaspost I have not yet tested x-components compiled from string. Will look into it.

@lexdubyna
Copy link

@Marvellous890 This is my test folders structure that works:

app
    Components
        MediaImage.php
views
    compiled
    components
        anonymous
            alert.php
        media-image.blade.php

and code:

$blade = new Lexdubyna\Blade\Blade(
    [get_template_directory() . '/views'],
    get_template_directory() . '/views/compiled'
);
$blade->compiler()->components([
    'media-image' => App\Components\MediaImage::class,
    'components.anonymous.alert' => 'alert'
]);

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

7 participants