In the last section of this guide we created the pages module. We created some content, but besides that, there is not yet much to see.
We will make one small change to how our slug is generated. Besides that we will add 2 things to our page module:
If you look at the page in edit mode, you will notice that under the title there is a generated slug:
While in some cases this would be correct, for this one, we will need to change it. All our pages will be directly under the root of our website. We will also remove the language parameter as we will not implement it in this guide.
Open up the page controller app/Http/Controllers/Twill/PageController.php
and setup the controller:
1<?php 2 3namespace App\Http\Controllers\Twill; 4 5use A17\Twill\Http\Controllers\Admin\ModuleController as BaseModuleController; 6 7class PageController extends BaseModuleController 8{ 9 protected $moduleName = 'pages';10 11 /**12 * This method can be used to enable/disable defaults. See setUpController in the docs for available options.13 */14 protected function setUpController(): void15 {16 $this->setPermalinkBase('');17 $this->withoutLanguageInPermalink();18 }19}
We set our permalinkBase
to an empty string instead of letting it default to the name of our model which is pages
.
Then we add withoutLanguageInPermalink
to tell the controller to not use the language permalink.
Refresh the page and you now see that the slug is cleaned up.
These changes do not affect how the model's slug is stored in the database, it just changes the visual representation of it.
Model slugs are always saved purely based on the content you enter. If you enter 'example' in the url field when creating or editing the model, that is what will be saved.
The front-end is always responsible for handling the slugs.
Before we dive in, let's talk about how Twill approaches this, this is important to know how to link things up later.
In Twill we use crop configurations. For example (the default provided for all modules):
1'cover' => [ 2 'default' => [ 3 [ 4 'name' => 'default', 5 'ratio' => 16 / 9, 6 ], 7 ], 8 'mobile' => [ 9 [10 'name' => 'mobile',11 'ratio' => 1,12 ],13 ],14 'flexible' => [15 [16 'name' => 'free',17 'ratio' => 0,18 ],19 [20 'name' => 'landscape',21 'ratio' => 16 / 9,22 ],23 [24 'name' => 'portrait',25 'ratio' => 3 / 5,26 ],27 ],28],
We can see that our main array key is named "cover", that is our image role. This is just what we use to identify the field and purpose of the image.
Inside of that we have 3 additional array keys, these are our crop names. These are usually used to provide different variants of the image for different purposes, for example, one for desktop, one for mobile etc.. Other examples could be for a listing on the search results.
As you can see in the flexible key, there are 3 items. These can be used to let the content editor decide which of the 3 formats to use.
Depending on what we are working on, there are 2 places where we can set these up.
If you want to make a role available to all your modules, you can add the in the config/twill.php
file:
1<?php 2 3return [ 4 'default_crops' => [ 5 'page_cover' => [ 6 'default' => [ 7 [ 8 'name' => 'default', 9 'ratio' => 16 / 9,10 ]11 ]12 ]13 ]14];
But that may not always be the desired approach. If your image roles are more bound to your model we can add them in our models instead:
1<?php 2 3namespace App\Models; 4 5use A17\Twill\Models\Behaviors\HasBlocks;
6use A17\Twill\Models\Behaviors\HasTranslation; 7use A17\Twill\Models\Behaviors\HasSlug; 8use A17\Twill\Models\Behaviors\HasMedias; 9use A17\Twill\Models\Behaviors\HasRevisions;10use A17\Twill\Models\Model;11 12class Page extends Model13{14 use HasBlocks, HasTranslation, HasSlug, HasMedias, HasRevisions;15 16 protected $fillable = [
17 'published',18 'title',19 'description',20 ];21 22 public $translatedAttributes = [
23 'title',24 'description',25 ];26 27 public $slugAttributes = [
28 'title',29 ];30 31 public $mediasParams = [32 'cover' => [33 'default' => [34 [35 'name' => 'default',36 'ratio' => 16 / 9,37 ],38 ],39 'mobile' => [40 [41 'name' => 'landscape',42 'ratio' => 16 / 9,43 ],44 ],45 ],46 ];47}
Finally, there are roles specific to blocks, but we will get back to these later in the guide.
Now that we know this, we can decide on how to add our media field to our pages module.
For this guide, we do not have to create new crops as we will use the default cover
crop. But still it was important
to know about how they work for when you want to customize more!
Let's open up our module controller app/Http/Controllers/Twill/PageController.php
and add the field to the getForm
method.
Important note here, the name we give our field will also be used to match with our crop configuration. So make sure you always have a crop config for your field name!
1<?php 2 3namespace App\Http\Controllers\Twill; 4 5use A17\Twill\Models\Contracts\TwillModelContract; 6use A17\Twill\Services\Forms\Fields\Medias; 7use A17\Twill\Services\Listings\Columns\Text; 8use A17\Twill\Services\Listings\TableColumns; 9use A17\Twill\Services\Forms\Fields\Input;10use A17\Twill\Services\Forms\Form;11use A17\Twill\Http\Controllers\Admin\ModuleController as BaseModuleController;12 13class PageController extends BaseModuleController14{15 protected $moduleName = 'pages';16 17 public function getForm(TwillModelContract $model): Form18 {19 $form = parent::getForm($model);20 21 $form->add(22 Input::make()->name('description')->label('Description')->translatable()23 );24 25 $form->add(26 Medias::make()->name('cover')->label('Cover image')27 );28 29 return $form;30 }31}
Nice! We can now go back to a create or edit page for our page module and we should see the media field:
And when we actually attach a file we can see that the default crop configuration is being applied!
The final step we have to do is to add a block editor field. This will enable the drag-and-drop editor for our page!
The approach is the same.
We edit the module controller app/Http/Controllers/Twill/PageController.php
and add the field to the getForm
method.
1<?php 2 3namespace App\Http\Controllers\Twill; 4 5use A17\Twill\Models\Contracts\TwillModelContract; 6use A17\Twill\Services\Forms\Fields\BlockEditor; 7use A17\Twill\Services\Forms\Fields\Medias; 8use A17\Twill\Services\Listings\Columns\Text; 9use A17\Twill\Services\Listings\TableColumns;10use A17\Twill\Services\Forms\Fields\Input;11use A17\Twill\Services\Forms\Form;12use A17\Twill\Http\Controllers\Admin\ModuleController as BaseModuleController;13 14class PageController extends BaseModuleController15{16 protected $moduleName = 'pages';17 18 public function getForm(TwillModelContract $model): Form19 {20 $form = parent::getForm($model);21 22 $form->add(23 Input::make()->name('description')->label('Description')->translatable()24 );25 26 $form->add(27 Medias::make()->name('cover')->label('Cover image')28 );29 30 $form->add(31 BlockEditor::make()32 );33 34 return $form;35 }36}
Head over to the form once more and you will see that there is now a block editor at the bottom!
And that is about it for now! We have our page module, a media field for the cover image and a block editor.
In the next section we will create our own block!