|
| 1 | +--- |
| 2 | +navigation.priority: 1000 |
| 3 | +--- |
| 4 | + |
| 5 | +# The Extensions API |
| 6 | + |
| 7 | +## Introduction |
| 8 | + |
| 9 | +The Extensions API a powerful interface designed for package developers who want to extend the functionality of HydePHP. |
| 10 | + |
| 11 | +Using the API, you can hook directly into the HydePHP Kernel and extend sites with custom page types and new features. |
| 12 | + |
| 13 | +This documentation page functions heavily through examples, so it's recommended that the sections are read in order. |
| 14 | + |
| 15 | +### Prerequisites |
| 16 | + |
| 17 | +Before creating your extension, it will certainly be helpful if you first become familiar with |
| 18 | +the basic internal architecture of HydePHP, as well as how the auto-discovery system works, |
| 19 | +so you can understand how your code works with the internals. |
| 20 | + |
| 21 | +- [Core concepts overview](core-concepts) |
| 22 | +- [Architecture concepts](architecture-concepts) |
| 23 | +- [Autodiscovery](autodiscovery) |
| 24 | + |
| 25 | +### The why and how of the Extensions API |
| 26 | + |
| 27 | +HydePHP being a static site generator, the Extensions API is centered around [Page Models](page-models), |
| 28 | +which you are hopefully already familiar with, otherwise you should read up on them first. |
| 29 | + |
| 30 | +What the Extensions API does is to allow you to create custom page types, and tell HydePHP how to discover them. |
| 31 | +This may sound like a small thing, but it's actually incredibly powerful as the page models are the foundation |
| 32 | +of HydePHP's functionality. They tell the system how to discover pages, how to render them, |
| 33 | +and how they interact with the site. |
| 34 | + |
| 35 | +Any other functionality you want to add to HydePHP, such as new commands or configuration options, |
| 36 | +can be added the same way as you would in Laravel, and are thus not part of our API. |
| 37 | +See the [Laravel package development guide](https://laravel.com/docs/10.x/packages) for more. |
| 38 | + |
| 39 | + |
| 40 | +## Creating your Extension class |
| 41 | + |
| 42 | +The entry-point for your extension is your Extensions class. Within this, you can register the custom page classes. |
| 43 | +If needed, you can also register discovery handlers which can run custom logic at various parts of the boot process. |
| 44 | + |
| 45 | +In this article we will create an extension that registers a new type of page, a `JsonPageExtension`. |
| 46 | + |
| 47 | +The first step is to create a class that extends the `HydeExtension` class: |
| 48 | + |
| 49 | +```php |
| 50 | +use Hyde\Foundation\Concerns\HydeExtension; |
| 51 | + |
| 52 | +class JsonPageExtension extends HydeExtension { |
| 53 | + // |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +In here, we will register our extension class name in the `getPageClasses` method: |
| 58 | + |
| 59 | +```php |
| 60 | +class JsonPageExtension extends HydeExtension { |
| 61 | + public static function getPageClasses(): array { |
| 62 | + return [ |
| 63 | + JsonPage::class, |
| 64 | + ]; |
| 65 | + } |
| 66 | +} |
| 67 | +``` |
| 68 | + |
| 69 | +Hyde will then use the information from the `JsonPage` class to automatically discover the pages when booting the Kernel. |
| 70 | +For example, if you specify the file extension and source directory, that is all Hyde needs to know to discover the pages. |
| 71 | + |
| 72 | +If our pages need more complex discovery logic, we can create custom handlers. so let's take a quick look at that next. |
| 73 | + |
| 74 | +### Discovery handlers |
| 75 | + |
| 76 | +The discovery handlers lets you run code at various points of the booting process. This is usually only needed if your |
| 77 | +page models cannot provide the information required for Hyde run the standard auto-discovery, and thus need custom logic. |
| 78 | + |
| 79 | +Usually in these cases, you would only need to add files to the Kernel `FileCollection`, |
| 80 | +though the `HydeExtension` class offers following three discovery handlers, in case you need them: |
| 81 | + |
| 82 | +```php |
| 83 | +/** Runs during file discovery */ |
| 84 | +public function discoverFiles(FileCollection $collection): void; |
| 85 | + |
| 86 | +/** Runs during page discovery */ |
| 87 | +public function discoverPages(PageCollection $collection): void; |
| 88 | + |
| 89 | +/** Runs during route discovery */ |
| 90 | +public function discoverRoutes(RouteCollection $collection): void; |
| 91 | +``` |
| 92 | + |
| 93 | +Any of these can be implemented in your extension class, and they will be called during the discovery. As you can see, |
| 94 | +the instance of the discovery collection is injected into the method for you to interact with. |
| 95 | + |
| 96 | +#### Discovery handler example |
| 97 | + |
| 98 | +Let's go crazy and implement a discovery handler to collect `JsonPage` files from an external API! We will do this |
| 99 | +by implementing the `discoverPages` method in our extension class, and from there inject pages retrieved from our API. |
| 100 | + |
| 101 | +```php |
| 102 | +class JsonPageExtension extends HydeExtension { |
| 103 | + public function discoverPages(PageCollection $collection): void { |
| 104 | + $pages = Http::get('https://example.com/my-api')->collect(); |
| 105 | + |
| 106 | + $pages->each(function (array $page) use ($collection): void { |
| 107 | + $collection->addPage(JsonPage::fromArray($page)); |
| 108 | + }); |
| 109 | + } |
| 110 | +} |
| 111 | +``` |
| 112 | + |
| 113 | +Since the discovery steps are handled sequentially, the added pages will automatically be discovered as routes without |
| 114 | +us having to implement that handler method. As we inject the page objects directly, we bypass the need of the `FileCollection`. |
| 115 | + |
| 116 | + |
| 117 | +## Registering your extension |
| 118 | + |
| 119 | +Now that we have our extension class, we need to register it with HydePHP. |
| 120 | + |
| 121 | +It's important that your class is registered before the HydeKernel boots. Therefore, an excellent place for this is the |
| 122 | +`register` method of your extensions service provider, where you call the `registerExtension` method of the `HydeKernel` |
| 123 | +singleton instance, which you can access via the `Hyde\Hyde` facade, or via the service container. |
| 124 | + |
| 125 | +```php |
| 126 | +use Hyde\Hyde; |
| 127 | +use Hyde\Foundation\HydeKernel; |
| 128 | +use Illuminate\Support\ServiceProvider; |
| 129 | + |
| 130 | +class JsonPageExtensionServiceProvider extends ServiceProvider { |
| 131 | + public function register(): void { |
| 132 | + // Via the service container: |
| 133 | + $this->app->make(HydeKernel::class)->registerExtension(JsonPageExtension::class); |
| 134 | + |
| 135 | + // Or via the facade: |
| 136 | + Hyde::registerExtension(JsonPageExtension::class); |
| 137 | + } |
| 138 | +} |
| 139 | +``` |
| 140 | + |
| 141 | +### Packaging your extension |
| 142 | + |
| 143 | +To make your extension available to other HydePHP users, you can make it into a [Composer](https://getcomposer.org/) package, |
| 144 | +and publish it to [Packagist](https://packagist.org/) for others to install. |
| 145 | + |
| 146 | +If you register your service provider in your package's `composer.json` file, your extension automatically be enabled when |
| 147 | +the package is installed in a HydePHP project! |
| 148 | + |
| 149 | +```json |
| 150 | +{ |
| 151 | + "extra": { |
| 152 | + "laravel": { |
| 153 | + "providers": [ |
| 154 | + "My\\Namespace\\JsonPageExtensionServiceProvider" |
| 155 | + ] |
| 156 | + } |
| 157 | + } |
| 158 | +} |
| 159 | +``` |
| 160 | + |
| 161 | +### Telling the world about your extension |
| 162 | + |
| 163 | +Next up, why not send us a Tweet at [@HydeFramework](https://twitter.com/HydeFramework) and tell us about your extension, |
| 164 | +so we can feature it? |
0 commit comments