laravel / folio

Page based routing for Laravel.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Will this work for regular php files?

inmanturbo opened this issue · comments

The view() helper can also be used to reach for plain vanilla (non-blade) .php files. Is there a way to do this with folio as well?

In the case where there may be any reason you want to preserve paths and/or don't need the extra compile step in some views.

EDIT:

I see where '.blade.php' is hard coded in the Match pipeline. Any plans to allow customizing or extending the pipeline, or any interest in a PR to that effect? In fact if the Pipeline and renderer could be extended, I can foresee a wide variety of use cases for other file types as well, including markdown and html.

Right now this does not work with vanilla PHP. But I'll bring this up internally. Can't provide guarantees however that we'll pursue this sorry. Thanks for your request!

Thanks for taking a look @driesvints!

This commit in a demo shows a naive bare minimum of what someone would have to do currently, to get this working on their own:

inmanturbo/folio-demo@a6e6f9b

It would be nice if the Laravel\Folio\Router simply called something like Folio::pipeline() (made up method) which by default would just return the array currently being used by the package, and if Folio exposed a public method, (for the sake of this example called withPipeline()) where one could (optionally) set a custom array as a property to be traversed in Laravel\Folio\Router::matchAtPath():

// Laravel\Folio\Router

    /**
     * Resolve the given URI via page based routing at the given mount path.
     */
    protected function matchAtPath(string $mountPath, Request $request, string $uri): ?MatchedView
    {
        $state = new State(
            uri: $uri,
            mountPath: $mountPath,
            segments: explode('/', $uri)
        );

        for ($i = 0; $i < $state->uriSegmentCount(); $i++) {
            $value = (new Pipeline)
                ->send($state->forIteration($i))
-                ->through([
-                   new EnsureNoDirectoryTraversal,
-                    new TransformModelBindings($request),
-                    new SetMountPathOnMatchedView,
-                    // ...
-                    new MatchRootIndex,
-                    new MatchDirectoryIndexViews,
-                    new MatchWildcardViewsThatCaptureMultipleSegments,
-                    new MatchLiteralDirectories,
-                    new MatchWildcardDirectories,
-                    new MatchLiteralViews,
-                    new MatchWildcardViews,
-                ])->then(fn () => new StopIterating);
+                ->through(Folio::pipeline())
+                ->then(fn () => new StopIterating);

            if ($value instanceof MatchedView) {
                return $value;
            } elseif ($value instanceof ContinueIterating) {
                $state = $value->state;

                continue;
            } elseif ($value instanceof StopIterating) {
                break;
            }
        }

        return null;
    }
//Laravel\Folio\FolioManager

public array $pipeline = [];

public function withPipeline(array $pipeline)
{
    $this->pipeline = $pipeline;
   
    return $this;
}

public function pipeline() : array
{
     return !empty($this->pipeline) ?
                  $this->pipeline :
                  [ 
                   // default pipeline array
                    new EnsureNoDirectoryTraversal,
                    new TransformModelBindings($request),
                    new SetMountPathOnMatchedView,
                    // ...
                    new MatchRootIndex,
                    new MatchDirectoryIndexViews,
                    new MatchWildcardViewsThatCaptureMultipleSegments,
                    new MatchLiteralDirectories,
                    new MatchWildcardDirectories,
                    new MatchLiteralViews,
                    new MatchWildcardViews,
                ];
}

which would give the option of passing custom array to the router in the service provider:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Laravel\Folio\Folio;

class FolioServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap services.
     */
    public function boot(): void
    {
        Folio::withPipeline([
                    new EnsureNoDirectoryTraversal,
                    new TransformModelBindings($request),
                    new SetMountPathOnMatchedView,
                    // ...
                    new \App\MatchPhpOrMarkdownRootIndex, // < --- custom class
                    new MatchDirectoryIndexViews,
                    new MatchWildcardViewsThatCaptureMultipleSegments,
                    new MatchLiteralDirectories,
                    new MatchWildcardDirectories,
                    new MatchLiteralViews,
                    new MatchWildcardViews,
        ])->route(resource_path('views/pages'), middleware: [
            '*' => [
                //
            ],
        ]);
    }
}