# Blueprints Source: https://runway.duncanmcclean.com/blueprints Blueprints are a key component to Statamic's content modeling process. They let you define the fields available in the Control Panel and how your data is stored. ## Creating & managing blueprints Every resource will have it's own blueprint. Just like with collections, you can manage the blueprints in the Control Panel. Runway blueprints in the Control Panel When configuring fields, make sure that the field handles in your blueprint should match up *exactly* with the column names in the database, otherwise bad things will happen. You'll also want to ensure the database column type matches the fieldtype you're trying to use (see [Supported Fieldtypes](#supported-fieldtypes)). ## Supported Fieldtypes Runway supports pretty much ALL fieldtypes available in Statamic, including Bard. As long as you have the correct fieldtype and the correct column type, everything should "just work"! For simplicity, here's a table matching Statamic's Core fieldtypes with the correct column types: | **Fieldtype** | **Column Type** | **Notes** | | ------------------------------------------------------------ | ------------------------- | -------------------------------------------------------------------------------------------- | | [Array](https://statamic.dev/fieldtypes/array) | `json` | | | Asset Container | `string`/`json` | | | [Assets](https://statamic.dev/fieldtypes/assets) | `string`/`json` | | | [Bard](https://statamic.dev/fieldtypes/bard) | `string`/`json` | If 'Display HTML' is `true`, then Bard will save as a `string`. | | [Button Group](https://statamic.dev/fieldtypes/button_group) | `string` | | | [Checkboxes](https://statamic.dev/fieldtypes/checkboxes) | `json` | | | [Code](https://statamic.dev/fieldtypes/code) | `string` | | | [Collections](https://statamic.dev/fieldtypes/collections) | `string`/`json` | If 'Max items' is `1`, column type should be `string`. Otherwise, `json` is what you want. | | [Color](https://statamic.dev/fieldtypes/color) | `string` | | | [Date](https://statamic.dev/fieldtypes/date) | `string`/`range` | Format is specified field configuration options. Ranges are should be stored as json. | | [Dictionary](https://statamic.dev/fieldtypes/dictionary) | `string`/`json` | If 'Max items' is `1`, column type should be `string`. Otherwise, `json` is what you want. | | [Entries](https://statamic.dev/fieldtypes/entries) | `string`/`json` | If 'Max items' is `1`, column type should be `string`. Otherwise, `json` is what you want. | | [Form](https://statamic.dev/fieldtypes/form) | `string`/`json` | If 'Max items' is `1`, column type should be `string`. Otherwise, `json` is what you want. | | [Grid](https://statamic.dev/fieldtypes/grid) | `json` | | | [Group](https://statamic.dev/fieldtypes/group) | `json` | | | [Hidden](https://statamic.dev/fieldtypes/hidden) | `string` | | | [HTML](https://statamic.dev/fieldtypes/html) | - | UI only | | [Icon](https://statamic.dev/fieldtypes/icon) | `string` | | | [Integer](https://statamic.dev/fieldtypes/integer) | `integer` | | | [Link](https://statamic.dev/fieldtypes/link) | `json` | | | [List](https://statamic.dev/fieldtypes/list) | `json` | | | [Markdown](https://statamic.dev/fieldtypes/markdown) | `string` | | | [Navs](https://statamic.dev/fieldtypes/navs) | `string`/`json` | | | [Radio](https://statamic.dev/fieldtypes/radio) | `string` | | | [Range](https://statamic.dev/fieldtypes/range) | `string` | | | [Replicator](https://statamic.dev/fieldtypes/replicator) | `json` | | | [Revealer](https://statamic.dev/fieldtypes/revealer) | - | UI only | | [Section](https://statamic.dev/fieldtypes/section) | - | UI only | | [Select](https://statamic.dev/fieldtypes/select) | `string`/`integer`/`json` | | | [Sites](https://statamic.dev/fieldtypes/sites) | `string`/`json` | | | [Slug](https://statamic.dev/fieldtypes/slug) | `string` | | | [Spacer](https://statamic.dev/fieldtypes/spacer) | - | UI only | | [Structures](https://statamic.dev/fieldtypes/structures) | `json` | | | [Table](https://statamic.dev/fieldtypes/table) | `json` | | | [Tags](https://statamic.dev/fieldtypes/tags) | `json` | | | [Taxonomies](https://statamic.dev/fieldtypes/taxonomies) | `string`/`json` | | | [Template](https://statamic.dev/fieldtypes/template) | `string` | | | [Terms](https://statamic.dev/fieldtypes/terms) | `string`/`json` | | | [Text](https://statamic.dev/fieldtypes/text) | `string` | | | [Textarea](https://statamic.dev/fieldtypes/textarea) | `string` | | | [Time](https://statamic.dev/fieldtypes/time) | `string` | | | [Toggle](https://statamic.dev/fieldtypes/toggle) | `boolean` | | | [User Groups](https://statamic.dev/fieldtypes/user-groups) | `string`/`json` | When the resource is the `User` model, you don't need to create a column for this fieldtype. | | [User Roles](https://statamic.dev/fieldtypes/user-roles) | `string`/`json` | When the resource is the `User` model, you don't need to create a column for this fieldtype. | | [Users](https://statamic.dev/fieldtypes/users) | `string`/`integer`/`json` | | | [Video](https://statamic.dev/fieldtypes/video) | `string` | | | [Width](https://statamic.dev/fieldtypes/width) | `integer` | | | [YAML](https://statamic.dev/fieldtypes/yaml) | `string` | | ## Eloquent Relationships Runway provides two fieldtypes to let you manage Eloquent Relationships within Statamic: * Belongs To * Has Many To find out more about Runway's fieldtypes, check out the [Fieldtypes](/fieldtypes) page. ## Validation Since Runway stores data in the database, you can use Laravel's standard validation rules directly in your blueprints. For example, Statamic's flat-file storage doesn't support the `unique` validation rule since there's no database to query. With Runway, you can use it just like you would in a regular Laravel application: ```yaml theme={null} - handle: email field: type: text display: Email validate: - required - email - 'unique:users,email,{id}' ``` When editing existing models, you'll want to exclude the current model from the uniqueness check. Runway will automatically substitute `{id}` (or whatever your model's primary key is) with the current model's ID during validation. ## Nesting fields inside JSON columns To avoid needing to create a migration for every new field you add to a blueprint, fields can be stored within JSON columns. To do this, you'll first need to configure the JSON column under the `nested_field_prefixes` key in your `config/runway.php` config file. ```php theme={null} 'resources' => [ Order::class => [ 'nested_field_prefixes' => [ // [!code ++] 'address', // [!code ++] ], // [!code ++] ], ], ``` Then, when you're adding fields to your blueprint, simply prefix the column name, like shown below, and Runway will be smart enough to read/write from your JSON column. 🧠 ```yaml theme={null} - handle: address_street_name # Represents the street_name key, in the address column. field: type: text display: 'Street Name' ``` **Heads up!** In order for Nested Fields to work, you'll need to define a cast for the JSON column in your Eloquent model. ```php theme={null} protected function casts(): array { return [ 'address' => 'array', // or 'json', AsArrayObject::class ]; } ``` ## Computed Values Runway supports the concept of [computed values](https://statamic.dev/content-modeling/computed-values). However, unlike in core, where they're defined in your `AppServiceProvider`, you define computed values in Runway by adding accessors to your Eloquent model. For example: if you have `first_name` and `last_name` fields, you may want a computed value to combine them, so you might do something like this: ```php theme={null} use Illuminate\Database\Eloquent\Casts\Attribute; public function fullName(): Attribute { return Attribute::make( get: function () { return "{$this->first_name} {$this->last_name}"; } ); } ``` In order for augmentation to work properly, model accessors should be `public` functions. Then, in the resource's blueprint, set the field's visibility to "Computed": Field's visibility set to computed Computed values can't be searched, sorted or filtered due to them being computed *after* the query has been executed. # Control Panel Source: https://runway.duncanmcclean.com/control-panel Runway creates listing and publish forms for your Eloquent models, allowing you to manage them just like you would with entries. One of Runway’s core features is the Control Panel integration. Runway will create listing and publish form pages for each of your resources. Screenshot of Control Panel Listing View The Control Panel functionality is built to work in exactly the same way you’d expect with entries. You can set filters, define scopes and use custom actions. ## Disable Control Panel functionality Technically, you can’t fully disable Runway’s CP feature. However, what you can do is hide the Nav Item from the Control Panel. ```php config/runway.php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'hidden' => true, ], ], ``` ## Permissions Screenshot of Runway's User Permissions If you have other users who are not 'super users', you may wish to also give them permission to view/create/update specific resources. Runway gives you granular control over which actions users can/cannot do for each of your resources. ### Permission labels You may customize permission labels by adding a `resources/lang/{lang}/runway.php` file. ```php resources/lang/pt_BR/runway.php theme={null} 'permissions' => [ 'create' => 'Criar :resource', 'delete' => 'Excluir :resource', 'edit' => 'Editar :resource', 'view' => 'Visualizar :resource' ] ``` In the example above, `:resource` will be replaced by the resource's `name`. ### Custom permissions If you need to, you can add new permissions to the existing ones created by Runway: ```php app/Providers/AppServiceProvider.php theme={null} public function boot() { Permission::group('Runway', function () { foreach (Runway::allResources() as $resource) { Permission::get("edit {$resource->handle()}")->addChild( Permission::make("edit other owners {$resource->handle()}") ->label(trans('runway.permissions.edit_other_owners_resource', [ 'resource' => $resource->name() ])) ); } }); } ``` ## Authorization If you need to, you can change how resource actions are authorized by extending and rebinding the `ResourcePolicy` class. ```php app/Policies/ResourcePolicy.php theme={null} app->bind(RunwayResourcePolicy::class, ResourcePolicy::class); } ``` ## Actions Runway supports using [Statamic Actions](https://statamic.dev/extending/actions#content) to perform tasks on your models. You may register your own custom actions, as per the Statamic documentation. If you wish to only show an action on one of your models, you can filter it down in the `visibleTo` method. ```php theme={null} use App\Models\Post; class YourCustomAction extends Action { public function visibleTo($item) { return $item instanceof Post; } } ``` ## Filters Runway provides a "Fields" filter to filter models in the Control Panel based on blueprint fields. Control Panel Filters You can create your own filters using [query scopes and filters](https://statamic.dev/extending/query-scopes-and-filters#filters). To make your filter visible in a Runway resource, specify it in `visibleTo` method, specifying the context of the resource and the key as 'runway'. ```php theme={null} /** * Determine when the filter is shown. * * @param string $key * @return bool */ public function visibleTo($key) { return $key === 'runway' && $this->context['resource'] === 'product'; } ``` ## Scoping Control Panel Results If you don't want to return everything, you may add a scope (`runwayListing`) to limit the returned results. ```php focus={7-11} theme={null} use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class YourModel extends Model { #[Scope] protected function runwayListing(Builder $query): void { $query->where('something', true); } } ``` ### Scoping search results On top of scoping your Control Panel results, you may also scope how Runway searches your models. To do this, you may specify a `runwaySearch` scope. ```php focus={7-11} theme={null} use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class YourModel extends Model { #[Scope] protected function runwaySearch(Builder $query, string $searchTerm): void { // Your own search logic } } ``` ## Widget Runway provides a widget, allowing you to display a list of models from a resource on the Control Panel dashboard. You can configure it in `config/statamic/cp.php`: ```php theme={null} // config/statamic/cp.php 'widgets' => [ [ 'type' => 'runway_resource', 'resource' => 'product', 'limit' => 10, ], ], ``` ### Options * `resource`: The resource's handle **(required)**. * `width`: Width of dashboard area as a percentage. Accepts `25`, `33`, `50`, `66`, `75` and `100`. * `sites`: Determines the sites in which this widget should be displayed. * `limit`: Limit number of entries. Defaults to `5`. * `sort`: Sort and order by field name. E.g. `''title:desc''`. Defaults to the resources''s settings. * `fields`: An array of field handles to be displayed as columns in the widget. * `title`: The title of the widget. Defaults to the resource name. # Front-end Routing Source: https://runway.duncanmcclean.com/frontend-routing Runway can serve up your Eloquent models on the front-end of your site, just like entries. ## Enabling Before getting started, ensure you’ve run `php artisan migrate`. Runway comes with a `runway_uris` table which will be used to store all of the front-end URIs. First things first, add a `route` key to your resource config, with the URI structure you want to use. Feel free to use Antlers in there for anything dynamic, like a slug or a date. ```php config/runway.php theme={null} 'route' => '/products/{{ slug }}', ``` Next, add the `RunwayRoutes` trait to your Eloquent model. ```php theme={null} use StatamicRadPack\Runway\Routing\Traits\RunwayRoutes; class Product extends Model { use RunwayRoutes; ``` If you have any existing models, make sure you run `php please runway:rebuild-uris` to build the ["URIs cache"](#content-uri-cache) Runway uses to map models to URIs. ## Customising the template/layout used Runway will assume you want to use the `default` template and the `layout` layout for resources. However, most of the time, you’ll want to change this. To change it, just specify what you want to change them to. ```php config/runway.php theme={null} 'template' => 'products.index', 'layout' => 'layouts.shop', ``` ## Available variables Instead your show/detail view of your model, you’ll have access to a bunch of variables: * All fields configured in your blueprint (with augmentation of course) * Any fields not in your blueprint but configured in your model, like `created_at`, `updated_at`. * Any other variables provided by [the Cascade](https://statamic.dev/cascade#content) ## Static Caching Invalidation If you're taking advantage of Statamic's [Static Caching](https://statamic.dev/static-caching) functionality, Runway will automatically invalidate the URI of your models on save. You may also configure additional URIs to be invalidated on save. ```php theme={null} // config/statamic/static_caching.php 'invalidation' => [ 'class' => null, 'rules' => [ 'runway' => [ 'product' => [ 'urls' => [ '/products', '/products/*', ], ], ], ], ], ``` ## URI Cache Since Runway allows you to define your routes using Antlers, much like collections, Runway needs to index all the possible URIs so it can efficiently find the related Eloquent model. Runway uses the `runway_uris` table to do this. Unless disabled, your application will have a `runway_uris` table, which is responsible for mapping URIs to Eloquent models. Anytime you create, update or delete an Eloquent model, Runway will update its mappings in the `runway_uris` table. ### Building the URI Cache When configuring front-end routing in an application with existing models, you should run the `php please runway:rebuild-uris` command to build the Runway's "URI Cache". If you wish to limit the models being "cached" by the `runway:rebuild-uris` command, you may add the `runwayRoutes` query scope to your model: ```php focus={7-11} theme={null} use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class Product extends Model { #[Scope] protected function scopeRunwayRoutes(Builder $query): void { $query->where('is_public', true); } } ``` ### Customizing the table name By default, Runway will use the `runway_uris` table to store the "URI Cache". If you wish to change the name of the table, you may do so in the `runway.php` configuration file: ```php theme={null} /* |-------------------------------------------------------------------------- | Runway URIs Table |-------------------------------------------------------------------------- | | When using Runway's front-end routing functionality, Runway will store model | URIs in a table to enable easy "URI -> model" lookups. If needed, you can | customize the table name here. | */ 'uris_table' => 'runway_uris', ``` ## Live Preview Statamic's Live Preview gives you the ability to see what your model will look like in real time as you write and edit. By default, you'll be able to preview your model at your resource's configured route. However, you are free to customize the available preview targets, just like you can with collections. ```php theme={null} // config/runway.php 'preview_targets' => [ ['label' => 'Model', 'url' => '{permalink}'], ['label' => 'Index', 'url' => '/products'] ], ``` You may use the model's variables in the URL, just like defining a route. You can learn more about preview targets in the [Statamic documentation](https://statamic.dev/live-preview#preview-targets). # GraphQL API Source: https://runway.duncanmcclean.com/graphql Integrates with Statamic's GraphQL API, bringing you yet another way to query your Eloquent models. GraphQL is an awesome way to fetch just the right information you need from your backend. It's commonly used in 'headless' environments. Statamic includes a read-only [GraphQL API](https://statamic.dev/graphql) out of the box. Runway extends upon this so you can query your Eloquent models. ## Enabling for resources GraphQL must be enabled for each of the resources you wish to query. It's as simple as adding to your config: ```php config/runway.php theme={null} 'resources' => [ \App\Models\Product::class => [ 'name' => 'Products', 'blueprint' => 'product', 'graphql' => true, ], ], ``` You must also ensure you have [GraphQL enabled](https://statamic.dev/graphql#enable-graphql) in Statamic as well for it to be available to you. ## Queries For each resource, there's two kinds of queries you can do. An 'index' query and a 'show' query: ### Index Query Example of an index query: ```graphql theme={null} { products { data { id name price description } } } ``` An index query also allows for pagination between results, you can read up more on that in the [Statamic Documentation](https://statamic.dev/graphql#pagination). ### Show Query Example of a show query: ```graphql theme={null} { products(id: "2") { id name price description } } ``` ## Relationships If you're using the 'Belongs To' or 'Has Many' fieldtypes provided by Runway, you can also query the related models. ```graphql theme={null} { product(id: "2") { id name brand { id name created_at updated_at } } } ``` Notice that in the above example, we have a 'Belongs To' fieldtype which we're querying as simply `brand`, instead of `brand_id`. Runway removes the `_id` for you so you can build a nice, clean query. ## Filtering and Sorting You may also filter & sort results the same way you would with the built-in queries. [Review the Statamic Docs](https://statamic.dev/graphql#filtering). # Multi-site Source: https://runway.duncanmcclean.com/guides/multisite Learn how to use Runway with Statamic's multi-site feature. Out of the box, Runway doesn't come with multisite support as Runway doesn't assume anything about how your models are created. However, there is an easy way to scope the model results you get to only those related to the currently selected site. 1. Add a column to your model that'll contain a site handle. 2. Once created, add the following scope to your model. Be sure to change `site` to the handle of the column you just created. ```php focus={6-10} theme={null} // app/Models/Post.php use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; #[Scope] protected function runwayListing(Builder $query): void { $query->where('site', Site::selected()->handle()); } ``` 3. Now, when you go to your model's listing page, the returned results should relate to the currently selected site. ## Localisations Sorry, Runway doesn't support creating localisations of models as we've built Runway to be as unopinionated as possible, which introducing this feature would go against. # Introduction Source: https://runway.duncanmcclean.com/index Eloquently manage your Eloquent models in Statamic with Runway. Get up and running with Runway in your Statamic site. Learn more about Resources, the core concept behind Runway. ## Control Panel integration Runway fits right into the Control Panel - enabling you to create, edit and view your models. In most cases, you'll not notice the difference between an entry in the CP and an Eloquent model in the CP. * [Review documentation](/control-panel) ## Front-end routing Need to show your models on the front-end of your site? No problem - Runway's got that under control. Simply tell Runway the route you'd like to use and it'll serve up the front-end for you. ```php config/runway.php theme={null} return [ 'resources' => [ \App\Models\Product::class => [ 'route' => '/products/{{ slug }}', ], ], ]; ``` * [Review documentation](/frontend-routing) ## Antlers templating In addition to front-end routing, you may also use Runway's tag to loop through your models and display the results. The tag supports filtering, using Eloquent scopes and sorting. ```antlers theme={null} {{ runway:product }}

{{ name }}

Price: {{ price }}

{{ /runway:product }} ``` * [Review documentation](https://runway.duncanmcclean.com/templating) ## GraphQL API If you're a GraphQL fan, you're now able to fetch your models via GraphQL. Runway will augment the fields just like you'd expect. ```graphql theme={null} { products(limit: 25, sort: "name") { data { id name price description } } } ``` ## REST API If you don't like GraphQL and would prefer plain old REST, you can do that too. Runway easily integrates with Statamic's REST API. ```php config/runway.php theme={null} 'resources' => [ 'collections' => true, // ... 'runway' => [ 'product' => true, ], ], ``` ## Search Runway integrates with Statamic's [Search](https://statamic.dev/search) feature, allowing you to search your Eloquent models in the Control Panel and via the `{{ search:results }}` tag. It's just as simple as adjusting your config file. ```php config/statamic/search.php theme={null} 'indexes' => [ 'myindex' => [ 'driver' => 'local', 'searchables' => ['collection:blog', 'runway:order'], ], ], ``` # Installation Source: https://runway.duncanmcclean.com/installation How to install and configure Runway in your Statamic project. ## System Requirements * Statamic 5 * Laravel 10 or above * PHP 8.2 or above ## Installing via Composer First, you need to install Runway as a Composer dependency: ```sh theme={null} composer require statamic-rad-pack/runway ``` Next, publish the configuration file: ```sh theme={null} php artisan vendor:publish --tag="runway-config" ``` The configuration file will have been published as `config/runway.php`. Now that everything's installed & published, you'll want to [configure Runway Resources](/resources) for each of the models you wish to be editable in Runway. # Relationships Source: https://runway.duncanmcclean.com/relationships Relationships are an important part of any web application. Runway provides a way to manage Eloquent relationships within Statamic. ## Belongs To Runway provides a dedicated fieldtype to manage [`belongsTo`](https://laravel.com/docs/master/eloquent-relationships#one-to-many-inverse) relationships within Statamic. ```php theme={null} belongsTo(Author::class); } } ``` ```yaml theme={null} - handle: author_id field: type: belongs_to display: Author resource: author ``` You should make sure that the field handle matches the column name in the database. ### Templating In Antlers, you can access any of the fields on the model. They'll be [augmented](https://statamic.dev/extending/augmentation) using the resource's blueprint. ```antlers theme={null} Written by {{ author:first_name }} {{ author:last_name }} ({{ author:location }}) ``` ### Options | **Option** | **Description** | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `mode` | Set the UI style for this field. Can be one of 'default' (Stack Selector), 'select' (Select Dropdown) or 'typeahead' (Typeahead Field). | | `resource` | Specify the Runway Resource to be used for this field. | | `relationship_name` | The name of the Eloquent Relationship this field should use. When left empty, Runway will attempt to guess it based on the field's handle. | | `create` | By default you may create new models. Set to `false` to only allow selecting from existing models. | | `with` | Specify any relationships you want to be eager loaded when this field is augmented. This option accepts an array of relationships. | | `title_format` | Configure the title format used for displaying results in the fieldtype. You can use Antlers to pull in model data. | | `query-scopes` | Allows you to specify a [query scope](https://statamic.dev/extending/query-scopes-and-filters#scopes) which should be applied when retrieving selectable models. You should specify the query scope's handle, which is usually the name of the class in snake case. For example: `MyAwesomeScope` would be `my_awesome_scope`. | ## Has Many Runway provides a dedicated fieldtype to manage [`hasMany`](https://laravel.com/docs/master/eloquent-relationships#one-to-many) relationships within Statamic. ```php theme={null} hasMany(Post::class); } } ``` ```yaml theme={null} - handle: posts field: type: has_many display: Posts resource: post ``` You should ensure that the field handle matches the name of the Eloquent relationship in your model (the method name). ### Templating Loop through the models and do anything you want with the data. ```antlers theme={null} ``` ### Options | **Option** | **Description** | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `mode` | Set the UI style for this field. Can be one of 'default' (Stack Selector), 'select' (Select Dropdown) or 'typeahead' (Typeahead Field). | | `resource` | Specify the Runway Resource to be used for this field. | | `relationship_name` | The name of the Eloquent Relationship this field should use. When left empty, Runway will attempt to guess it based on the field's handle. | | `create` | By default you may create new models. Set to `false` to only allow selecting from existing models. | | `with` | Specify any relationships you want to be eager loaded when this field is augmented. This option accepts an array of relationships. | | `title_format` | Configure the title format used for displaying results in the fieldtype. You can use Antlers to pull in model data. | | `reorderable` | Determines whether the models can be reordered. Defaults to `false`. | | `order_column` | When reordering is enabled, this determines which column should be used for storing the sort order. When the relationship uses a pivot table, the order column must exist on the pivot table. | | `query-scopes` | Allows you to specify a [query scope](https://statamic.dev/extending/query-scopes-and-filters#scopes) which should be applied when retrieving selectable models. You should specify the query scope's handle, which is usually the name of the class in snake case. For example: `MyAwesomeScope` would be `my_awesome_scope`. | ## Belongs To Many The Has Many fieldtype is also compatible with [`belongsToMany`](https://laravel.com/docs/master/eloquent-relationships#many-to-many) relationships. You can use the Has Many fieldtype on both sides of the relationship. ```php theme={null} belongsToMany(Post::class); } } ``` ```yaml theme={null} - handle: posts field: type: has_many display: Posts resource: post ``` You should ensure that the field handle matches the name of the Eloquent relationship in your model (the method name). For more information on templating with the Has Many fieldtype and the config options available, see the [Has Many](#content-has-many) section. ## Polymorphic Relationships Runway doesn't currently support Polymorphic relationships out of the box, since they can get pretty complicated. If you need it, please [upvote this feature request](https://github.com/statamic-rad-pack/runway/discussions/245). # Resources Source: https://runway.duncanmcclean.com/resources Resources are a core part of Runway. They tell Runway about your Eloquent models and how you'd like them to be managed. ## What are resources? For each of the Eloquent models you wish to use with Runway, you’ll need to define a ‘resource’. A resource basically tells Runway about the model and how you’d like it to be configured - which blueprint to use, whether it should be manageable in the CP, etc. ## Defining resources There are three steps involved in defining a resource: Add the resource to Runway's config file. The key should be the model, and the value should be an array of configuration options: ```php config/runway.php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', ], ], ``` Add the `HasRunwayResource` trait to your Eloquent model: ```php app/Models/Order.php theme={null} use StatamicRadPack\Runway\Traits\HasRunwayResource; // [!code ++] class Order extends Model { use HasRunwayResource; // [!code ++] } ``` Finally, you can start adding fields to your resource's blueprint. To learn more about using Blueprints in Runway, please review the [Blueprints](/blueprints) page. If you're moving a collection to the database, use the `php please runway:import-collection` command. It'll help you set up everything you need, including moving your entries to the database. ## Configuring resources There’s about a dozen configuration options available for resources, they are all documented below. ### Hidden By default, Runway provides a Control Panel interface for managing your models. If you’d like to hide the CP Nav Item that’s registered for this model, just say so: ```php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'hidden' => true, ], ], ``` This will only hide the resource from the Control Panel navigation, the page will still be accessible via its URL if you know where to look. If you want to prevent access to the resource entirely, use [permissions](/control-panel#permissions) instead. ### Route If you want to take advantage of Runway’s front-end routing abilities, you can pass in a `route` to enable it. Your `route` can include Antlers code - the variables available are driven by the resource’s blueprint. ```php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'route' => '/my-orders/{{ id }}', ], ], ``` ### Templates & Layouts You may also specify the `template` and `layout` you want to use when front-end routing. ```php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'route' => '/my-orders/{{ id }}', 'template' => 'orders.show', 'layout' => 'default', ], ], ``` ### Read Only You may also specify if you want a resource to be 'read only' - eg. users will not be able to create models and when editing, all fields will be marked as read only and no save button will be displayed. ```php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'read_only' => true, ], ], ``` ### Duplicatable By default, Runway allows models to be duplicated via the Duplicate action in the Control Panel. You can disable this for a resource by setting `duplicatable` to `false`. ```php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'duplicatable' => false, ], ], ``` ### Ordering Sometimes you may want to change the order that your models are returned in the Control Panel listing table. You can use the `order_by` and `order_by_direction` configuration options to tell Runway the order you wish models to be returned. ```php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', // In this case, orders will the highest total will be displayed first. 'order_by' => 'total', 'order_by_direction' => 'DESC', ], ], ``` ### Title field When Runway displays models inside inside the Control Panel (eg. in relationship fields, in search), it'll default to showing the first listable field it can find, based on your blueprint. If you'd like to specify a different field, you may do so by setting the `title_field` option on your resource. ```php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'title_field' => 'name', ], ], ``` ### Search Index The `search_index` option allows you to specify a [search index](https://statamic.dev/search#indexes) which should be used when search models in the Control Panel listing table. ```php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'search_index' => 'my_search_index', ], ], ``` ### Eager Loading To help with performance, Runway will automatically ["eager load"](https://laravel.com/docs/master/eloquent-relationships#eager-loading) any Eloquent relationships it knows about based on the fields you've defined in your blueprint. However, if you wish, you can override the relationships that get eager loaded by providing the `with` option on your resource: ```php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'with' => ['lineItems', 'customer'], ], ], ``` ### Publish States If you're writing content that you would like to be able to store without publishing right away, you can add the `published` config option to your resource's config array. It'll allow you to have published & unpublished models, with all of the status indicators and filtering you'd expect. ```php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'published' => true, // Assumes the model has a `published` boolean column. 'published' => 'is_active', // Otherwise, you can specify the column name. ], ], ``` By default, it'll use a `published` column in the database to keep track of the model's "status". You're free to change the name of this column as needed. Runway **won't** automatically add this database column for you, you will need to add it yourself: ```php theme={null} Schema::table('products', function (Blueprint $table) { $table->boolean('published'); }); ``` ### Prevent creating new models If you want to prevent new models being created via the Control Panel, you can mark the resource's blueprint as "Hidden": ```yaml theme={null} hide: true ``` ## Actions In much the same way with entries, you can create custom Actions which will be usable in the listing tables provided by Runway. You can register them in the same way as you normally would. The only thing that’s different is the fact that instead of filtering down to just `Entry` objects for example, you can filter by your model, like `Order`. ```php theme={null} use App\Models\Order; public function visibleTo($item) { return $item instanceof Order; } ``` ## Queries Every query made by Runway to your model will call the `runway` query scope. This allows you to easily filter the models returned by Runway. ```php focus={7-11} theme={null} use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class YourModel extends Model { #[Scope] protected function runway(Builder $query): void { $query->where('something', true); } } ``` If you only want to filter models returned in the Control Panel, see the `runwayListing` and `runwaySearch` scopes documented on the [Control Panel](/control-panel#content-scoping-control-panel-results) page. ### Disabling global scopes By default, Runway will observe all global scopes registered on your model. However, this might not be ideal if you want to access, for example, soft deleted models in Runway. You can work around this by calling the `withoutGlobalScopes` method in the `runway` query scope: ```php focus={7-15} theme={null} use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class YourModel extends Model { #[Scope] protected function runway(Builder $query): void { // Disables ALL global scopes $query->withoutGlobalScopes(); // Disables a specific global scope $query->withoutGlobalScope([ActiveScope::class]); } } ``` You can find more information about global scopes on the [Laravel documentation](https://laravel.com/docs/12.x/eloquent#removing-global-scopes). ## List of Resources If you're unsure about the handle of a resource, you may want to check it. You may do so with the `php please runway:resources` command which will display a list of Runway Resources. Resource List command # REST API Source: https://runway.duncanmcclean.com/rest-api Integrates with Statamic's Content API to provide a RESTful JSON API for your Eloquent models. Statamic comes with a read-only API that allows you to deliver content from Statamic to your frontend, external apps, SPA, or any other desired location. Content is delivered RESTfully as JSON data. Runway includes support for Statamic's Content API, which enables you to access your Eloquent models. If you prefer, Runway also supports [GraphQL](/graphql). ## Enabling for resources If you haven't already done so, you'll need to enable Statamic's REST API. You can do this by adding the following line to your `.env` file: ``` STATAMIC_API_ENABLED=true ``` Alternatively, you can enable it for all environments in `config/statamic/api.php`: ```php theme={null} 'enabled' => true, ``` Next, you'll need to enable the resources you want to make available. To do this, simply add a `runway` key to your `resources` array in `config/statamic/api.php`, and provide the handles of the resources for which you wish to enable the API: ```php theme={null} 'resources' => [ 'collections' => true, // ... 'runway' => [ 'products' => true, ], ], ``` ## Endpoints Each resource will have two endpoints: * `/api/runway/{resourceHandle}` for retrieving models associated with a resource. * `/api/runway/{resourceHandle}/{id}` for retrieving a specific model. ## Filtering To enable filtering for your resources, you'll need to opt in by defining a list of `allowed_filters` for each resource in your `config/statamic/api.php` configuration file: ```php theme={null} 'runway' => [ 'products' => [ 'allowed_filters' => ['name', 'slug'], ], ], ``` ## More Information For more information on Statamic's REST API functionality, please refer to the [Statamic Documentation](https://statamic.dev/rest-api#entries). # Revisions Source: https://runway.duncanmcclean.com/revisions Revisions are a powerful feature of Statamic that adds an entire publishing workflow to your authoring process. Statamic's Revisions feature allows you to create revisions (who would have guessed it), review and rollback to previous revisions of your content, and more. ## Enabling If you haven't already, you will need to [enable Statamic's revisions feature](https://statamic.dev/revisions#enabling) in your `.env`: ```dotenv theme={null} STATAMIC_REVISIONS_ENABLED=true ``` Next, make sure to enable Runway's ["publish states" feature](/resources#content-publish-states). This is a prerequisite for using revisions, it provides a way for models to be published or unpublished, much like entries. ```php config/runway.php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'published' => true, // Assumes the model has a `published` boolean column. 'published' => 'active', // Otherwise, you can specify the column name. ], ], ``` Finally, add the `revisions` config option to your resource's config: ```php config/runway.php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'published' => true, 'revisions' => true, ], ], ``` Now, when you're editing a model in the Control Panel, you'll be able to save using Revisions and view the history of changes. ## Storing Revisions in the Database Out of the box, Statamic will store revisions in your project's `storage/statamic/revisions` directory. However, if you'd prefer for Statamic to store revisions in the database instead, you can install the official Eloquent Driver and select the "Revisions" repository: ```shell theme={null} php please install:eloquent-driver ``` # Search Source: https://runway.duncanmcclean.com/search Runway integrates with Statamic's Search feature, allowing you to search your Eloquent models in the Control Panel and via the `{{ search:results }}` tag. ## Configuration ```php config/statamic/search.php theme={null} 'indexes' => [ 'myindex' => [ 'driver' => 'local', 'searchables' => ['collection:blog', 'runway:order'], // [!code ++] ], ], ``` You can scope the resources you'd like to be searchable, using the `runway:{resourceHandle}` syntax. If you'd like everything in Runway to be searchable, you can use`runway:*`. ### Title field By default, when displaying search results, Runway will use the first listable column as the 'title field'. If you'd like to change this, add the `title_field` option to your resource's config: ```php config/runway.php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'title_field' => 'name', ], ], ``` ## Further documentation... For further documentation on integrating Search in your site, please review the [Statamic Documentation](https://statamic.dev/search#overview). # Templating Source: https://runway.duncanmcclean.com/templating There’s no point storing data in a database for it never to be used, is there? ## Antlers Tag Runway provides a `{{ runway }}` Antlers tag to enable you to get model data for your resources. For example, if you wish to create a listing/index page for a resource, you can use the tag like shown below: ```antlers theme={null} {{ runway:post }}

{{ title }}

{{ intro_text }}

{{ /runway:post }} ``` There’s a bunch of helpful parameters you can use on the tag as well… ### Sorting You may use the `sort` parameter to adjust the order of the results. ```antlers theme={null} {{ runway:post sort="title:asc" }}

{{ title }}

{{ intro_text }}

{{ /runway:post }} ``` ### Eloquent Scopes If you've defined a scope on your Eloquent model and you want to filter by that in your front-end you may use the `scope` parameter. ```php focus={6-10} theme={null} // app/Models/Post.php use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Builder; #[Scope] protected function food(Builder $query): void { $query->whereIn('title', ['Pasta', 'Apple', 'Burger']); } ``` ```antlers theme={null} {{ runway:post query_scope="food" }}

{{ title }}

{{ intro_text }}

{{ /runway:post }} ``` If you need to you can provide arguments to the scope like so: ```antlers theme={null} {{ runway:post query_scope="food:argument" }} ``` In the above example, `argument` can either be a string or we'll grab it from 'the context' (the available variables) if we can find it. You may also provide multiple scopes, if that's something you need... ```antlers theme={null} {{ runway:post query_scope="food:argument|fastfood" }} ``` ### Filtering Just like with the collection tag, you may filter your results like so: ```antlers theme={null} {{ runway:post where="author_name:duncan" }}

{{ title }}

{{ intro_text }}

{{ /runway:post }} ``` You can also query Belongs To / Has Many fields using the `where` parameter. Simply provide the ID(s) of the related models. ```antlers theme={null} {{ runway:post where="categories:2" }}

{{ title }}

{{ intro_text }}

{{ /runway:post }} ``` You can also use the `where_in` parameter to filter by multiple IDs. ```antlers theme={null} {{ runway:post where_in="author_name:duncan,jack" }}

{{ title }}

{{ intro_text }}

{{ /runway:post }} ``` ### Eager Loading If your model has a relationship that you'd like to bring into the template, you may specify the `with` parameter. ```antlers theme={null} {{ runway:post with="user" }}

{{ title }}

By {{ user:name }}

{{ /runway:post }} ``` You can specify multiple relationships to eager load, just separate with pipes. ```antlers theme={null} {{ runway:post with="user|comments" }} ``` Eager Loading can make a **massive** difference in the speed of your queries. ### Limiting If you only want X number of results returned instead of ALL of them, you may specify a `limit`. ```antlers theme={null} {{ runway:post limit="15" }}

{{ title }}

{{ intro_text }}

{{ /runway:post }} ``` ### Scoping As [with the collection tag](https://statamic.dev/tags/collection#scope), you may use the `as` parameter to scope your results. ```antlers theme={null} {{ runway:post as="posts" }} {{ posts }}

{{ title }}

{{ intro_text }}

{{ /posts }} {{ /runway:post }} ``` ### Publish State By default, when you're using Runway's [Publish States](/resources#publish-states) feature, only published models are included. Models can be queried against `published` or `draft` status with conditions on `status` like this: ```antlers theme={null} {{ runway:post status="published" }} {{ posts }}

{{ title }}

{{ intro_text }}

{{ /posts }} {{ /runway:post }} ``` ### Pagination If you want to paginate your results onto multiple pages, you can use the `paginate` parameter, along with [scoping](#scoping) and [limiting](#limiting). Using the Runway tag with pagination is a little more complicated but it’s not rocket science. ```antlers theme={null} {{ runway:post as="posts" paginate="true" limit="10" }} {{ if no_results }}

Nothing has been posted yet. Sad times.

{{ /if }} {{ posts }}

{{ title }}

{{ intro_text }}

{{ /posts }} {{ paginate }} {{ if prev_page }} Previous {{ /if }} Page {{ current_page }} of {{ total_pages }} {{ if next_page }} Next {{ /if }} {{ /paginate }} {{ /runway:post }} ``` ## Counts When you just want to know how many results you have, you can use the `{{ runway:count }}` tag. ```antlers theme={null} {{ runway:count from="posts" }} ``` You can use the `where` parameter to filter the results: ```antlers theme={null} {{ runway:count from="posts" where="author_name:duncan" }} ``` ## Blade You can even use Runway's tag in Blade views, thanks to Statamic's [Antlers Blade Components](https://statamic.dev/blade#using-antlers-blade-components) feature: ```blade theme={null}

{{ $title }}

{{ $intro_text }}

``` ## Augmentation All the results output from the Runway tag are ‘augmented’, which essentially means everything is the same as you’d expect if you had the same data in an entry. The process of augmentation takes a value (from the database in our case) and processes it via the fieldtype into a value appropriate for the front-end. Let’s imagine you have an Assets field in your blueprint, you may have something selected for the field. In the database, the path to the asset is stored. When this field is then augmented, Statamic does a lookup of the asset by it’s path and spits out variables like `url`, `alt` and a couple of others. (There’s another explanation of augmentation over on [the Statamic documentation](https://statamic.dev/extending/augmentation#what-is-augmentation)) # Upgrading from v3.x to v4.0 Source: https://runway.duncanmcclean.com/upgrade-guides/v3-x-to-v4-0 ## Overview Please don't upgrade multiple versions at once (eg. from v2 to v4). Please upgrade one step at a time. To get started with the upgrade process, follow the below steps: **1.** In your `composer.json` file, update the `doublethreedigital/runway` version constraint: ```json theme={null} "doublethreedigital/runway": "^5.0" ``` **2.** Then run: ``` composer update doublethreedigital/runway --with-dependencies ``` **3.** You may also want to clear your route & view caches: ``` php artisan route:clear php artisan view:clear ``` **4.** Update complete! **Please test locally before deploying to production!** ## Changes ### High: Permission keys have changed Permission keys have changed. If you have a user role with custom permissions set, you will need to make some changes: If you're using the **files** user repository, the permission keys in the `resources/users/roles.yaml` file should have been automatically with the new permission names. If you're using **any other** user repository, you will need to update the permission keys manually. Examples of the changes are shown below: * `View Products` -> `view product` * `Edit Products` -> `edit product` * `Create new Product` -> `create product` * `Delete Product` -> `delete product` *** [You may also view a diff of changes between v3.x and v4.0](https://github.com/statamic-rad-pack/runway/compare/3.x...4.x) # Upgrading from v4.x to v5.0 Source: https://runway.duncanmcclean.com/upgrade-guides/v4-x-to-v5-0 ## Overview Please don't upgrade multiple versions at once (eg. from v3 to v5). Please upgrade one step at a time. To get started with the upgrade process, follow the below steps: **1.** In your `composer.json` file, update the `doublethreedigital/runway` version constraint: ```json theme={null} "doublethreedigital/runway": "^5.0" ``` **2.** Then run: ``` composer update doublethreedigital/runway --with-dependencies ``` **3.** You may also want to clear your route & view caches: ``` php artisan route:clear php artisan view:clear ``` **4.** Update complete! **Please test locally before deploying to production!** ## Changes ### High: Add `HasRunwayResource` trait to Eloquent models You will need to add a new `HasRunwayResource` trait to all Eloquent models configured in the Runway config: ```php theme={null} // app/Models/Order.php use StatamicRadPack\Runway\Traits\HasRunwayResource; class Order extends Model { use HasRunwayResource; } ``` *** [You may also view a diff of changes between v4.x and v5.0](https://github.com/statamic-rad-pack/runway/compare/4.x...5.x) # Upgrading from v5.x to v6.0 Source: https://runway.duncanmcclean.com/upgrade-guides/v5-x-to-v6-0 ## Overview Please don't upgrade multiple versions at once (eg. from v4 to v6). Please upgrade one step at a time. To get started with the upgrade process, follow the below steps: **1.** As Runway is now part of [The Rad Pack](https://github.com/statamic-rad-pack), you'll need to uninstall the addon under its old name and re-install under the Rad Pack: ```sh theme={null} composer remove doublethreedigital/runway composer require statamic-rad-pack/runway:^6.0 ``` **2.** Next, you'll need to update references to Runway's traits in your Eloquent models. ```php theme={null} augment($model); AugmentedModel::augment($model, $resource->blueprint()); // Now.. $model->toAugmentedArray(); ``` Every field will now return `Value` objects, rather than just the augmented value. ### Medium: Has Many Fieldtype - Table Mode removed Runway previously included a special "Table" mode for the Has Many fieldtype. However, the Table mode has been removed to help reduce complexity of Runway's fieldtypes. If you were using the Table mode on any of your Has Many fields, you should switch the `mode` to `default`. **Don't know if you're using the Table mode?** You can find out by searching these terms in your code editor of choice: * `mode: table` * `'mode' => 'table'` *** [You may also view a diff of changes between v5.x and v6.0](https://github.com/statamic-rad-pack/runway/compare/5.x...6.x) # Upgrading from v6.x to v7.0 Source: https://runway.duncanmcclean.com/upgrade-guides/v6-to-v7 ## Overview Please don't upgrade multiple versions at once (eg. from v5 to v7). Please upgrade one step at a time. To get started with the upgrade process, follow the below steps: **1.** In your `composer.json` file, change the `statamic-rad-pack/runway` version constraint to `^7.0`: ```json theme={null} "statamic-rad-pack/runway": "^7.0" ``` **2.** Then run: ``` composer update statamic-rad-pack/runway --with-dependencies ``` **3.** Next, please ensure you have cleared the route and view caches: ``` php artisan route:clear php artisan view:clear ``` **4.** You're now running Runway v7. Please review this upgrade guide for information on changes which may affect your project. **Please test your project locally before deploying to production!** ## High impact changes ## Statamic support **Affects all apps using Runway** The minimum version of Statamic is now 5. Please review the [Statamic 5 upgrade guide](https://statamic.dev/upgrade-guide/4-0-to-5-0). ### PHP support **Affects apps using PHP 8.1** The minimum version of PHP is now 8.2. We highly recommend upgrading all the way to PHP 8.3. ### Resource handles are now generated differently **Affects apps with Eloquent models, where the class name is multiple words** Runway will now generate resource handles slightly differently for Eloquent models, where the class name is multiple words. For example: in v6, the resource handle for a model named `BlogPost` would have been `blogpost`. In v7, it will now be `blog_post` for easier readability. If this affects you, you can either update all references to the old resource handle in your blueprints & templates, or manually override the handle of the resource in your Runway config: ```php config/runway.php theme={null} BlogPost::class => [ 'handle' => 'blogpost', ], ``` *** [You may also view a diff of changes between v6.x and v7.0](https://github.com/statamic-rad-pack/runway/compare/6.x...7.x) # Upgrading from v7.x to v8.0 Source: https://runway.duncanmcclean.com/upgrade-guides/v7-to-v8 ## Overview Please don't upgrade multiple major versions at once (eg. from v6 to v8). You should upgrade one major version at a time. To get started with the upgrade process, follow the below steps: **1.** In your `composer.json` file, change the `statamic-rad-pack/runway` version constraint to `^8.0`: ```json theme={null} "statamic-rad-pack/runway": "^8.0" ``` **2.** Then run: ``` composer update statamic-rad-pack/runway --with-dependencies ``` **3.** Next, please ensure you have cleared the route and view caches: ``` php artisan route:clear php artisan view:clear ``` **4.** You're now running Runway v8. Please review this upgrade guide for information on changes which may affect your project. **Please test your project locally before deploying to production!** ## High impact changes ### Changes to Nested Fields **Affects apps using nested JSON fields.** In previous versions of Runway, nested fields were configured using the `->` separator. However, in Statamic 5, validation around field handles has been tightened up, and `>` is no longer considered a valid character in field handles. To work around this, v8 introduces some changes around how nested fields are configured: 1. Instead of using `->` to separate the column name and the JSON key in field handles, you should now use an underscore: ```yaml theme={null} - handle: address->street_name # [!code --] handle: address_street_name # [!code ++] field: type: text display: 'Street Name' ``` 2. You should also specify the "nested field prefixes" (eg. the JSON column names) in your Runway config file. This will allow Runway to determine which fields are nested. ```php theme={null} Order::class => [ 'nested_field_prefixes' => [ 'address', ], ], ``` As an upside of this new approach, nested fields can now be used with Runway's [GraphQL API](/graphql). ## Low impact changes ### Removal of the `cp_icon` config option The `cp_icon` configuration option has been removed in Runway 8, in favour of being able to change the icon using Statamic's [Nav Preferences](https://statamic.dev/preferences#accessing-preferences) feature. ```php theme={null} 'resources' => [ \App\Models\Order::class => [ 'name' => 'Orders', 'cp_icon' => 'date', // [!code --] ], ], ``` ### Generate Migrations command has been removed The `runway:generate-migrations` command has been removed in favour of the new `runway:import-collection` command which handles the entire process of generating Eloquent models, database migrations and importing entries. *** [You may also view a diff of changes between v7.x and v8.0](https://github.com/statamic-rad-pack/runway/compare/7.x...8.x) # Upgrading from v8.x to v9.0 Source: https://runway.duncanmcclean.com/upgrade-guides/v8-to-v9 ## Overview Please don't upgrade multiple major versions at once (eg. from v7 to v9). You should upgrade one major version at a time. To get started with the upgrade process, follow the below steps: **1.** In your `composer.json` file, change the `statamic-rad-pack/runway` version constraint to `^9.0`: ```json theme={null} "statamic-rad-pack/runway": "^9.0" ``` **2.** Then run: ``` composer update statamic-rad-pack/runway --with-dependencies ``` **3.** Next, please ensure you have cleared the route and view caches: ``` php artisan route:clear php artisan view:clear ``` **4.** Carefully review this upgrade guide for changes which may affect your project. ## High impact changes ### PHP and Laravel support **Affects apps using PHP \< 8.2 or Laravel \< 11.** * The minimum version of PHP is now 8.2. * The minimum version of Laravel is now 11. We highly recommend upgrading all the way to Laravel 12 and PHP 8.4. ## Medium impact changes ### The `scope` parameter on the Runway tag has been renamed **Affects app using the `scope` parameter on the Runway tag** The `scope` parameter on the Runway tag has been renamed to `query_scope` to avoid conflicts with Antlers' own `scope` parameter. ```antlers theme={null} {{ runway:post scope="food" }} {{# [!code --] #}} {{ runway:post query_scope="food" }} {{# [!code ++] #}} ``` ### `runway:rebuild-uri-cache` no longer removes global query scopes The `runway:rebuild-uri-cache` command no longer removes global query scopes when querying models. If you were relying on this behaviour, you may remove global scopes using the `runwayRoutes` query scope: ```php theme={null} #[Scope] public function runwayRoutes($query) { return $query->withoutGlobalScopes(); } ``` *** [You may also view a diff of changes between v8.x and v9.0](https://github.com/statamic-rad-pack/runway/compare/8.x...9.x)