# Introduction

Welcome to the Voyager documentation for version 1.0. This documentation will teach you how to install, configure, and use Voyager so that way you can create some kick ass stuff!

Hm Hm (cough)… I mean… Arrgg! Ye young scallywag! What say we learn how to steer this ship!

![Voyager Screenshot](https://s3.amazonaws.com/thecontrolgroup/voyager-screenshot.png)

Before installing Voyager you may want to take a quick moment to learn what is is and what it isn't, we'll do that in the next section.


# What is Voyager

Before installing Voyager it is very important to take a quick moment to learn *what it is* & *what it isn't*.

## What it is

* An admin interface for your Laravel app
* An easy way to add/edit/delete data for your app
* A menu builder (build menus in Voyager for your app)
* A media manager for your files
* CRUD/BREAD generator ([learn more about BREAD here](/1.0/core-concepts/bread-builder))

Voyager is simply an admin for your Laravel app. Whatever you want your app to do on the front-end is completely up to you. You are in control of your application and you can use Voyager to make your life easier by adding data, editing users, creating menus, and many other administrative tasks.

## What it isn't

* A content management system (CMS)
* A blogging platform
* Wordpress (Bleh! 😜)

Voyager is not a CMS or a blogging platform. But it can be used to create a CMS or a blogging platform, but out of the box it is neither of those. As stated in the previous section you have full control on what your application will do and how it will function.

With Laravel & Voyager you can create any kind of application your heart desires. Laravel & Voyager are simply tools to make it easier to build.


# Installation

Voyager is super easy to install. After creating your new Laravel application you can include the Voyager package with the following command:

```bash
composer require tcg/voyager
```

Next make sure to create a new database and add your database credentials to your .env file, you will also want to add your application URL in the `APP_URL` variable:

```
APP_URL=http://localhost
DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
```

{% hint style="info" %}
**Using Laravel 5.4?**\
If you are installing with Laravel 5.4 you will need to [add the Service Provider manually](/1.0/getting-started/installation#adding-the-service-provider). Otherwise, if you are on 5.5 this happens automatically thanks to package auto-discovery.
{% endhint %}

Finally, we can install Voyager. You can choose to install Voyager with dummy data or without the dummy data. The dummy data will include 1 admin account (if no users already exist), 1 demo page, 4 demo posts, 2 categories and 7 settings.

To install Voyager without dummy data simply run

```bash
php artisan voyager:install
```

If you prefer installing it with the dummy data run the following command:

```bash
php artisan voyager:install --with-dummy
```

{% hint style="danger" %}
**Specified key was too long error**\
If you see this error message you have an outdated version of MySQL, use the following solution: <https://laravel-news.com/laravel-5-4-key-too-long-error>
{% endhint %}

And we're all good to go!

Start up a local development server with `php artisan serve` And, visit the URL <http://localhost:8000/admin> in your browser.

If you installed with the dummy data, a user has been created for you with the following login credentials:

> **email:** `admin@admin.com`\
> **password:** `password`

{% hint style="info" %}
**Quick note**\
A dummy user is **only** created if there are no current users in your database.
{% endhint %}

If you did not go with the dummy user, you may wish to assign admin priveleges to an existing user. This can easily be done by running this command:

```bash
php artisan voyager:admin your@email.com
```

If you wish to create a new admin user you can pass the `--create` flag, like so:

```bash
php artisan voyager:admin your@email.com --create
```

And you will be prompted for the users name and password.

## Advanced

This section is meant for users who are installing Voyager on an already existing Laravel installation or for users who want to perform a manual install. If this is not the case, you should go back to the [installation](/1.0/getting-started/installation) documentation or skip this section.

The first thing you should do is publish the assets that come with Voyager. You can do that by running the following commands:

```bash
php artisan vendor:publish --provider=VoyagerServiceProvider
php artisan vendor:publish --provider=ImageServiceProviderLaravel5
```

## Adding the Service Provider

{% hint style="info" %}
**This is only required if you are using Laravel 5.4!**\
If you are on Laravel 5.5+ you can skip this step.
{% endhint %}

To add the Voyager Service Provider open up your application `config/app.php` file and add `TCG\Voyager\VoyagerServiceProvider::class,` in the `providers` array like so:

```php
<?php

'providers' => [
    // Laravel Framework Service Providers...
    //...

    // Package Service Providers
    TCG\Voyager\VoyagerServiceProvider::class,
    // ...

    // Application Service Providers
    // ...
],
```


# Upgrading


# Version 1.0 to 1.0.\*

To update to the latest version inside of your composer.json file make sure to update the version of voyager inside the require declaration inside of your composer.json to:

```
"tcg/voyager": "1.0.*"
```

And then run

```
composer update tcg/voyager
```

Next, you may want to be sure that you have all the latest published assets. To re-publish the voyager assets you can run the following command:

```
php artisan vendor:publish --tag=voyager_assets --force
```

Lastly, you may wish to clear your view cache by running the following command:

```
php artisan view:clear
```


# Version 0.11 to 1.0

**Update your Composer.json**

To update to the latest version inside of your composer.json file make sure to update the version of voyager inside the require declaration inside of your composer.json to:

```
"tcg/voyager": "1.0.*"
```

And then run composer update

**Run the necessary migrations**

You will now need to run the following migrations to include new tables or rows that have been added to the latest version. you can find each of these migrations below:

* <https://github.com/the-control-group/voyager/blob/master/publishable/database/migrations/2017_07_05_210000_add_policyname_to_data_types_table.php>
* <https://github.com/the-control-group/voyager/blob/master/publishable/database/migrations/2017_08_05_000000_add_group_to_settings_table.php>
* <https://github.com/the-control-group/voyager/blob/master/publishable/database/migrations/2017_04_11_000000_alter_post_nullable_fields_table.php>
* (possibly need this migration, if already exists do not include) <https://github.com/the-control-group/voyager/blob/v0.11.14/publishable/database/migrations/2017_04_21_000000_add_order_to_data_rows_table.php>

You can do this by adding each of those migrations to your `database/migrations` folder and then run `php artisan migrate`

**Upgrading Settings**

Only applicable if you are using settings in your application. New to version 1.0, settings are grouped by section. For instance the following setting will not work:

```php
{{ setting('title') }}
```

Each setting key will now belong to a group. Which means that you would need to change the setting to:

`{{ setting('site.title') }}`

And that title key would now need to have a group with the name of 'Site', like the following:

![](https://github.com/the-control-group/voyager/tree/d1a65f76a3a0b36478fb2bf0a11f51d539dc88e9/docs/.gitbook/assets/011_10_settings.png)

To update all the settings in your app, you may want to, just create a group name, such as Site, and then update all your settings to include the `site` prefix:

```php
{{ setting('site.description') }}
```

Any previous Admin settings have been added to a group called 'Admin'.

**Final Steps**

Next, you may want to be sure that you have all the latest published assets. To re-publish the voyager assets you can run the following command:

```
php artisan vendor:publish --tag=voyager_assets --force
```

Then you may wish to clear your view cache by running the following command:

```
php artisan view:clear
```

At last, must change your `User` model to extend `TCG\Voyager\Models\User`

```php
use TCG\Voyager\Models\User as VoyagerUser;

class User extends VoyagerUser
{
    // ...
}
```

And now you'll be upgraded to the latest version.

**If you're planning to use hooks** If you want to use Hooks (Voyager's built-in plugin system) you must run `php artisan hook:setup` before it will work. This is now included in `php artisan voyager:install`, so this will only need to be run after upgrading from an earlier version.

**Troubleshooting**

Be sure to ask us on our slack channel if you are experiencing any issues and we will try and assist. Thanks.


# Configurations

With the installation of voyager you will have a new configuration file located at `config/voyager.php` In this file you can find various options to change the configuration of your voyager installation. Following is a more detailed description of each of the configuration sets:

**User Config**

```php
'user' => [
    'add_default_role_on_register' => true,
    'default_role'                 => 'user',
    'admin_permission'             => 'browse_admin',
    'namespace'                    => App\User::class,
],
```

**add\_default\_role\_on\_register**: Specify whether you would like to add the default role to any new user that is created.

**default\_role**: You can also specify what the **default\_role** is of the user.

**admin\_permission**: The permission needed to view the admin dashboard.

**namespace**: The namespace of your apps User Class.

**Controller Config**

```php
'controllers' => [
    'namespace' => 'TCG\\Voyager\\Http\\Controllers',
],
```

You can specify the default `controller` namespace of voyager so if you ever wish to override any of the core functionality of voyager you can do so by duplicating the Voyager Controllers and specifying the location of your custom controllers.

> If you do only wish to overwrite a single controller, you might consider adding the following piece of code in your `AppServiceProvider`'s `register`-method:
>
> ```php
> $this->app->bind(VoyagerBreadController::class, MyBreadController::class);
> ```

**Model Config**

```php
'models' => [
    //'namespace' => 'App\\',
],
```

You can specify the namespace or location of your models. This is used when creating the Models from the database section of Voyager. If not defined the default application namespace will be used.

**Asset Config**

```php
'assets_path' => '/vendor/tcg/voyager/assets',
```

You may wish to specify a different asset path. If your site lives in a subfolder you may need to include that directory to the beginning of the path. This may also be used in case you wish to duplicate the published assets and customize your own.

> Note: When upgrading to new version of voyager the assets located in the /vendor/tcg/voyager/assets directory may need to be overwritten, so if you wish to customize any styles you will want to duplicate that directory and specify the new location of your asset\_path.

**Storage Config**

```php
'storage' => [
    'disk' => 'public',
],
```

By default voyager is going to use the `public` local storage. You can additionally use any driver inside of your `config/filesystems.php`. This means you can use s3, google cloud storage, or any other file storage system you would like.

**Database Config**

```php
'database' => [
    'tables' => [
        'hidden' => ['migrations', 'data_rows', 'data_types', 'menu_items', 'password_resets', 'permission_role', 'settings'],
    ],
],
```

You may wish to hide some database tables in the Voyager database section. In the database config you can choose which tables would like to hide.

**Prefix Config**

```php
'prefix' => 'admin',
```

In this config you can specify an alternate prefix for visiting voyager. Instead of visiting `/admin` perhaps you want to visit `/backend` to visit the voyager admin.

**Multilingual Config**

Thanks to all the contributors to voyager we now have multilingual support.

```php
'multilingual' => [
    'enabled' => false,
    'default' => 'en',
    'locales' => [
        'en',
        //'pt',
    ],
],
```

You can specify whether or not you want to **enable** mutliple languages. You can then specify your **default** language and all the support languages (**locales**)

**Dashboard Config**

```php
'dashboard' => [

    'navbar_items' => [
        'Profile' => [
            'route'         => 'voyager.profile',
            'classes'       => 'class-full-of-rum',
            'icon_class'    => 'voyager-person',
        ],
        'Home' => [
            'route'         => '/',
            'icon_class'    => 'voyager-home',
            'target_blank'  => true,
        ],
        'Logout' => [
            'route'      => 'voyager.logout',
            'icon_class' => 'voyager-power',
        ],
    ],

    'widgets' => [
        'TCG\\Voyager\\Widgets\\UserDimmer',
        'TCG\\Voyager\\Widgets\\PostDimmer',
        'TCG\\Voyager\\Widgets\\PageDimmer',
    ],

],
```

In the dashboard config you can add **navbar\_items**, make the **data\_tables** responsive, and manage your dashboard **widgets**.

**navbar\_items** Include a new route in the main user navbar dropdown by including a 'route', 'icon\_class', and 'target\_blank'.

**data\_tables** If you set 'responsive' to true the datatables will be responsive.

**widgets** Here you can manage the widgets that live on your dashboard. You can take a look at an example widget class by viewing the current widgets inside of `tcg/voyager/src/Widgets`.

**Primary Color Config**

```php
'primary_color' => '#22A7F0',
```

The default primary color for the Voyager admin dashboard is a light blue color. You can change that primary color by changing the value of this config.

**Show Dev Tips Config**

```
'show_dev_tips' => true,
```

In the Voyager admin there are dev tips or notifications that will show you how to reference certain values from voyager. You can choose to hide these notifications by setting this configuration to false.

**Additional CSS Config**

```php
'additional_css' => [
    //'css/custom.css',
],
```

This is super cool, you can add your own custom stylesheets that will be included in the Voyager Admin dashboard. This means you could technically create a whole new theme for Voyager by adding your own custom stylesheet.

**Additional JS Config**

```php
'additional_js' => [
    //'js/custom.js',
],
```

The same goes for this configuration. You can add your own javascript that will be executed in the Voyager admin dashboard. Add as many js files as needed.

**Google Maps Config**

```php
'googlemaps' => [
    'key'    => env('GOOGLE_MAPS_KEY', ''),
    'center' => [
        'lat' => env('GOOGLE_MAPS_DEFAULT_CENTER_LAT', '32.715738'),
        'lng' => env('GOOGLE_MAPS_DEFAULT_CENTER_LNG', '-117.161084'),
    ],
    'zoom' => env('GOOGLE_MAPS_DEFAULT_ZOOM', 11),
],
```

There is a new data type called **coordinates** that allow you to add a google map as a datatype. The user can then drag and drop a pin in the google map to save a longitude and latitude value in the database.

In this config you can set the default Google Maps Keys and center location. This call also be added to your .env file.


# Routing

After running the voyager installer you will see a few new routes that have been added to your `routes/web.php` file which look like the following:

```php
Route::group(['prefix' => 'admin'], function () {
    Voyager::routes();
});
```

This is where the voyager routes will be rendered. You can change the `admin` prefix if you desire, or set any other route configuration you need, such as `middleware` or `domain`.

When creating a new BREAD type and specifying a slug for that BREAD, you can then visit that route from the following link:

```
URL/admin/slug-name
```

As an example, if we have a `products` table and we specified the slug to be `products`. You will now be able to visit the following URL:

```
URL/admin/products
```

{% hint style="info" %}
**Notice**\
You may not see a link to your newly created routes or BREAD inside your admin menu. To create a new link in your admin menu visit the documentation for the menu section.
{% endhint %}


# Media Manager

Voyager has a full-fledged Media Manager which allows you to upload files, re-name files, and delete files. You can also add new folders and move files/folders. Basically anything that you would be able to do in any type of Media Manager you can do so in the Voyager Media Manager.

![](/files/-LrOVMDibnyMMYE7oDz-)

You may also drag and drop files onto the 'upload' button to upload multiple files.

{% hint style="info" %}
**Notice on File Upload Size**\
If you are getting an error when trying to upload large files, this may be a setting that needs to be changed in your PHP. Be sure to check `max_file_upload` and `file_upload_size`
{% endhint %}


# Menus and Menu Builder

With Voyager you can easily create menus for your application. In fact the Voyager admin is using the menu builder for the navigation you use on the left hand side.

You can view your current Menus by clicking on the *Tools->Menu Builder* button. You can add, edit, or delete any current menu. This means that you can create a new menu for the header, sidebar, or footer of your site. Create as many menus as you would like.

When you are ready to add menu items to your menu you can click on the builder button of the corresponding menu:

![](/files/-LrOUO_53SnAbZLfHGKQ)

This will take you to the Menu Builder where you can add, edit, and delete menu items.

![](/files/-LrOUO_75VwScr5uM7Ia)

After creating and configuring your menu, you can easily implement that menu in your application. Say that we have a menu called `main`. Inside of any view file we could now output the menu by using the following code:

```
menu('main');
```

This will output your menu in an unstyled unordered list. If you do use bootstrap to stylize your web app you can pass a second argument to the menu display method telling it that you want to stylize the menu with bootstrap styles like so:

```
menu('main', 'bootstrap');
```

Taking it one more step further you can even specify your own view and stylize your menu however you would like. Say for instance that we had a file located at `resources/views/my_menu.blade.php`, which contained the following code:

```markup
<ul>
    @foreach($items as $menu_item)
        <li><a href="{{ $menu_item->link() }}">{{ $menu_item->title }}</a></li>
    @endforeach
</ul>
```

Then anywhere you wanted to display your menu you can now call:

```
menu('main', 'my_menu');
```

And your custom menu will now be output.


# Database Manager

Voyager has some awesome database tools which allow you to Add/Edit/Delete or view current database tables. The other cool part of Voyager is that you can add BREAD or (Browse, Read, Edit, Add, & Delete) functionality to any of your tables.

![](/files/-LrOVMEtUes3LIx906e-)

Inside of your admin panel you can visit Tools->Database and you'll be able to view all your current tables in your database. You may also click on 'Create a New Table' to create a new table in your database. All newly created tables will use the charset defined in your [default database connection](https://laravel.com/docs/database#configuration).

![](/files/-LrOVMEwIfTzLIcXY-up)

If you click the table name you can view the current schema. Additionally you can click on the View, Edit, or Delete buttons to perform that action for that table.

You may also choose to Add BREAD (Browse, Read, Edit, Add, & Delete) for any of your database tables. Once a table already has BREAD you may choose to edit the current BREAD or Delete the BREAD for that table.

Read on further about the BREAD builder in the next section.


# BREAD Builder

When adding or editing the current BREAD for a database table you will first see the BREAD info which allows you to set the Display Names, slug, icon, Model and Controller Namespace, Policy Name. You can also choose if you would like to Generate permissions for that BREAD type.

![](/files/-LrOVMIItVyfqzcxmTog)

When you scroll down you will see each of the rows that are associated with that table where you can select where in your views you want to see each of those fields:

* BROWSE (field will show up when you browse the current data)
* READ (field will show when you click to view the current data)
* EDIT (field will be visible and allow you to edit the data)
* ADD (field will be visible when you choose to create a new data type)
* DELETE (doesn't pertain to delete so this can be checked or unchecked)

![](/files/-LrOVMIMWx70F-V7bwRL)

You may also choose to specify what form type you want to use for each field. This can be a TextBox, TextArea, Checkbox, Image, and many other types of form elements.

Each field also has additional details or options that can be included. These types are checkbox, dropdown, radio button, and image.

## Additional Field Options

When Editing Your Browse, Read, Edit, Add, and Delete Rows you have a select box that allows you to include additional details or options for your datatype. This textarea accepts JSON and it applies to the following types of inputs:

* Text (Text Box, Text Area, Rich Textbox and Hidden)
* Check Box
* Drop Down
* Radio Button
* Image
* Date

Find out how to use these additional details below:

### Text (Text Box, Text Area, Rich Textbox and Hidden)

```php
{
    "default" : "Default text"
}
```

Text Box, Text Area, Rich Textbox and Hidden are all kind of texts inputs. In the JSON above you can specify the `default` value of the input.

### Check Box

```php
{
    "on" : "On Text",
    "off" : "Off Text",
    "checked" : "true"
}
```

In Voyager a Check Box is converted into a toggle switch, and as you can see above the `on` key will contain the value when the toggle switch is on, and the `off` will contain the value that is set when the switch is off. If `checked` is set to *true* the checkbox will be toggle on; otherwise by default it will be off.

### Drop Down

```php
{
    "default" : "option1",
    "options" : {
        "option1": "Option 1 Text",
        "option2": "Option 2 Text"
    }
}
```

When specifying that an input type should be a dropdown you will need to specify the values of that dropdown. In the JSON above you can specify the `default` value of the dropdown if it does not have a value. Additionally, in the `options` object you will specify the *value* of the option on the **left** and the *text* to be displayed on the **right**.

### Radio Button

```php
{
    "default" : "radio1",
    "options" : {
        "radio1": "Radio Button 1 Text",
        "radio2": "Radio Button 2 Text"
    }
}
```

The Radio button is exactly the same as the dropdown. You can specify a `default` if one has not been set and in the `options` object you will specify the *value* of the option on the **left** and the *text* to be displayed on the **right**.

### Image

```php
{
    "resize": {
        "width": "1000",
        "height": null
    },
    "quality" : "70%",
    "upsize" : true,
    "thumbnails": [
        {
            "name": "medium",
            "scale": "50%"
        },
        {
            "name": "small",
            "scale": "25%"
        },
        {
            "name": "cropped",
            "crop": {
                "width": "300",
                "height": "250"
            }
        }
    ]
}
```

The image input has many options. By default if you do not specify any options no problem... Your image will still be uploaded. But, if you want to resize an image, set the quality of the image, or specify thumbnails for the uploaded image you will need to specify those details.

**resize** If you want to specify a size you will need to include that in the `resize` object. If you set either **height** or **width** to null it will keep the aspect ratio based on the width or height that is set. So, for the example above the `width` is set to `1000` pixels and since the `height` is set to `null` it will resize the image width to 1000 pixels and resize the height based on the current aspect ratio.

**quality** If you wish to compress the image with a percentage quality you can specify that percentage in the `quality` key. Typically between 70 and 100% there is little notice of image quality, but the image size may be dramatically lower.

**upsize** This is only valid if you have set your image to be resized. If you specify your image to resized to 1000 pixels and the image is smaller than 1000 pixels by default it will not upsize that image to the 1000 pixels; however, if you set `upsize` to true. It will upsize all images to your specified resize values.

**thumbnails** Thumbnails takes an array of objects. Each object is a new thumbnail that is created. Each object contains 2 values, the `name` and `scale` percentage. The `name` will be attached to your thumbnail image (as an example say the image you uploaded was ABC.jpg a thumbnail with the `name` of `medium` would now be created at ABC-medium.jpg). The `scale` is the percentage amount you want that thumbnail to scale. This value will be a percentage of the *resize* width and height if specified.

### Date & Timestamp

```php
{
    "format" : "%Y-%m-%d"
}
```

The date & timestamp input field is where you can input a date. In the JSON above you can specify the `format` value of the output of the date. It allows you to display a formatted `date` in browse and read views, using Carbon's `formatLocalized()` method

## Description

All types can include a description in order to help your future self or other users using your Voyager admin panel to understand exactly what a specific BREAD input field is for, this can be defined in the `Optional Details` JSON input field:

```php
{
    "description": "A helpful description text here for your future self."
}
```

## Validation

Inside of the *Optional Details* section for each row in your BREAD you can also specify validation rules with some simple JSON. Here is an example of how to add a validation rule or *required* and *max length of 12*

```php
{
    "validation": {
        "rule": "required|max:12"
    }
}
```

Additionally, you may wish to add some custom error messages which can be accomplished like so:

```php
{
    "validation": {
        "rule": "required|max:12",
        "messages": {
            "required": "This :attribute field is a must.",
            "max": "This :attribute field maximum :max."
        }
    }
}
```

Since `v0.10.13` you can do the `required` and `max:12` rule the following way:

```php
{
    "validation": {
        "rules": [
            "required",
            "max:12"
        ]
    }
}
```

You can find a list of all available validation rules in the [Laravel docs](https://laravel.com/docs/validation#available-validation-rules).

## Generating Slugs

Using the bread builder you may wish to automatically generate slugs of a certain input. Lets say you have some posts, which have a title and a slug. If you want to automatically generate the slug from the title attribute, you may include the following *Optional Details*:

```php
{
    "slugify": {
        "origin": "title",
        "forceUpdate": true
    }
}
```

This will automatically generate the slug from the input of the `title` field. If a slug does already exists, it will only be updated if `forceUpdate` is set enabled, by default this is disabled.

## Relationships

Using the BREAD builder you can easily create Relationships between tables. At the bottom of the page you will see a new button that says 'Create Relationship'

![](/files/-LrOVMHPClygrOaaG2o_)

{% hint style="info" %}
**Notice**\
If you have not yet created the BREAD for the table yet, it will need to be created first and then you can come back after creating the BREAD to add the relationship. Otherwise you'll end up with a notification which looks like the following.
{% endhint %}

![](/files/-LrOVMHTtSeOMaYnk2cj)

So, after the BREAD has already been created you will then be able to create a new relationship. After you click on the 'Create a Relationship' button. You will see a new Modal window that looks like the following:

![](/files/-LrOVMHV_E_9RU05lE6w)

You will first specify which type of relationship this is going to be, then you will select the table you are referencing and which Namespace that belongs to that table. You will then select which row combines those tables.

You can also specify which columns you would like to see in the dropdown or the multi-select.

Now, you can easily create `belongsTo`, `belongsToMany`, `hasOne`, and `hasMany` relationships directly in Voyager.

## Null Values

You might want to save an input field into the database as a `null` value instead of an empty string.

Simply enough, inside the BREAD you can include the following *Optional Details* for the field:

```php
{
    "null": ""
}
```

This will turn an empty string into a `null` value. However you might want to be able to add both an empty string and a `null` value to the database for that field. However you have to choose a replacement for the `null` value, but it can be anything you wish. For example, if you want a field to change a string (ex. `Nothing`) into a `null` value you could include the following *Optional Details* for that field:

```php
{
    "null": "Nothing"
}
```

Now entering `Nothing` into the field will end up as a `null` value in the database.

## Display options

There are also a few options that you can include to change the way your BREAD is displayed. You can add a `display` key to your json object and change the width of the particular field and even specify a custom ID.

```php
{
    "display": {
        "width": "3",
        "id": "custom_id"
    }
}
```

The width is displayed on a 12-grid system. Setting it with a width of 3 will span 25% of the width.

The **id** will let you specify a custom id wrapper around your element. example:

```markup
<div id="custom_id">
    <!-- Your field element -->
</div>
```


# Settings

The Settings section allows you to add any site wide settings you would like. You can add an image upload setting for your site logo or a text box for the main headline on your homepage.

![](/files/-LrOUOotWDe5Kd3BtdnR)

In this new version you have the ability to add different groups for different settings. So, if you created a new setting inside of the `site` group and it had a key of `title` you would then be able to reference that setting any where on your site by doing the following:

```php
<?php
echo setting('site.title');
```

Or inside of any blade template like:

```
{{ setting('site.title') }}
```

So, now you can add all kinds of settings in Voyager and reference them in your application.


# Roles and Permissions

Voyager comes with Roles and Permissions out of the box. Each *User* has a *Role* which has a set of *Permissions*.

Inside of the dashboard you can choose to Add, Edit, or delete the current Roles. Additionally when you click to edit a particular role you can specify the BREAD permissions.

![](/files/-LrOVMDmwQ581k-_z41H)

New in version 1.0, we've changed Voyager's authorization system to be [more in line with Laravel](https://laravel.com/docs/5.5/authorization#authorizing-actions-using-policies)! This means that you can check for permissions in the following ways:

```php
// via user object
$canViewPost = $user->can('read', $post);
$canViewPost = Auth::user()->can('read', $post);

// via controller
$canViewPost = $this->authorize('read', $post);
```

You may also choose to use the Voyager facade and pass the permission as a string:

```php
$canBrowsePost = Voyager::can('browse_posts');
$canViewPost = Voyager::can('read_posts');
$canEditPost = Voyager::can('edit_posts');
$canAddPost = Voyager::can('add_posts');
$canDeletePost = Voyager::can('delete_posts');
```

The value of each check will return a boolean whether or not the user has that certain permission. However you might wish to throw a forbidden exception if the user does not have a certain permission. This can be done using the `canOrFail` method:

```php
Voyager::canOrFail('browse_admin');
```

Out of the box there are some permissions you can use by default:

* `browse_admin`: Whether or not the user may browse the Voyager admin panel.
* `browse_database`: Whether or not the user may browse the Voyager database menu section.
* `browse_bread`: Whether or not the user may browse the Voyager BREAD menu section.
* `browse_media`: Whether or not the user may browse the Voyager media section.
* `browse_menu`: Whether or not the user may browse the Voyager menu section.
* `browse_settings`: Whether or not the user may browse the Voyager settings section.
* `read_settings`: Whether or not the user can view or see a particular setting.
* `edit_settings`: Whether or not the user can edit a particular setting.
* `add_settings`: Whether or not the user can add a new setting.
* `delete_settings`: Whether or not the user can delete a particular setting.

Additionally you can `Generate permissions` for every BREAD type you create. This will create the `browse`, `read`, `edit`, `add` and `delete` permission.

As an example, perhaps we are creating a new BREAD type from a `products` table. If we choose to `Generate permissions` for our `products` table. Our permission keys will be `browse_products`, `read_products`, `edit_products`, `add_products` and `delete_products`.

{% hint style="info" %}
**Notice**\
If a menu item is associated with any kind of BREAD, then it will check for the `browse` permission, for example for the `Posts` BREAD menu item, it will check for the `browse_posts` permission. If the user does not have the required permission, that menu item will be hidden.
{% endhint %}

## Using Permissions in your Blade Template files

You can also check for permissions using blade syntax. Let's say for instance that you want to check if a user can `browse_posts`, simple enough we can use the following syntax:

```php
@can('browse', $post)
    I can browse posts
@endcan
```

Or perhaps you need to run an else condition for a permission. That's simple enough:

```php
@can('browse', $post)
    I can browse posts
@else
    I cannot browse posts
@endcan
```

Couldn't be easier, right ;)


# Helper methods

Voyager has several helper functions that are ready to use. Here you can find the list of available function that may speed up your development.

## Thumbnails URL

Voyager will generate thumbnails for Image field type when you specify the [additional field options](/1.0/core-concepts/bread-builder#additional-field-options).

After you have your thumbnails generated, you may want to display the thumbnails in your view or get the thumbnail URL. In order to do that you need to add `Resizable` traits to your model.

```php
use TCG\Voyager\Traits\Resizable;

class Post extends Model
{
    use Resizable;
}
```

Then you can call the thumbnail function in your view or anywhere you like.

```php
@foreach($posts as $post)
    <img src="{{Voyager::image($post->thumbnail('small'))}}" />
@endforeach
```

Or you can specify the optional image field name (attribute), default to `image`

```php
@foreach($posts as $post)
    <img src="{{Voyager::image($post->thumbnail('small', 'photo'))}}" />
@endforeach
```


# Multilanguage

Voyager supports multiple languages for your models.To get started, you need to configure some things first.

## Setup

First you need to define some `locales` in your `config/voyager.php` file and `enable` multilanguage:

```php
'multilingual' => [
        'enabled' => true,
        'rtl' => false,
        'default' => 'en',
        'locales' => [
            'en',
            'da',
        ],
    ],
```

After that you need to include the `Translatable` Trait in your model and define the translatable attributes:

```php
use TCG\Voyager\Traits\Translatable;
class Post extends Model
{
    use Translatable;
    protected $translatable = ['title', 'body'];
}
```

Now you will see a language-selection in your Pages BREAD.

## Usage

### Eager-load translations

```php
// Loads all translations
$posts = Post::with('translations')->get();

// Loads all translations
$posts = Post::all();
$posts->load('translations');

// Loads all translations
$posts = Post::withTranslations()->get();

// Loads specific locales translations
$posts = Post::withTranslations(['en', 'da'])->get();

// Loads specific locale translations
$posts = Post::withTranslation('da')->get();

// Loads current locale translations
$posts = Post::withTranslation('da')->get();
```

### Get default language value

```php
echo $post->title;
```

### Get translated value

```php
echo $post->getTranslatedAttribute('title', 'locale', 'fallbackLocale');
```

If you do not define locale, the current application locale will be used. You can pass in your own locale as a string. If you do not define fallbackLocale, the current application fallback locale will be used. You can pass your own locale as a string. If you want to turn the fallback locale off, pass false. If no values are found for the model for a specific attribute, either for the locale or the fallback, it will set that attribute to null.

### Translate the whole model

```php
$post = $post->translate('locale', 'fallbackLocale');
echo $post->title;
echo $post->body;

// You can also run the `translate` method on the Eloquent collection
// to translate all models in the collection.
$posts = $posts->translate('locale', 'fallbackLocale');
echo $posts[0]->title;
```

If you do not define locale, the current application locale will be used. You can pass in your own locale as a string. If you do not define fallbackLocale, the current application fallback locale will be used. You can pass in your own locale as a string. If you want to turn the fallback locale off, pass false. If no values are found for the model for a specific attribute, either for the locale or the fallback, it will set that attribute to null.

### Check if model is translatable

```php
// with string
if (Voyager::translatable(Post::class)) {
    // it's translatable
}

// with object of Model or Collection
if (Voyager::translatable($post)) {
    // it's translatable
}
```

### Set attribute translations

```php
$post = $post->translate('da');
$post->title = 'foobar';
$post->save();
```

This will update or create the translation for title of the post with the locale da. Please note that if a modified attribute is not translatable, then it will make the changes directly to the model itself. Meaning that it will overwrite the attribute in the language set as default.


# Adding Custom FormFields

You can easily add a new FormField to Voyager. In the example below we will add a number form field (which is already included by default in Voyager).

First we create a new class in our project (it doesn't matter where it is placed) called `NumberFormField`

```php
<?php

namespace App\FormFields;

use TCG\Voyager\FormFields\AbstractHandler;

class NumberFormField extends AbstractHandler
{
    protected $codename = 'number';

    public function createContent($row, $dataType, $dataTypeContent, $options)
    {
        return view('formfields.number', [
            'row' => $row,
            'options' => $options,
            'dataType' => $dataType,
            'dataTypeContent' => $dataTypeContent
        ]);
    }
}
```

The `codename` variable is used in the dropdown you see in the BREAD builder. In the `createContent` method we are returning the view that is used to display our form field.

Next, we will create the view specified above.

```markup
<input type="number"
       class="form-control"
       name="{{ $row->field }}"
       data-name="{{ $row->display_name }}"
       type="number"
       @if($row->required == 1) required @endif
             step="any"
       placeholder="{{ isset($options->placeholder)? old($row->field, $options->placeholder): $row->display_name }}"
       value="@if(isset($dataTypeContent->{$row->field})){{ old($row->field, $dataTypeContent->{$row->field}) }}@else{{old($row->field)}}@endif">
```

In the view we can add whatever logic we want.

When we are done with our view, we will tell Voyager that we have a new form field. We will do this in a service provider (in the example below we use the `AppServiceProvider`.

```php
<?php

namespace App\Providers;

use TCG\Voyager\Facades\Voyager;
use App\FormFields\NumberFormField;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    //..

    public function register()
    {
        Voyager::addFormField(NumberFormField::class);
    }
}
```


# Overriding Views

You can override any of the BREAD views by creating a new folder in `resources/views/vendor/voyager/slug-name` and *slug-name* will be the *slug* that you have assigned for that table. There are 2 files that you will include in each which will be:

* browse.blade.php
* edit-add.blade.php


# Using custom HTTP controllers

You can use your own Controller by extending Voyager's Controllers. To do it, first define your controller Namespace at `config/voyager.php` :

```php
/*
|--------------------------------------------------------------------------
| Controllers config
|--------------------------------------------------------------------------
|
| Here you can specify voyager controller settings
|
*/

'controllers' => [
    'namespace' => 'App\\Http\\Controllers\\Voyager',
],
```

then run `php artisan voyager:controllers`, voyager will now use the child controllers which will be created at `App/Http/Controllers/Voyager`


# Overriding Routes

You can override any Voyager routes by writing the routes you want to overwrite below `Voyager::routes()`. For example if you want to override your post LoginController:

```php
Route::group(['prefix' => 'admin'], function () {
   Voyager::routes();

   // Your overwrites here
   Route::post('login', ['uses' => 'MyAuthController@postLogin', 'as' => 'postlogin']);
});
```


# Additional CSS and JS

As of the latest version you can now add additional CSS and JS files to the voyager master blade without having to copy or modify the blade file itself removing potential manual migration headaches later on. The CSS and JS files are added *after* any Voyager assets so you can override styles and functionality comfortably.

This is all handled via the `voyager.php` config, if you have not started with a fresh install of `0.11.10+` you will need to manually add this to your config.

```php
    // Here you can specify additional assets you would like to be included in the master.blade
    'additional_css' => [
        //'css/custom.css',
    ],

    'additional_js' => [
        //'js/custom.js',
    ],
```

You may want to look at the `/vendor/tcg/voyager/publishable/config/voyager.php` to see the config layout and check for any missing options.


# Enabling Soft-Delete

This is only to assist with enabling soft-deletion for your models within Voyager. Please refer to the [Laravel documentation](https://laravel.com/docs/eloquent#soft-deleting) for specifics.

## Table Configurations in Voyager

When creating a table using the Database Manager you've selected the 'Add Soft Deletes' button and then when adding the BREAD functionality to that table you've added a Model Name, you only have to edit your Model file to fully enable Soft-Delete on that table.

## Editing the Table's Model

A default model will look like this:

```php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;


class YourModelName extends Model
{

}
```

Just turn it into:

```php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;


class Documento extends Model
{
    use SoftDeletes;
    protected $dates = ['deleted_at'];
}
```

And from now on, every time you delete a record from that table, it won't actually be deleted, only the `deleted_at` column will be written with the current timestamp.


# Using HTTPS on yours site

**Symptom:** When visiting your site with HTTPS, images within Voyager fail to load.

**Cause:** Images urls are generated by Voyager using

```php
Storage::disk(config('voyager.storage.disk'))->url($file);
```

If voyager.storage.disk is set to public, and the public disk is the default from Laravel, then the url property in the disk configuration is set to

```php
'url' => env('APP_URL').'/storage',
```

which uses the non-HTTPS APP\_URL value to build an absolute url to the image.

**Solution:** If you remove env('APP\_URL'). from the public disk configuration, then it will render a domain-relative url, which will always use the current domain and protocol.

As an aside, if you need a fully-qualified URL, you could wrap the call to `Voyager::image('...')` with `asset()`, so it would be

```php
asset(Voyager::image('...'))
```

This will return the current protocol, domain, and correct path to that image.


# Introduction

Welcome to the Voyager documentation for version 1.1. This documentation will teach you how to install, configure, and use Voyager so that way you can create some kick ass stuff!

Hm Hm (cough)… I mean… Arrgg! Ye young scallywag! What say we learn how to steer this ship!

![Voyager Screenshot](https://s3.amazonaws.com/thecontrolgroup/voyager-screenshot.png)

Before installing Voyager you may want to take a quick moment to learn what is is and what it isn't, we'll do that in the next section.


# What is Voyager

Before installing Voyager it is very important to take a quick moment to learn *what it is* & *what it isn't*.

## What it is

* An admin interface for your Laravel app
* An easy way to add/edit/delete data for your app
* A menu builder (build menus in Voyager for your app)
* A media manager for your files
* CRUD/BREAD generator ([learn more about BREAD here](/1.1/core-concepts/bread-builder))

Voyager is simply an admin for your Laravel app. Whatever you want your app to do on the front-end is completely up to you. You are in control of your application and you can use Voyager to make your life easier by adding data, editing users, creating menus, and many other administrative tasks.

## What it isn't

* A content management system (CMS)
* A blogging platform
* Wordpress (Bleh! 😜)

Voyager is not a CMS or a blogging platform. But it can be used to create a CMS or a blogging platform, but out of the box it is neither of those. As stated in the previous section you have full control on what your application will do and how it will function.

With Laravel & Voyager you can create any kind of application your heart desires. Laravel & Voyager are simply tools to make it easier to build.


# Installation

Voyager is super easy to install. After creating your new Laravel application you can include the Voyager package with the following command:

```bash
composer require tcg/voyager
```

Next make sure to create a new database and add your database credentials to your .env file, you will also want to add your application URL in the `APP_URL` variable:

```
APP_URL=http://localhost
DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
```

{% hint style="info" %}
**Using Laravel 5.4?**\
If you are installing with Laravel 5.4 you will need to [add the Service Provider manually](/1.1/getting-started/installation#adding-the-service-provider). Otherwise, if you are on 5.5 this happens automatically thanks to package auto-discovery.
{% endhint %}

Finally, we can install Voyager. You can choose to install Voyager with dummy data or without the dummy data. The dummy data will include 1 admin account (if no users already exist), 1 demo page, 4 demo posts, 2 categories and 7 settings.

To install Voyager without dummy data simply run

```bash
php artisan voyager:install
```

If you prefer installing it with the dummy data run the following command:

```bash
php artisan voyager:install --with-dummy
```

{% hint style="danger" %}
**Specified key was too long error**\
If you see this error message you have an outdated version of MySQL, use the following solution: <https://laravel-news.com/laravel-5-4-key-too-long-error>
{% endhint %}

And we're all good to go!

Start up a local development server with `php artisan serve` And, visit the URL <http://localhost:8000/admin> in your browser.

If you installed with the dummy data, a user has been created for you with the following login credentials:

> **email:** `admin@admin.com`\
> **password:** `password`

{% hint style="info" %}
**Quick note**\
A dummy user is **only** created if there are no current users in your database.
{% endhint %}

If you did not go with the dummy user, you may wish to assign admin priveleges to an existing user. This can easily be done by running this command:

```bash
php artisan voyager:admin your@email.com
```

If you wish to create a new admin user you can pass the `--create` flag, like so:

```bash
php artisan voyager:admin your@email.com --create
```

And you will be prompted for the users name and password.

## Advanced

This section is meant for users who are installing Voyager on an already existing Laravel installation or for users who want to perform a manual install. If this is not the case, you should go back to the [installation](/1.1/getting-started/installation) documentation or skip this section.

The first thing you should do is publish the assets that come with Voyager. You can do that by running the following commands:

```bash
php artisan vendor:publish --provider=VoyagerServiceProvider
php artisan vendor:publish --provider=ImageServiceProviderLaravel5
```

## Adding the Service Provider

{% hint style="info" %}
**This is only required if you are using Laravel 5.4!**\
If you are on Laravel 5.5+ you can skip this step.
{% endhint %}

To add the Voyager Service Provider open up your application `config/app.php` file and add `TCG\Voyager\VoyagerServiceProvider::class,` in the `providers` array like so:

```php
<?php

'providers' => [
    // Laravel Framework Service Providers...
    //...

    // Package Service Providers
    TCG\Voyager\VoyagerServiceProvider::class,
    // ...

    // Application Service Providers
    // ...
],
```


# Upgrading

## Upgrading 1.0 to 1.1

### Update your Composer.json

To update to the latest version inside of your composer.json file make sure to update the version of voyager inside the require declaration inside of your composer.json to:

`"tcg/voyager": "1.1.*"`

And then run `composer update`

### Run the necessary migrations

You will now need to run the following migrations to include new tables or rows that have been added to the latest version. you can find each of these migrations below:

```
https://github.com/the-control-group/voyager/blob/1.1/migrations/2017_11_26_013050_add_user_role_relationship.php
https://github.com/the-control-group/voyager/blob/1.1/migrations/2017_11_26_015000_create_user_roles_table.php
https://github.com/the-control-group/voyager/blob/1.1/migrations/2018_03_11_000000_add_user_settings.php
https://github.com/the-control-group/voyager/blob/1.1/migrations/2018_03_14_000000_add_details_to_data_types_table.php
https://github.com/the-control-group/voyager/blob/1.1/migrations/2018_03_16_000000_make_settings_value_nullable.php
```

You can do this by adding each of those migrations to your `database/migrations` folder and then run `php artisan migrate`

### Update Configuration

The `voyager.php` configuration file has had a few changes. The `prefix` key has been removed in favor of the `user.redirect` key. Please note that the `user.redirect` key should be prefixed with a slash (`/`), unlike the original `prefix` key.

### Multi Roles

Multi-roles is a new feature come by in v1.1 that allows you to have multiple roles and one primary role. You can fetch the user's primary role like normally using this:

```php
$user->role->name // Name of primary role
```

But now you can also use the new belongsToMany roles relationship to fetch all extra roles:

```php
$user->roles() // gets all extra roles relationship
$user->roles()->get() // gets all extra as a collection
```

Besides that there is a helper to get all the roles, both the primary and the extra roles:

```php
$user->roles_all() // collection of all roles
```

Please note, that you do not have to use the multi-roles and you can continue to use the primary role without any changes.

Also, make sure that you add the new data row into the database for the `users` data type. Insert a new row of data in the `data_rows` table. Make sure that it's `data_type_id` is the ID for the `users` data type, normally this would be ID `3`, but better make sure it is correct.

Then make sure the other fields are like below:

| field         | user\_belongstomany\_role\_relationship                                                                                                                        |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type          | relationship                                                                                                                                                   |
| display\_name | Roles                                                                                                                                                          |
| required      | 0                                                                                                                                                              |
| browse        | 1                                                                                                                                                              |
| read          | 1                                                                                                                                                              |
| edit          | 1                                                                                                                                                              |
| add           | 1                                                                                                                                                              |
| delete        | 0                                                                                                                                                              |
| details       | `{"model":"TCG\\Voyager\\Models\\Role","table":"roles","type":"belongsToMany","column":"id","key":"id","label":"name","pivot_table":"user_roles","pivot":"1"}` |
| order         | 11                                                                                                                                                             |

### Bread

The BREAD and Database section in Voyager has been separated into two sections. So in order to get access to the BREAD section using the menu, make sure to add the following menu item:

![](/files/-LQxjDYxOARLQinjktbz)

However, you might still not be able to see it, because it requires permission, so go ahead and create a new row in the `permissions` table with the `key` being `browse_bread`, leave the `table_name` to be `null`.

You should now be able to access the BREAD section.

## Translations

> If you have not translated any of the Voyager language strings, you may skip this step.

Voyager have changed its translations strings from being like `__('voyager.generic.close')` to be prefixed with the `voyager::` group.

Meaning that you would have to update your translated strings inside `resources/lang/LOCALE.json` to use the new prefix.

## Final Steps

Next, you may want to be sure that you have all the latest published assets. To re-publish the voyager assets you can run the following command:

```
php artisan vendor:publish --tag=voyager_assets --force
```

Then you may wish to clear your view cache by running the following command:

```
php artisan view:clear
```

## Troubleshooting

Be sure to ask us on our slack channel if you are experiencing any issues and we will try and assist. Thanks.


# Configurations

With the installation of Voyager you will find a new configuration file located at `config/voyager.php`.\
In this file you can find various options to change the configuration of your Voyager installation.

{% hint style="info" %}
If you cache your configuration files please make sure to run `php artisan config:clear` after you changed something.
{% endhint %}

Below we will take a deep dive into the configuration file and give a detailed description of each configuration set.

## Users

```php
<?php

'user' => [
    'add_default_role_on_register' => true,
    'default_role'                 => 'user',
    'admin_permission'             => 'browse_admin',
    'namespace'                    => App\User::class,
    'redirect'                     => '/admin'
],
```

**add\_default\_role\_on\_register:** Specify whether you would like to add the default role to any new user that is created.\
**default\_role:** You can also specify what the **default\_role** is of the user.\
**admin\_permission:** The permission needed to view the admin dashboard.\
**namespace:** The namespace of your apps User Class.\
**redirect:** Redirect path after the user logged in.

## Controller

```php
<?php

'controllers' => [
    'namespace' => 'TCG\\Voyager\\Http\\Controllers',
],
```

You can specify the default `controller` namespace of Voyager. If you ever wish to override any of the core functionality of Voyager you can do so by duplicating the Voyager controllers and specifying the location of your custom controllers.

{% hint style="info" %}
**Overwrite a single controller**\
If you only want to overwrite a single controller, you might consider adding the following piece of code to your `AppServiceProvider` class in the `register` method.\
`$this->app->bind(VoyagerBreadController::class, MyBreadController::class);`
{% endhint %}

## Model

```php
<?php

'models' => [
    //'namespace' => 'App\\',
],
```

You can specify the namespace or location of your models. This is used when creating the Models from the database section of Voyager. If not defined the default application namespace will be used.

## Assets

```php
<?php

'assets_path' => '/vendor/tcg/voyager/assets',
```

You may wish to specify a different asset path. If your site lives in a subfolder you may need to include that directory to the beginning of the path. This may also be used in case you wish to duplicate the published assets and customize your own.

{% hint style="info" %}
When upgrading to new version of voyager the assets located in the `/vendor/tcg/voyager/assets` directory may need to be overwritten, so if you wish to customize any styles you will want to duplicate that directory and specify the new location of your asset\_path.
{% endhint %}

## Storage

```php
<?php

'storage' => [
    'disk' => 'public',
],
```

By default Voyager is going to use the `public` local storage. You can additionally use any driver inside of your `config/filesystems.php`. This means you can use S3, Google Cloud Storage, or any other file storage system you would like.

## Database

```php
<?php

'database' => [
    'tables' => [
        'hidden' => ['migrations', 'data_rows', 'data_types', 'menu_items', 'password_resets', 'permission_role', 'settings'],
    ],
],
```

You may wish to hide some database tables in the Voyager database section. In the database config you can choose which tables would like to hide.

## Multilingual

```php
<?php

'multilingual' => [
    'enabled' => false,
    'default' => 'en',
    'locales' => [
        'en',
        //'pt',
    ],
],
```

You can specify whether or not you want to **enable** mutliple languages. You can then specify your **default** language and all the support languages (**locales**)

Read more about multilanguage [here](/1.1/core-concepts/multilanguage).

## Dashboard

```php
<?php

'dashboard' => [
    'navbar_items' => [
        'Profile' => [
            'route'         => 'voyager.profile',
            'classes'       => 'class-full-of-rum',
            'icon_class'    => 'voyager-person',
        ],
        'Home' => [
            'route'         => '/',
            'icon_class'    => 'voyager-home',
            'target_blank'  => true,
        ],
        'Logout' => [
            'route'      => 'voyager.logout',
            'icon_class' => 'voyager-power',
        ],
    ],
    'widgets' => [
        'TCG\\Voyager\\Widgets\\UserDimmer',
        'TCG\\Voyager\\Widgets\\PostDimmer',
        'TCG\\Voyager\\Widgets\\PageDimmer',
    ],
],
```

In the dashboard config you can add **navbar\_items**, make the **data\_tables** responsive, and manage your dashboard **widgets**.

**navbar\_items** Include a new route in the main user navbar dropdown by including a 'route', 'icon\_class', and 'target\_blank'.

**data\_tables** If you set 'responsive' to true the datatables will be responsive.

**widgets** Here you can manage the widgets that live on your dashboard. You can take a look at an example widget class by viewing the current widgets inside of `tcg/voyager/src/Widgets`.

## Primary color

```php
<?php

'primary_color' => '#22A7F0',
```

The default primary color for the Voyager admin dashboard is a light blue color. You can change that primary color by changing the value of this config.

## Show developer tips

```php
<?php

'show_dev_tips' => true,
```

In the Voyager admin there are developer tips or notifications that will show you how to reference certain values from Voyager. You can choose to hide these notifications by setting this configuration value to false.

## Additional stylesheets

```php
<?php

'additional_css' => [
    //'css/custom.css',
],
```

You can add your own custom stylesheets that will be included in the Voyager admin dashboard. This means you could technically create a whole new theme for Voyager by adding your own custom stylesheet.

Read more [here](/1.1/customization/additional-css-js).

{% hint style="info" %}
The path will be passed to Laravels [asset](https://laravel.com/docs/helpers#method-asset) function.
{% endhint %}

## Additional Javascript

```php
<?php

'additional_js' => [
    //'js/custom.js',
],
```

The same goes for this configuration. You can add your own javascript that will be executed in the Voyager admin dashboard. Add as many javascript files as needed.

Read more [here](/1.1/customization/additional-css-js).

## Google Maps

```php
<?php

'googlemaps' => [
    'key'    => env('GOOGLE_MAPS_KEY', ''),
    'center' => [
        'lat' => env('GOOGLE_MAPS_DEFAULT_CENTER_LAT', '32.715738'),
        'lng' => env('GOOGLE_MAPS_DEFAULT_CENTER_LNG', '-117.161084'),
    ],
    'zoom' => env('GOOGLE_MAPS_DEFAULT_ZOOM', 11),
],
```

There is a new data type called **coordinates** that allow you to add a google map as a datatype. The user can then drag and drop a pin in the Google Maps to save a longitude and latitude value in the database.

In this config you can set the default Google Maps Keys and center location. This can also be added to your .env file.


# Routing

After running the voyager installer you will see a few new routes that have been added to your `routes/web.php` file which look like the following:

```php
Route::group(['prefix' => 'admin'], function () {
    Voyager::routes();
});
```

This is where the Voyager routes will be rendered. You can change the `admin` prefix if you desire, or set any other route configuration you need, such as `middleware` or `domain`.

When creating a new BREAD type and specifying a slug for that BREAD, you can then visit that route from the following link:

```
URL/admin/slug-name
```

As an example, if we have a `products` table and we specified the slug to be `products`. You will now be able to visit the following URL:

```
URL/admin/products
```

{% hint style="info" %}
**Notice**\
You may not see a link to your newly created routes or BREAD inside your admin menu. To create a new link in your admin menu visit the documentation for the [menu section](/1.1/core-concepts/menus-and-menu-builder).
{% endhint %}


# Media Manager

Voyager has a full-fledged Media Manager which allows you to upload files, re-name files, and delete files. You can also add new folders and move files/folders. Basically anything that you would be able to do in any type of Media Manager you can do so in the Voyager Media Manager.

![](/files/-LrOVMDibnyMMYE7oDz-)

You may also drag and drop files onto the 'upload' button to upload multiple files.

{% hint style="info" %}
**Notice on File Upload Size**\
If you are getting an error when trying to upload large files, this may be a setting that needs to be changed in your PHP. Be sure to check `max_file_upload` and `file_upload_size`
{% endhint %}


# Menus and Menu Builder

With Voyager you can easily create menus for your application. In fact the Voyager admin is using the menu builder for the navigation you use on the left hand side.

You can view your current Menus by clicking on the *Tools->Menu Builder* button. You can add, edit, or delete any current menu. This means that you can create a new menu for the header, sidebar, or footer of your site. Create as many menus as you would like.

When you are ready to add menu items to your menu you can click on the builder button of the corresponding menu:

![](/files/-LrOUO_53SnAbZLfHGKQ)

This will take you to the Menu Builder where you can add, edit, and delete menu items.

![](/files/-LrOUO_75VwScr5uM7Ia)

After creating and configuring your menu, you can easily implement that menu in your application. Say that we have a menu called `main`. Inside of any view file we could now output the menu by using the following code:

```php
menu('main');
```

This will output your menu in an unstyled unordered list. If you do use bootstrap to stylize your web app you can pass a second argument to the menu display method telling it that you want to stylize the menu with bootstrap styles like so:

```php
menu('main', 'bootstrap');
```

Taking it one more step further you can even specify your own view and stylize your menu however you would like. Say for instance that we had a file located at `resources/views/my_menu.blade.php`, which contained the following code:

```markup
<ul>
    @foreach($items as $menu_item)
        <li><a href="{{ $menu_item->link() }}">{{ $menu_item->title }}</a></li>
    @endforeach
</ul>
```

Then anywhere you wanted to display your menu you can now call:

```php
menu('main', 'my_menu');
```

And your custom menu will now be output.

## Menu as JSON

If you dont want to render your menu but get an array instead, you can pass `_json` as the second parameter. For example:

```php
menu('main', '_json')
```

This will give you a collection of menu-items.


# Database Manager

Voyager has some awesome database tools which allow you to Add/Edit/Delete or view current database tables. The other cool part of Voyager is that you can add BREAD or (Browse, Read, Edit, Add, & Delete) functionality to any of your tables.

![](/files/-LrOVMEtUes3LIx906e-)

Inside of your admin panel you can visit Tools->Database and you'll be able to view all your current tables in your database. You may also click on 'Create a New Table' to create a new table in your database. All newly created tables will use the charset defined in your [default database connection](https://laravel.com/docs/database#configuration).

![](/files/-LrOVMEwIfTzLIcXY-up)

If you click the table name you can view the current schema. Additionally you can click on the View, Edit, or Delete buttons to perform that action for that table.

You may also choose to Add BREAD (Browse, Read, Edit, Add, & Delete) for any of your database tables. Once a table already has BREAD you may choose to edit the current BREAD or Delete the BREAD for that table.

Read on further about the BREAD builder in the next section.


# BREAD Builder

When adding or editing the current BREAD for a database table you will first see the BREAD info which allows you to set the Display Names, slug, icon, `Model` and Controller Namespace, Policy Name. You can also choose if you would like to Generate permissions for that BREAD type.

![](/files/-LrOVMIItVyfqzcxmTog)

When you scroll down you will see each of the rows that are associated with that table where you can select where in your views you want to see each of those fields:

* BROWSE (field will show up when you browse the current data)
* READ (field will show when you click to view the current data)
* EDIT (field will be visible and allow you to edit the data)
* ADD (field will be visible when you choose to create a new data type)
* DELETE (doesn't pertain to delete so this can be checked or unchecked)

![](/files/-LrOVMIMWx70F-V7bwRL)

You may also choose to specify what form type you want to use for each field. This can be a TextBox, TextArea, Checkbox, Image, and many other types of form elements.

Each field also has additional details or options that can be included. These types are checkbox, dropdown, radio button, and image.

## Additional Field Options

When Editing Your Browse, Read, Edit, Add, and Delete Rows you have a select box that allows you to include additional details or options for your datatype. This textarea accepts JSON and it applies to the following types of inputs:

* Text (Text Box, Text Area, Rich Textbox and Hidden)
* Check Box
* Drop Down
* Radio Button
* Image
* Date

Find out how to use these additional details below:

### Text (Text Box, Text Area, Rich Textbox and Hidden)

```php
{
    "default" : "Default text"
}
```

Text Box, Text Area, Rich Textbox and Hidden are all kind of texts inputs. In the JSON above you can specify the `default` value of the input.

### Check Box

```php
{
    "on" : "On Text",
    "off" : "Off Text",
    "checked" : "true"
}
```

In Voyager a Check Box is converted into a toggle switch, and as you can see above the `on` key will contain the value when the toggle switch is on, and the `off` will contain the value that is set when the switch is off. If `checked` is set to *true* the checkbox will be toggle on; otherwise by default it will be off.

### Drop Down

```php
{
    "default" : "option1",
    "options" : {
        "option1": "Option 1 Text",
        "option2": "Option 2 Text"
    }
}
```

When specifying that an input type should be a dropdown you will need to specify the values of that dropdown. In the JSON above you can specify the `default` value of the dropdown if it does not have a value. Additionally, in the `options` object you will specify the *value* of the option on the **left** and the *text* to be displayed on the **right**.

### Radio Button

```php
{
    "default" : "radio1",
    "options" : {
        "radio1": "Radio Button 1 Text",
        "radio2": "Radio Button 2 Text"
    }
}
```

The Radio button is exactly the same as the dropdown. You can specify a `default` if one has not been set and in the `options` object you will specify the *value* of the option on the **left** and the *text* to be displayed on the **right**.

### Image

```php
{
    "resize": {
        "width": "1000",
        "height": null
    },
    "quality" : "70%",
    "upsize" : true,
    "thumbnails": [
        {
            "name": "medium",
            "scale": "50%"
        },
        {
            "name": "small",
            "scale": "25%"
        },
        {
            "name": "cropped",
            "crop": {
                "width": "300",
                "height": "250"
            }
        }
    ]
}
```

The image input has many options. By default if you do not specify any options no problem... Your image will still be uploaded. But, if you want to resize an image, set the quality of the image, or specify thumbnails for the uploaded image you will need to specify those details.

**resize** If you want to specify a size you will need to include that in the `resize` object. If you set either **height** or **width** to null it will keep the aspect ratio based on the width or height that is set. So, for the example above the `width` is set to `1000` pixels and since the `height` is set to `null` it will resize the image width to 1000 pixels and resize the height based on the current aspect ratio.

**quality** If you wish to compress the image with a percentage quality you can specify that percentage in the `quality` key. Typically between 70 and 100% there is little notice of image quality, but the image size may be dramatically lower.

**upsize** This is only valid if you have set your image to be resized. If you specify your image to resized to 1000 pixels and the image is smaller than 1000 pixels by default it will not upsize that image to the 1000 pixels; however, if you set `upsize` to true. It will upsize all images to your specified resize values.

**thumbnails** Thumbnails takes an array of objects. Each object is a new thumbnail that is created. Each object contains 2 values, the `name` and `scale` percentage. The `name` will be attached to your thumbnail image (as an example say the image you uploaded was ABC.jpg a thumbnail with the `name` of `medium` would now be created at ABC-medium.jpg). The `scale` is the percentage amount you want that thumbnail to scale. This value will be a percentage of the *resize* width and height if specified.

### Date & Timestamp

```php
{
    "format" : "%Y-%m-%d"
}
```

The date & timestamp input field is where you can input a date. In the JSON above you can specify the `format` value of the output of the date. It allows you to display a formatted `date` in browse and read views, using Carbon's `formatLocalized()` method

## Description

All types can include a description in order to help your future self or other users using your Voyager admin panel to understand exactly what a specific BREAD input field is for, this can be defined in the `Optional Details` JSON input field:

```php
{
    "description": "A helpful description text here for your future self."
}
```

## Validation

Inside of the *Optional Details* section for each row in your BREAD you can also specify validation rules with some simple JSON. Here is an example of how to add a validation rule or *required* and *max length of 12*

```php
{
    "validation": {
        "rule": "required|max:12"
    }
}
```

Additionally, you may wish to add some custom error messages which can be accomplished like so:

```php
{
    "validation": {
        "rule": "required|max:12",
        "messages": {
            "required": "This :attribute field is a must.",
            "max": "This :attribute field maximum :max."
        }
    }
}
```

Since `v0.10.13` you can do the `required` and `max:12` rule the following way:

```php
{
    "validation": {
        "rules": [
            "required",
            "max:12"
        ]
    }
}
```

You can find a list of all available validation rules in the [Laravel docs](https://laravel.com/docs/validation#available-validation-rules).

## Generating Slugs

Using the bread builder you may wish to automatically generate slugs of a certain input. Lets say you have some posts, which have a title and a slug. If you want to automatically generate the slug from the title attribute, you may include the following *Optional Details*:

```php
{
    "slugify": {
        "origin": "title",
        "forceUpdate": true
    }
}
```

This will automatically generate the slug from the input of the `title` field. If a slug does already exists, it will only be updated if `forceUpdate` is set enabled, by default this is disabled.

## Relationships

Using the BREAD builder you can easily create Relationships between tables. At the bottom of the page you will see a new button that says 'Create Relationship'

![](/files/-LrOVMHPClygrOaaG2o_)

{% hint style="info" %}
**Notice**\
If you have not yet created the BREAD for the table yet, it will need to be created first and then you can come back after creating the BREAD to add the relationship. Otherwise you'll end up with a notification which looks like the following.
{% endhint %}

![](/files/-LrOVMHTtSeOMaYnk2cj)

So, after the BREAD has already been created you will then be able to create a new relationship. After you click on the 'Create a Relationship' button. You will see a new Modal window that looks like the following:

![](/files/-LrOVMHV_E_9RU05lE6w)

You will first specify which type of relationship this is going to be, then you will select the table you are referencing and which Namespace that belongs to that table. You will then select which row combines those tables.

You can also specify which columns you would like to see in the dropdown or the multi-select.

Now, you can easily create `belongsTo`, `belongsToMany`, `hasOne`, and `hasMany` relationships directly in Voyager.

## Tagging

Tagging gives you the possibility to add new items to a Belongs-To-Many relationship directly when editing or adding a BREAD.

To activate this function, you simply have to enable `Tagging` in the relationship details

![](/files/-LrOVMIPmLdNCx2OWB6R)

After that you can enter a free-text into the select and hit enter to save a new relationship.

{% hint style="info" %}
**Be aware:**

This only stores the `display-column` so you have to make sure that all other fields are either nullable or have a default value.
{% endhint %}

## Null Values

You might want to save an input field into the database as a `null` value instead of an empty string.

Simply enough, inside the BREAD you can include the following *Optional Details* for the field:

```php
{
    "null": ""
}
```

This will turn an empty string into a `null` value. However you might want to be able to add both an empty string and a `null` value to the database for that field. However you have to choose a replacement for the `null` value, but it can be anything you wish. For example, if you want a field to change a string (ex. `Nothing`) into a `null` value you could include the following *Optional Details* for that field:

```php
{
    "null": "Nothing"
}
```

Now entering `Nothing` into the field will end up as a `null` value in the database.

## Display options

There are also a few options that you can include to change the way your BREAD is displayed. You can add a `display` key to your json object and change the width of the particular field and even specify a custom ID.

```php
{
    "display": {
        "width": "3",
        "id": "custom_id"
    }
}
```

The width is displayed on a 12-grid system. Setting it with a width of 3 will span 25% of the width.

The **id** will let you specify a custom id wrapper around your element. example:

```markup
<div id="custom_id">
    <!-- Your field element -->
</div>
```

## Ordering Bread Items

You can define the default order for browsing BREADs and order your BREAD items with drag-and-drop.\
For this you need to change the settings for your BREAD first:

![](/files/-LrOVMIRYEVrkFMc-KyO)

**Order column** is the field in your table where the order is stored as an integer.\
**Order display column** is the field which is shown in the drag-drop list.\
**Order direction** the direction in which the field is ordered.

After this you can go to your BREAD-browse page and you will see a button **Order.**\
Clicking this button will bring you to the page where you can re-arrange your items:

![](/files/-LrOVMITVM9FMcPrHXnB)


# Settings

The Settings section allows you to add any site wide settings you would like. You can add an image upload setting for your site logo or a text box for the main headline on your homepage.

![](/files/-LrOUOotWDe5Kd3BtdnR)

In this new version you have the ability to add different groups for different settings. So, if you created a new setting inside of the `site` group and it had a key of `title` you would then be able to reference that setting any where on your site by doing the following:

```php
<?php
echo setting('site.title');
```

Or inside of any blade template like:

```
{{ setting('site.title') }}
```

So, now you can add all kinds of settings in Voyager and reference them in your application.


# Compass

The Compass section is a quick place for you to go for some link references, font references, run some commands or view some logs.

In the first tab you will see a few link resources and you will see all the fonts that you can use inside of Voyager.

![](/files/-LrOVMFr0W0_QXgXFBK_)

In the Command section you can actually run some artisan commands directly from Voyager.

![](/files/-LrOVMFuqU1n75-c7ib8)

And Lastly, under the Logs tab you will be able to view all your application logs.

![](/files/-LrOVMFwFYriPLMNcG8a)


# Roles and Permissions

Voyager comes with Roles and Permissions out of the box. Each *User* has a *Role* which has a set of *Permissions*.

Inside of the dashboard you can choose to Add, Edit, or delete the current Roles. Additionally when you click to edit a particular role you can specify the BREAD permissions.

![](/files/-LQxkyYsXLEAqp646dRI)

New in version 1.0, we've changed Voyager's authorization system to be [more in line with Laravel](https://laravel.com/docs/5.5/authorization#authorizing-actions-using-policies)! This means that you can check for permissions in the following ways:

```php
// via user object
$canViewPost = $user->can('read', $post);
$canViewPost = Auth::user()->can('read', $post);

// via controller
$canViewPost = $this->authorize('read', $post);
```

You may also choose to use the Voyager facade and pass the permission as a string:

```php
$canBrowsePost = Voyager::can('browse_posts');
$canViewPost = Voyager::can('read_posts');
$canEditPost = Voyager::can('edit_posts');
$canAddPost = Voyager::can('add_posts');
$canDeletePost = Voyager::can('delete_posts');
```

The value of each check will return a boolean whether or not the user has that certain permission. However you might wish to throw a forbidden exception if the user does not have a certain permission. This can be done using the `canOrFail` method:

```php
Voyager::canOrFail('browse_admin');
```

Out of the box there are some permissions you can use by default:

* `browse_admin`: Whether or not the user may browse the Voyager admin panel.
* `browse_database`: Whether or not the user may browse the Voyager database menu section.
* `browse_bread`: Whether or not the user may browse the Voyager BREAD menu section.
* `browse_media`: Whether or not the user may browse the Voyager media section.
* `browse_menu`: Whether or not the user may browse the Voyager menu section.
* `browse_settings`: Whether or not the user may browse the Voyager settings section.
* `read_settings`: Whether or not the user can view or see a particular setting.
* `edit_settings`: Whether or not the user can edit a particular setting.
* `add_settings`: Whether or not the user can add a new setting.
* `delete_settings`: Whether or not the user can delete a particular setting.

Additionally you can `Generate permissions` for every BREAD type you create. This will create the `browse`, `read`, `edit`, `add` and `delete` permission.

As an example, perhaps we are creating a new BREAD type from a `products` table. If we choose to `Generate permissions` for our `products` table. Our permission keys will be `browse_products`, `read_products`, `edit_products`, `add_products` and `delete_products`.

{% hint style="info" %}
**Notice**\
If a menu item is associated with any kind of BREAD, then it will check for the `browse` permission, for example for the `Posts` BREAD menu item, it will check for the `browse_posts` permission. If the user does not have the required permission, that menu item will be hidden.
{% endhint %}

## Using Permissions in your Blade Template files

You can also check for permissions using blade syntax. Let's say for instance that you want to check if a user can `browse_posts`, simple enough we can use the following syntax:

```php
@can('browse', $post)
    I can browse posts
@endcan
```

Or perhaps you need to run an else condition for a permission. That's simple enough:

```php
@can('browse', $post)
    I can browse posts
@else
    I cannot browse posts
@endcan
```

Couldn't be easier, right ;)


# Helper methods

Voyager has several helper functions that are ready to use. Here you can find the list of available function that may speed up your development.

## Thumbnails URL

Voyager will generate thumbnails for Image field type when you specify the [additional field options](/1.1/core-concepts/bread-builder#additional-field-options).

After you have your thumbnails generated, you may want to display the thumbnails in your view or get the thumbnail URL. In order to do that you need to add `Resizable` traits to your model.

```php
use TCG\Voyager\Traits\Resizable;

class Post extends Model
{
    use Resizable;
}
```

#### Display a single image

```php
@foreach($posts as $post)
    <img src="{{Voyager::image($post->thumbnail('small'))}}" />
@endforeach
```

Or you can specify the optional image field name (attribute), default to `image`

```php
@foreach($posts as $post)
    <img src="{{Voyager::image($post->thumbnail('small', 'photo'))}}" />
@endforeach
```

#### Display multiple images

```php
@foreach($posts as $post)
    $images = json_decode($post->images);
    @foreach($images as $image)
        <img src="{{ Voyager::image($post->getThumbnail($image, 'small')) }}" />
    @endforeach
@endforeach
```


# Multilanguage

Voyager supports multiple languages for your models.To get started, you need to configure some things first.

## Setup

First you need to define some `locales` in your `config/voyager.php` file and `enable` multilanguage:

```php
'multilingual' => [
        'enabled' => true,
        'rtl' => false,
        'default' => 'en',
        'locales' => [
            'en',
            'da',
        ],
    ],
```

After that you need to include the `Translatable` Trait in your model and define the translatable attributes:

```php
use TCG\Voyager\Traits\Translatable;
class Post extends Model
{
    use Translatable;
    protected $translatable = ['title', 'body'];
}
```

Now you will see a language-selection in your Pages BREAD.

## Usage

### Eager-load translations

```php
// Loads all translations
$posts = Post::with('translations')->get();

// Loads all translations
$posts = Post::all();
$posts->load('translations');

// Loads all translations
$posts = Post::withTranslations()->get();

// Loads specific locales translations
$posts = Post::withTranslations(['en', 'da'])->get();

// Loads specific locale translations
$posts = Post::withTranslation('da')->get();

// Loads current locale translations
$posts = Post::withTranslation('da')->get();
```

### Get default language value

```php
echo $post->title;
```

### Get translated value

```php
echo $post->getTranslatedAttribute('title', 'locale', 'fallbackLocale');
```

If you do not define locale, the current application locale will be used. You can pass in your own locale as a string. If you do not define fallbackLocale, the current application fallback locale will be used. You can pass your own locale as a string. If you want to turn the fallback locale off, pass false. If no values are found for the model for a specific attribute, either for the locale or the fallback, it will set that attribute to null.

### Translate the whole model

```php
$post = $post->translate('locale', 'fallbackLocale');
echo $post->title;
echo $post->body;

// You can also run the `translate` method on the Eloquent collection
// to translate all models in the collection.
$posts = $posts->translate('locale', 'fallbackLocale');
echo $posts[0]->title;
```

If you do not define locale, the current application locale will be used. You can pass in your own locale as a string. If you do not define fallbackLocale, the current application fallback locale will be used. You can pass in your own locale as a string. If you want to turn the fallback locale off, pass false. If no values are found for the model for a specific attribute, either for the locale or the fallback, it will set that attribute to null.

### Check if model is translatable

```php
// with string
if (Voyager::translatable(Post::class)) {
    // it's translatable
}

// with object of Model or Collection
if (Voyager::translatable($post)) {
    // it's translatable
}
```

### Set attribute translations

```php
$post = $post->translate('da');
$post->title = 'foobar';
$post->save();
```

This will update or create the translation for title of the post with the locale da. Please note that if a modified attribute is not translatable, then it will make the changes directly to the model itself. Meaning that it will overwrite the attribute in the language set as default.


# Overriding files

## Overriding BREAD Views

You can override any of the BREAD views for a **single** BREAD by creating a new folder in `resources/views/vendor/voyager/slug-name` where *slug-name* is the *slug* that you have assigned for that table. There are 4 files that you can override:

* browse.blade.php
* edit-add.blade.php
* read.blade.php
* order.blade.php

Alternatively you can override the views for **all** BREADs by creating any of the above files under `resources/views/vendor/voyager/bread`

## Using custom Controllers

You can override the controller for a single BREAD by creating a controller which extends Voyagers controller, for example:

```php
<?php

namespace App\Http\Controllers;

class VoyagerCategoriesController extends \TCG\Voyager\Http\Controllers\VoyagerBaseController
{
    //...
}
```

After that go to the BREAD-settings and fill in the Controller Name with your fully-qualified class-name:

![](/files/-LrOVME3022kFwRdRYST)

You can now override all methods from the [VoyagerBaseController](https://github.com/the-control-group/voyager/blob/1.1/src/Http/Controllers/VoyagerBaseController.php)

## Overriding Voyagers Controllers

If you want to override any of Voyagers core controllers you first have to change your config file `config/voyager.php`:

```php
/*
|--------------------------------------------------------------------------
| Controllers config
|--------------------------------------------------------------------------
|
| Here you can specify voyager controller settings
|
*/
​
'controllers' => [
    'namespace' => 'App\\Http\\Controllers\\Voyager',
],
```

Then run `php artisan voyager:controllers`, Voyager will now use the child controllers which will be created at `App/Http/Controllers/Voyager`

## Overriding Voyager-Models

You are also able to override Voyagers models if you need to.\
To do so, you need to add the following to your AppServiceProviders register method:

```php
Voyager::useModel($name, $object);
```

Where **name** is the class-name of the model and **object** the fully-qualified name of your custom model. For example:

```php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Events\Dispatcher;
use TCG\Voyager\Facades\Voyager;

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        Voyager::useModel('DataRow', \App\DataRow::class);
    }
    // ...
}
```

The next step is to create your model and make it extend the original model. In case of `DataRow`:

```php
<?php

namespace App;

class DataRow extends \TCG\Voyager\Models\DataRow
{
    // ...
}
```


# Overriding Routes

You can override any Voyager routes by writing the routes you want to overwrite below `Voyager::routes()`. For example if you want to override your post LoginController:

```php
Route::group(['prefix' => 'admin'], function () {
   Voyager::routes();

   // Your overwrites here
   Route::post('login', ['uses' => 'MyAuthController@postLogin', 'as' => 'postlogin']);
});
```


# Additional CSS and JS

As of the latest version you can now add additional CSS and JS files to the voyager master blade without having to copy or modify the blade file itself removing potential manual migration headaches later on. The CSS and JS files are added *after* any Voyager assets so you can override styles and functionality comfortably.

This is all handled via the `voyager.php` config file:

```php
// Here you can specify additional assets you would like to be included in the master.blade
'additional_css' => [
    //'css/custom.css',
],
'additional_js' => [
   //'js/custom.js',
],
```

{% hint style="info" %}
The path will be passed to Laravels [asset](https://laravel.com/docs/helpers#method-asset) function.
{% endhint %}


# Enabling Soft-Delete

This is only to assist with enabling soft-deletion for your models within Voyager. Please refer to the [Laravel documentation](https://laravel.com/docs/eloquent#soft-deleting) for specifics.

## Table Configurations in Voyager

When creating a table using the Database Manager you've selected the 'Add Soft Deletes' button and then when adding the BREAD functionality to that table you've added a Model Name, you only have to edit your Model file to fully enable Soft-Delete on that table.

## Editing the Table's Model

A default model will look like this:

```php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;


class YourModelName extends Model
{

}
```

Just turn it into:

```php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;


class Documento extends Model
{
    use SoftDeletes;
    protected $dates = ['deleted_at'];
}
```

And from now on, every time you delete a record from that table, it won't actually be deleted, only the `deleted_at` column will be written with the current timestamp.


# Custom relationship attributes

With Voyager 1.1 you are able to define additional attributes which you can show in a relationship.

For example a `Post` has an `Author` and you want to display the `Users` full-name. To do so, we first need to [define an Accessor](https://laravel.com/docs/eloquent-mutators#defining-an-accessor)

```php
public function getFullNameAttribute()
{
    return "{$this->first_name} {$this->last_name}";
}
```

After that we need to tell Voyager that there is an accessor we want to use:

```php
public $additional_attributes = ['full_name'];
```

Thats it! You can now select `full_name` in your Relationship.


# TinyMCE

If you want to customize TinyMCE within Voyager, you can do so by adding a [additional JS file](/1.1/customization/additional-css-js) to your config.

In this file you have to define a function like

```javascript
function tinymce_init_callback(editor)
{
    //...
}
```

Now you can control the TinyMCE instance(s) on the page. For all possible variables and functions, please refer to the [TinyMCE documentation](https://www.tinymce.com/docs/api/tinymce/tinymce.editor/).


# Adding custom Formfields

You can easily add a new Formfield to Voyager. In the example below we will add a number form field (which is already included by default in Voyager).

First we create a new class in our project (it doesn't matter where it is placed) called `NumberFormField`

```php
<?php

namespace App\FormFields;

use TCG\Voyager\FormFields\AbstractHandler;

class NumberFormField extends AbstractHandler
{
    protected $codename = 'number';

    public function createContent($row, $dataType, $dataTypeContent, $options)
    {
        return view('formfields.number', [
            'row' => $row,
            'options' => $options,
            'dataType' => $dataType,
            'dataTypeContent' => $dataTypeContent
        ]);
    }
}
```

The `codename` variable is used in the dropdown you see in the BREAD builder. In the `createContent` method we are returning the view that is used to display our form field.

Next, we will create the view specified above.

```markup
<input type="number"
       class="form-control"
       name="{{ $row->field }}"
       data-name="{{ $row->display_name }}"
       type="number"
       @if($row->required == 1) required @endif
             step="any"
       placeholder="{{ isset($options->placeholder)? old($row->field, $options->placeholder): $row->display_name }}"
       value="@if(isset($dataTypeContent->{$row->field})){{ old($row->field, $dataTypeContent->{$row->field}) }}@else{{old($row->field)}}@endif">
```

In the view we can add whatever logic we want.

When we are done with our view, we will tell Voyager that we have a new form field. We will do this in a service provider (in the example below we use the `AppServiceProvider`.

```php
<?php

namespace App\Providers;

use TCG\Voyager\Facades\Voyager;
use App\FormFields\NumberFormField;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    //..

    public function register()
    {
        Voyager::addFormField(NumberFormField::class);
    }
}
```


# Coordinates

With Voyager you are able to store coordinates and select them from a map.\
To do so, you first need to make sure that the column in your table is either `GEOMETRY` or `POINT`.

After that you have to include the Spatial-Trait in your Model and define the column:

```php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use TCG\Voyager\Traits\Spatial;

class Category extends Model
{
    use Spatial;
    
    protected $spatial = ['your_column'];
}
```

Now you can go to the tables BREAD-settings and set your field to be `Coordinates`.

After that you will get a Map where you can select your Coordinates.

{% hint style="info" %}
Make sure to set the Google Maps API-Key in your [configuration](/1.1/getting-started/configurations#google-maps).\
This is also the place where you can define the default location of your map.
{% endhint %}

## Getting the coordinates

You can get the coordinates from your model by calling

```php
$model->getCoordinates();
```

This will return an array of coordinates with `lat` as the latitude and `lng` as the longitude.


# Using HTTPS on yours site

**Symptom:** When visiting your site with HTTPS, images within Voyager fail to load.

**Cause:** Images urls are generated by Voyager using

```php
Storage::disk(config('voyager.storage.disk'))->url($file);
```

If voyager.storage.disk is set to public, and the public disk is the default from Laravel, then the url property in the disk configuration is set to

```php
'url' => env('APP_URL').'/storage',
```

which uses the non-HTTPS APP\_URL value to build an absolute url to the image.

**Solution:** If you remove env('APP\_URL'). from the public disk configuration, then it will render a domain-relative url, which will always use the current domain and protocol.

As an aside, if you need a fully-qualified URL, you could wrap the call to `Voyager::image('...')` with `asset()`, so it would be

```php
asset(Voyager::image('...'))
```

This will return the current protocol, domain, and correct path to that image.


# Missing required parameter

**Symptom:** You get an error page saying

```
Missing required parameters for [Route...]
```

**Cause:** There are two possible causes:\
1\. You dont have a primary-key for your table\
2\. You have a primary-key but it's **not** called `id`

**Solution:** As there are two causes, there are also two solutions: 1. Simply create a field `id` for the table\
2\. Tell your model about your primary-key: `protected $primaryKey = 'your_primary_key';`

Please consider following [Eloquents model conventions](https://laravel.com/docs/eloquent#eloquent-model-conventions)


# Introduction

Welcome to the Voyager documentation for version 1.2. This documentation will teach you how to install, configure, and use Voyager so that way you can create some kick ass stuff!

Hm Hm (cough)… I mean… Arrgg! Ye young scallywag! What say we learn how to steer this ship!

![Voyager Screenshot](https://s3.amazonaws.com/thecontrolgroup/voyager-screenshot.png)

Before installing Voyager you may want to take a quick moment to learn what is is and what it isn't, we'll do that in the next section.


# What is Voyager

Before installing Voyager it is very important to take a quick moment to learn *what it is* & *what it isn't*.

## What it is

* An admin interface for your Laravel app
* An easy way to add/edit/delete data for your app
* A menu builder (build menus in Voyager for your app)
* A media manager for your files
* CRUD/BREAD generator ([learn more about BREAD here](/1.2/bread/introduction))

Voyager is simply an admin for your Laravel app. Whatever you want your app to do on the front-end is completely up to you. You are in control of your application and you can use Voyager to make your life easier by adding data, editing users, creating menus, and many other administrative tasks.

## What it isn't

* A content management system (CMS)
* A blogging platform
* Wordpress (Bleh! 😜)

Voyager is not a CMS or a blogging platform. But it can be used to create a CMS or a blogging platform, but out of the box it is neither of those. As stated in the previous section you have full control on what your application will do and how it will function.

With Laravel & Voyager you can create any kind of application your heart desires. Laravel & Voyager are simply tools to make it easier to build.


# Installation

Voyager is super easy to install. After creating your new Laravel application you can include the Voyager package with the following command:

```bash
composer require tcg/voyager
```

Next make sure to create a new database and add your database credentials to your .env file, you will also want to add your application URL in the `APP_URL` variable:

```
APP_URL=http://localhost
DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
```

{% hint style="info" %}
**Using Laravel 5.4?**\
If you are installing with Laravel 5.4 you will need to [add the Service Provider manually](/1.2/getting-started/installation#adding-the-service-provider). Otherwise, if you are on 5.5 this happens automatically thanks to package auto-discovery.
{% endhint %}

Finally, we can install Voyager. You can choose to install Voyager with dummy data or without the dummy data. The dummy data will include 1 admin account (if no users already exist), 1 demo page, 4 demo posts, 2 categories and 7 settings.

To install Voyager without dummy data simply run

```bash
php artisan voyager:install
```

If you prefer installing it with the dummy data run the following command:

```bash
php artisan voyager:install --with-dummy
```

{% hint style="danger" %}
**Specified key was too long error**\
If you see this error message you have an outdated version of MySQL, use the following solution: <https://laravel-news.com/laravel-5-4-key-too-long-error>
{% endhint %}

And we're all good to go!

Start up a local development server with `php artisan serve` And, visit the URL <http://localhost:8000/admin> in your browser.

If you installed with the dummy data, a user has been created for you with the following login credentials:

> **email:** `admin@admin.com`\
> **password:** `password`

{% hint style="info" %}
**Quick note**\
A dummy user is **only** created if there are no current users in your database.
{% endhint %}

If you did not go with the dummy user, you may wish to assign admin priveleges to an existing user. This can easily be done by running this command:

```bash
php artisan voyager:admin your@email.com
```

If you wish to create a new admin user you can pass the `--create` flag, like so:

```bash
php artisan voyager:admin your@email.com --create
```

And you will be prompted for the users name and password.

## Adding the Service Provider

{% hint style="info" %}
**This is only required if you are using Laravel 5.4!**\
If you are on Laravel 5.5+ you can skip this step.
{% endhint %}

To add the Voyager Service Provider open up your application `config/app.php` file and add `TCG\Voyager\VoyagerServiceProvider::class,` in the `providers` array like so:

```php
<?php

'providers' => [
    // Laravel Framework Service Providers...
    //...

    // Package Service Providers
    TCG\Voyager\VoyagerServiceProvider::class,
    // ...

    // Application Service Providers
    // ...
],
```

## Advanced

This section is meant for users who are installing Voyager on an already existing Laravel installation or for users who want to perform a manual install. If this is not the case, you should go back to the [installation](/1.2/getting-started/installation) documentation or skip this section.

The first thing you should do is publish the assets that come with Voyager. You can do that by running the following commands:

```bash
php artisan vendor:publish --provider="TCG\Voyager\VoyagerServiceProvider"
php artisan vendor:publish --provider="Intervention\Image\ImageServiceProviderLaravel5"
```

Next, call `php artisan migrate` to migrate all Voyager table.

{% hint style="info" %}
If you want to change migrations, for example to use a different table for users, don't migrate. Instead copy Voyagers migrations to `database/migrations`, make your changes, turn off the config option `database.autoload_migrations` and then migrate.
{% endhint %}

Now, open your User-Model (usually `app/User.php`) and make the class extend `\TCG\Voyager\Models\User` instead of `Authenticatable`.

```php
<?php

class User extends \TCG\Voyager\Models\User
{
    // ...
}
```

The next step is to add Voyagers routes to your `routes/web.php` file:

```php
<?php

Route::group(['prefix' => 'admin'], function () {
    Voyager::routes();
});
```

Now run\
`php artisan db:seed --class=VoyagerDatabaseSeeder`\
to seed some necessary data to your database,\
`php artisan hook:setup`\
to install the hooks system, and\
`php artisan storage:link`\
to create the storage symlink to your public folder.

After that, run `composer dump-autoload` to finish your installation!


# Upgrading

## Upgrading 1.1 to 1.2

### Laravel and PHP versions

Support for Laravel 5.4 was dropped in Voyager 1.2 and therefore the minimum PHP version is now 7.1.\
Please update your versions accordingly!

### Update your Composer.json

To update to the latest version inside of your composer.json file make sure to update the version of Voyager inside the require declaration inside of your composer.json to:

`tcg/voyager": "1.2.*`

And then run composer update

### Update Configuration

The `voyager.php` configuration file had a few changes.

```php
'storage' => [
    'disk' => 'public',
],
```

is now

```php
'storage' => [
    'disk' => env('FILESYSTEM_DRIVER', 'public'),
],
```

Also, the option

```php
'database' => [
    'autoload_migrations' => true,
]
```

was added. This allows you to exclude Voyagers migration-files from loading when running `php artisan migrate`.

There is a new section titled **Model specific settings** that contains new settings for Compass, cache and media-manager.

**Compass** is now switched off automatically when the environment is not `local`.\
This can be overriden by the following new config-key:

```php
'compass_in_production' => true,
```

New **cache** setting:

```php
    'settings' => [
        // Enables Laravel cache method for
        // storing cache values between requests
        'cache' => false,
    ],
```

The **media-manager** got some new configuration-options:

```php
'media' => [
    // The allowed mimetypes to be uploaded through the media-manager.
    'allowed_mimetypes' => '*', //All types can be uploaded

    /*'allowed_mimetypes' => [
        'image/jpeg',
        'image/png',
        'image/gif',
        'image/bmp',
        'video/mp4',
    ],*/

    //Path for media-manager. Relative to the filesystem.
    'path'                => '/',
    'show_folders'        => true,
    'allow_upload'        => true,
    'allow_move'          => true,
    'allow_delete'        => true,
    'allow_create_folder' => true,
    'allow_rename'        => true,
],
```

The top dropdown-items can now be translated by providing a language-key:

```php
<?php

'navbar_items' => [
    'voyager::generic.profile' => [
        'route'      => 'voyager.profile',
        'classes'    => 'class-full-of-rum',
        'icon_class' => 'voyager-person',
    ],
    'voyager::generic.home' => [
        'route'        => '/',
        'icon_class'   => 'voyager-home',
        'target_blank' => true,
    ],
    'voyager::generic.logout' => [
        'route'      => 'voyager.logout',
        'icon_class' => 'voyager-power',
    ],
],
```

If you were using casts in your user-model previously, please remove the array-cast of `settings`.

### Deprecation

`can`, `canOrAbort`, `canOrFail` in the Voyager facade were all removed in favor of Policies and Gates.\
Please refer to the [Laravel documentation](https://laravel.com/docs/authorization).

### User BREAD

The User BREAD now has its own controller. Please update your User BREAD to use `TCG\Voyager\Http\Controllers\VoyagerUserController` as the controller: ![](/files/-M246M8sZmO07QNk7kLj)

### Final Steps

Voyager changed its way on how to load assets.\
Assets don't get published anymore, instead they are loaded directly from the package.\
Because of that, you can safely remove everything from your `public/vendor/tcg/voyager` folder.\
Also you can remove the `assets_path` config-key from `config/voyager.php`.

## Troubleshooting

Be sure to ask us on our slack channel if you are experiencing any issues and we will try and assist. Thanks.


# Configurations

With the installation of Voyager you will find a new configuration file located at `config/voyager.php`.\
In this file you can find various options to change the configuration of your Voyager installation.

{% hint style="info" %}
If you cache your configuration files please make sure to run `php artisan config:clear` after you changed something.
{% endhint %}

Below we will take a deep dive into the configuration file and give a detailed description of each configuration set.

## Users

```php
<?php

'user' => [
    'add_default_role_on_register' => true,
    'default_role'                 => 'user',
    'admin_permission'             => 'browse_admin',
    'namespace'                    => App\User::class,
    'redirect'                     => '/admin'
],
```

**add\_default\_role\_on\_register:** Specify whether you would like to add the default role to any new user that is created.\
**default\_role:** You can also specify what the **default\_role** is of the user.\
**admin\_permission:** The permission needed to view the admin dashboard.\
**namespace:** The namespace of your apps User Class.\
**redirect:** Redirect path after the user logged in.

## Controller

```php
<?php

'controllers' => [
    'namespace' => 'TCG\\Voyager\\Http\\Controllers',
],
```

You can specify the default `controller` namespace of Voyager. If you ever wish to override any of the core functionality of Voyager you can do so by duplicating the Voyager controllers and specifying the location of your custom controllers.

{% hint style="info" %}
**Overwrite a single controller**\
If you only want to overwrite a single controller, you might consider adding the following piece of code to your `AppServiceProvider` class in the `register` method.\
`$this->app->bind(VoyagerBreadController::class, MyBreadController::class);`
{% endhint %}

## Model

```php
<?php

'models' => [
    //'namespace' => 'App\\',
],
```

You can specify the namespace or location of your models. This is used when creating the Models from the database section of Voyager. If not defined the default application namespace will be used.

## Assets

```php
<?php

'assets_path' => '/vendor/tcg/voyager/assets',
```

You may wish to specify a different asset path. If your site lives in a subfolder you may need to include that directory to the beginning of the path. This may also be used in case you wish to duplicate the published assets and customize your own.

{% hint style="info" %}
When upgrading to new version of voyager the assets located in the `/vendor/tcg/voyager/assets` directory may need to be overwritten, so if you wish to customize any styles you will want to duplicate that directory and specify the new location of your asset\_path.
{% endhint %}

## Storage

```php
<?php

'storage' => [
    'disk' => 'public',
],
```

By default Voyager is going to use the `public` local storage. You can additionally use any driver inside of your `config/filesystems.php`. This means you can use S3, Google Cloud Storage, or any other file storage system you would like.

## Database

```php
<?php

'database' => [
    'tables' => [
        'hidden' => ['migrations', 'data_rows', 'data_types', 'menu_items', 'password_resets', 'permission_role', 'settings'],
    ],
    'autoload_migrations' => true,
],
```

You may wish to hide some database tables in the Voyager database section. In the database config you can choose which tables would like to hide.\
`autoload_migrations` allows you to exclude Voyagers migration-files from loading when running `php artisan migrate`.

## Multilingual

```php
<?php

'multilingual' => [
    'enabled' => false,
    'default' => 'en',
    'locales' => [
        'en',
        //'pt',
    ],
],
```

You can specify whether or not you want to **enable** mutliple languages. You can then specify your **default** language and all the support languages (**locales**)

Read more about multilanguage [here](/1.2/core-concepts/multilanguage).

## Dashboard

```php
<?php

'dashboard' => [
    'navbar_items' => [
        'Profile' => [
            'route'         => 'voyager.profile',
            'classes'       => 'class-full-of-rum',
            'icon_class'    => 'voyager-person',
        ],
        'Home' => [
            'route'         => '/',
            'icon_class'    => 'voyager-home',
            'target_blank'  => true,
        ],
        'Logout' => [
            'route'      => 'voyager.logout',
            'icon_class' => 'voyager-power',
        ],
    ],
    'widgets' => [
        'TCG\\Voyager\\Widgets\\UserDimmer',
        'TCG\\Voyager\\Widgets\\PostDimmer',
        'TCG\\Voyager\\Widgets\\PageDimmer',
    ],
],
```

In the dashboard config you can add **navbar\_items**, make the **data\_tables** responsive, and manage your dashboard **widgets**.

**navbar\_items** Include a new route in the main user navbar dropdown by including a 'route', 'icon\_class', and 'target\_blank'.

**data\_tables** If you set 'responsive' to true the datatables will be responsive.

**widgets** Here you can manage the widgets that live on your dashboard. You can take a look at an example widget class by viewing the current widgets inside of `tcg/voyager/src/Widgets`.

## Primary color

```php
<?php

'primary_color' => '#22A7F0',
```

The default primary color for the Voyager admin dashboard is a light blue color. You can change that primary color by changing the value of this config.

## Show developer tips

```php
<?php

'show_dev_tips' => true,
```

In the Voyager admin there are developer tips or notifications that will show you how to reference certain values from Voyager. You can choose to hide these notifications by setting this configuration value to false.

## Additional stylesheets

```php
<?php

'additional_css' => [
    //'css/custom.css',
],
```

You can add your own custom stylesheets that will be included in the Voyager admin dashboard. This means you could technically create a whole new theme for Voyager by adding your own custom stylesheet.

Read more [here](/1.2/customization/additional-css-js).

{% hint style="info" %}
The path will be passed to Laravels [asset](https://laravel.com/docs/helpers#method-asset) function.
{% endhint %}

## Additional Javascript

```php
<?php

'additional_js' => [
    //'js/custom.js',
],
```

The same goes for this configuration. You can add your own javascript that will be executed in the Voyager admin dashboard. Add as many javascript files as needed.

Read more [here](/1.2/customization/additional-css-js).

## Google Maps

```php
<?php

'googlemaps' => [
    'key'    => env('GOOGLE_MAPS_KEY', ''),
    'center' => [
        'lat' => env('GOOGLE_MAPS_DEFAULT_CENTER_LAT', '32.715738'),
        'lng' => env('GOOGLE_MAPS_DEFAULT_CENTER_LNG', '-117.161084'),
    ],
    'zoom' => env('GOOGLE_MAPS_DEFAULT_ZOOM', 11),
],
```

There is a new data type called **coordinates** that allow you to add a google map as a datatype. The user can then drag and drop a pin in the Google Maps to save a longitude and latitude value in the database.

In this config you can set the default Google Maps Keys and center location. This can also be added to your .env file.

## Allowed Mimetypes

To allow/disallow mimetypes to be uploaded through the media-manager you can define an array `allowed_mimetypes`:

```php
<?php

'allowed_mimetypes' => [
     'image/jpeg',
     'image/png',
     'image/gif',
     'image/bmp',
     'video/mp4',
],
```

The user can only upload files with the given mimetypes. If you want to allow all types to be uploaded you can use the following:

```php
<?php

'allowed_mimetypes' => '*',
```


# Introduction

When adding or editing the current BREAD for a database table you will first see the BREAD info which allows you to set the Display Names, slug, icon, `Model` and Controller Namespace, Policy Name. You can also choose if you would like to Generate permissions for that BREAD type.

![](/files/-LrOVMIItVyfqzcxmTog)

When you scroll down you will see each of the rows that are associated with that table where you can select where in your views you want to see each of those fields:

* BROWSE (field will show up when you browse the current data)
* READ (field will show when you click to view the current data)
* EDIT (field will be visible and allow you to edit the data)
* ADD (field will be visible when you choose to create a new data type)
* DELETE (doesn't pertain to delete so this can be checked or unchecked)

![](/files/-LrOVMIMWx70F-V7bwRL)

You may also choose to specify what form type you want to use for each field. This can be a TextBox, TextArea, Checkbox, Image, and many other types of form elements.

Each field also has additional details or options that can be included. These types are checkbox, dropdown, radio button, and image.

## Validation

Inside of the *Optional Details* section for each row in your BREAD you can also specify validation rules with some simple JSON. Here is an example of how to add a validation rule for *required* and *max length of 12*

```php
{
    "validation": {
        "rule": "required|max:12"
    }
}
```

Additionally, you may wish to add some custom error messages which can be accomplished like so:

```php
{
    "validation": {
        "rule": "required|max:12",
        "messages": {
            "required": "This :attribute field is a must.",
            "max": "This :attribute field maximum :max."
        }
    }
}
```

You can also define multiple rules the following way:

```php
{
    "validation": {
        "rule": [
            "required",
            "max:12"
        ]
    }
}
```

### Action specific rules

You can define separate validation rules for edit and add:

```
{
    "validation": {
        "rule": "required",
        "edit": {
            "rule": "sometimes|min:3"
        },
        "add": {
            "rule": "min:3"
        }
    }
}
```

You can find a list of all available validation rules in the [Laravel docs](https://laravel.com/docs/validation#available-validation-rules).

## Tagging

Tagging gives you the possibility to add new items to a Belongs-To-Many relationship directly when editing or adding a BREAD.

To activate this function, you simply have to enable `Tagging` in the relationship details

![](/files/-LrOVMIPmLdNCx2OWB6R)

After that you can enter a free-text into the select and hit enter to save a new relationship.

{% hint style="info" %}
**Be aware:**

This only stores the `display-column` so you have to make sure that all other fields are either nullable or have a default value.
{% endhint %}

## Ordering Bread Items

You can define the default order for browsing BREADs and order your BREAD items with drag-and-drop.\
For this you need to change the settings for your BREAD first:

![](/files/-LrOVMIRYEVrkFMc-KyO)

**Order column** is the field in your table where the order is stored as an integer.\
**Order display column** is the field which is shown in the drag-drop list.\
**Order direction** the direction in which the field is ordered.

After this you can go to your BREAD-browse page and you will see a button **Order.**\
Clicking this button will bring you to the page where you can re-arrange your items:

![](/files/-LrOVMITVM9FMcPrHXnB)

## Scope browse-results

If you want to filter the browse results for a BREAD you can do so by creating a [Scope](https://laravel.com/docs/eloquent#local-scopes) in your model. For example if you want to only show posts that were created by the current user, define a Scope like the following:

```php
<?php
public function scopeCurrentUser($query)
{
    return $query->where('author_id', Auth::user()->id);
}
```

Next, go to the BREAD-settings for `posts` and look for the `Scope` input and select `currentUser`:

![](/files/-LrOVMIVVJyOz1sUmMr8)

After hitting `Submit` you will only see your own posts.


# Relationships

Using the BREAD builder you can easily create Relationships between tables. At the bottom of the page you will see a new button that says 'Create Relationship'

![](/files/-LrOVMHPClygrOaaG2o_)

{% hint style="info" %}
**Notice**\
If you have not yet created the BREAD for the table yet, it will need to be created first and then you can come back after creating the BREAD to add the relationship. Otherwise you'll end up with a notification which looks like the following.
{% endhint %}

![](/files/-LrOVMHTtSeOMaYnk2cj)

So, after the BREAD has already been created you will then be able to create a new relationship. After you click on the 'Create a Relationship' button. You will see a new Modal window that looks like the following:

![](/files/-LrOVMHV_E_9RU05lE6w)

You will first specify which type of relationship this is going to be, then you will select the table you are referencing and which Namespace that belongs to that table. You will then select which row combines those tables.

You can also specify which columns you would like to see in the dropdown or the multi-select.

Now, you can easily create `belongsTo`, `belongsToMany`, `hasOne`, and `hasMany` relationships directly in Voyager.


# Formfields

Formfields are the hearth of Voyagers BREAD-system.\
Each formfield represents a field in your database-table and one input (or output) in BREAD.\
To tweak your formfields you can insert JSON options which are described in the following pages.

All formfields share a handful options:

## Description

All types can include a description in order to help your future self or other users using your Voyager admin panel to understand exactly what a specific BREAD input field is for, this can be defined in the `Optional Details` JSON input field:

```php
{
    "description": "A helpful description text here for your future self."
}
```

## Display options

There are also a few options that you can include to change the way your BREAD is displayed. You can add a `display` key to your json object and change the width of the particular field and even specify a custom ID.

```php
{
    "display": {
        "width": "3",
        "id": "custom_id"
    }
}
```

The width is displayed on a 12-grid system. Setting it with a width of 3 will span 25% of the width.

The **id** will let you specify a custom id wrapper around your element. example:

```markup
<div id="custom_id">
    <!-- Your field element -->
</div>
```

## Default value

Most formfields allow you to define a default value when adding an entry:

```php
{
    "default" : "Default text"
}
```

## Null Values

You might want to save an input field into the database as a `null` value instead of an empty string.

Simply enough, inside the BREAD you can include the following *Optional Details* for the field:

```php
{
    "null": ""
}
```

This will turn an empty string into a `null` value. However you might want to be able to add both an empty string and a `null` value to the database for that field. However you have to choose a replacement for the `null` value, but it can be anything you wish. For example, if you want a field to change a string (ex. `Nothing`) into a `null` value you could include the following *Optional Details* for that field:

```php
{
    "null": "Nothing"
}
```

Now entering `Nothing` into the field will end up as a `null` value in the database.

## Generating Slugs

Using the bread builder you may wish to automatically generate slugs of a certain input. Lets say you have some posts, which have a title and a slug. If you want to automatically generate the slug from the title attribute, you may include the following *Optional Details*:

```php
{
    "slugify": {
        "origin": "title",
        "forceUpdate": true
    }
}
```

This will automatically generate the slug from the input of the `title` field. If a slug does already exists, it will only be updated if `forceUpdate` is set enabled, by default this is disabled.

## Custom view

You can specify a custom view to be used for a formfield.\
To do so, you have to specify the `view` attribute for your desired field:

```
{
    "view": "my_view"
}
```

This will then load `my_view` from `resources/views` instead of the formfield.

You get plenty of data passed to your view for you to use:

* `$action` can be `browse`, `read`, `edit`, `add` or `order`
* `$content` the content for this field
* `$dataType` the DataType
* `$dataTypeContent` the whole model-instance
* `$row` the DataRow

{% hint style="info" %}
**Developing a custom formfield?**\
If you are developing a custom formfield and want to customize any of the views, you can do so by merging `view` into `$options` in your formfields `createContent()` method.
{% endhint %}


# Checkbox/Multiple Checkbox/Radio

## Checkbox

```php
{
    "on" : "On Text",
    "off" : "Off Text",
    "checked" : true
}
```

In Voyager a Checkbox is converted into a toggle switch, and as you can see above the `on` key will contain the value when the toggle switch is on, and the `off` will contain the value that is set when the switch is off. If `checked` is set to *true* the checkbox will be toggle on; otherwise by default it will be off.

## Multiple Checkbox

```php
{
    "checked" : true,
    "options": {
        "checkbox1": "Checkbox 1 Text",
        "checkbox2": "Checkbox 2 Text"
    }
}
```

You can create as many checkboxes as you want.

## Radio Button

```php
{
    "default" : "radio1",
    "options" : {
        "radio1": "Radio Button 1 Text",
        "radio2": "Radio Button 2 Text"
    }
}
```

The Radio button is exactly the same as the dropdown. You can specify a `default` if one has not been set and in the `options` object you will specify the *value* of the option on the **left** and the *text* to be displayed on the **right**.


# Date & Time

```php
{
    "format" : "%Y-%m-%d"
}
```

The date & timestamp input field is where you can input a date. In the JSON above you can specify the `format` value of the output of the date. It allows you to display a formatted `date` in browse and read views, using Carbon's `formatLocalized()` method


# Dropdown

```php
{
    "default" : "option1",
    "options" : {
        "option1": "Option 1 Text",
        "option2": "Option 2 Text"
    }
}
```

When specifying that an input type should be a dropdown you will need to specify the values of that dropdown. In the JSON above you can specify the `default` value of the dropdown if it does not have a value. Additionally, in the `options` object you will specify the *value* of the option on the **left** and the *text* to be displayed on the **right**.


# Images

```php
{
    "resize": {
        "width": "1000",
        "height": null
    },
    "quality" : "70%",
    "upsize" : true,
    "thumbnails": [
        {
            "name": "medium",
            "scale": "50%"
        },
        {
            "name": "small",
            "scale": "25%"
        },
        {
            "name": "cropped",
            "crop": {
                "width": "300",
                "height": "250"
            }
        }
    ]
}
```

The image input has many options. By default if you do not specify any options no problem... Your image will still be uploaded. But, if you want to resize an image, set the quality of the image, or specify thumbnails for the uploaded image you will need to specify those details.

**resize** If you want to specify a size you will need to include that in the `resize` object. If you set either **height** or **width** to null it will keep the aspect ratio based on the width or height that is set. So, for the example above the `width` is set to `1000` pixels and since the `height` is set to `null` it will resize the image width to 1000 pixels and resize the height based on the current aspect ratio.

**quality** If you wish to compress the image with a percentage quality you can specify that percentage in the `quality` key. Typically between 70 and 100% there is little notice of image quality, but the image size may be dramatically lower.

**upsize** This is only valid if you have set your image to be resized. If you specify your image to resized to 1000 pixels and the image is smaller than 1000 pixels by default it will not upsize that image to the 1000 pixels; however, if you set `upsize` to true. It will upsize all images to your specified resize values.

**thumbnails** Thumbnails takes an array of objects. Each object is a new thumbnail that is created. Each object contains 2 values, the `name` and `scale` percentage. The `name` will be attached to your thumbnail image (as an example say the image you uploaded was ABC.jpg a thumbnail with the `name` of `medium` would now be created at ABC-medium.jpg). The `scale` is the percentage amount you want that thumbnail to scale. This value will be a percentage of the *resize* width and height if specified.


# Media Picker

The media picker formfield allows you to upload/delete/select files directly from the media-manager.\
You can customize the behaviour with the following options:

```php
{
    "max": 10,
    "min": 0,
    "expanded": false,
    "show_folders": true,
    "show_toolbar": true,
    "allow_upload": true,
    "allow_move": true,
    "allow_delete": true,
    "allow_create_folder": true,
    "allow_rename": true,
    "allow_crop": true,
    "allowed": [],
    "hide_thumbnails": false,
    "quality": 90,
    "watermark": {
        "source": "...",
        "position": "top-left",
        "x": 0,
        "y": 0
    }
}
```

| Name                  | Description                                                                                                                            | Type   | Default       |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------ | ------------- |
| base\_path            | The start path relative to the filesystem                                                                                              | String | /bread-slug/  |
| rename                | Rename uploaded files to a given string/expression                                                                                     | String | Original name |
| delete\_files         | <p>Delete files if the BREAD entry is deleted.</p><p>Use with caution!</p>                                                             | bool   | false         |
| show\_as\_images      | Shows stored data as images when browsing                                                                                              | bool   | false         |
| min                   | The minimum amount of files that can be selected                                                                                       | int    | 0             |
| max                   | <p>The maximum amount of files that can be selected.</p><p>0 means infinite</p>                                                        | int    | 0             |
| expanded              | If the media-picker should be expanded by default                                                                                      | bool   | false         |
| show\_folders         | Show subfolders                                                                                                                        | bool   | true          |
| show\_toolbar         | Shows/hides the whole toolbar                                                                                                          | bool   | false         |
| allow\_upload         | Allow users to upload new files                                                                                                        | bool   | true          |
| allow\_move           | Allow users to move files/folders                                                                                                      | bool   | true          |
| allow\_delete         | Allow users to delete files                                                                                                            | bool   | true          |
| allow\_create\_folder | Allow users to create new folders                                                                                                      | bool   | true          |
| allow\_rename         | <p>Allow users to rename files.</p><p>Use with caution!</p>                                                                            | bool   | true          |
| allow\_crop           | Allow users to crop images                                                                                                             | bool   | true          |
| hide\_thumbnails      | Hides known thumbnails and shows them as children of the parent image                                                                  | bool   | true          |
| quality               | Sets the quality of uploaded images and thumbnails                                                                                     | int    | 90            |
| allowed               | <p>The allowed types to be uploaded/selected.</p><p>Empty object means all types.</p><p>Files with other types won't be displayed.</p> | Object | \[]           |

## Allowed types

If you want your users to only be able to upload specific file-types you can do so by passing an object with mime-types to the \`allowed\` prop, for example:

```
["image", "audio", "video"]
```

or

```
["image/jpeg", "image/png", "image/bmp"]
```

## Expressions

The `base_path` and `rename` can contain the following placeholders:

* `{pk}` the primary-key of the entry (only for `base_path`)
* `{uid}` the user-id of the current logged-in user
* `{date:format}` the current date in the format defined in `format`. For example `{date:d.m.Y}`
* `{random:10}` random string with N characters

So a `base_path` can, for example, look like the following:

```
{
    "base_path": "/my-bread/{pk}/{date:Y}/{date:m}/"
}
```

## Watermark

A watermark can be added to uploaded images. To do so, you need to define a `source` property relative to Voyagers storage-disk. There are a few optional arguments you can use:\
**position** the position where the watermark is placed. Can be:

* top-left (default)
* top
* top-right
* left
* center
* right
* bottom-left
* bottom
* bottom-right

**x** Relative offset to the position on the x-axis. Defaults to 0

**y** Relative offset to the position on the y-axis. Defaults to 0

**size** the size (in percent) of the watermark relative to the image. Defaults to 15

## Thumbnails

You can generate thumbnails for each uploaded image.\
A thumbnail can be one of three types:

### Fit

Fit combines cropping and resizing to find the best way to generate a thumbnail matching your dimensions.\
You have to pass `width` and can pass `height` and `position`.\
An example for `fit` would be:

```
{
    "thumbnails": [
        {
            "type": "fit",
            "name": "fit-500",
            "width": 500, // Required
            "height": 500, // Optional
            "position": "center" // Optional. Refer to http://image.intervention.io/api/fit
        }
    ]
}
```

### Crop

Crop an image by given dimensions and position. You have to pass `width` and `height` and can pass `x` and `y`.\
An example for `crop` would be:

```
{
    "thumbnails": [
        {
            "type": "crop",
            "name": "crop-500-500",
            "width": 500, // Required
            "height": 500, // Required
            "x": 50, // Optional. Left offset
            "y": 50, // Optional. Top offset
        }
    ]
}
```

### Resize

Resize the image to the given dimensions. You have to pass `width` and/or `height`.\
Some examples for `resize`:

```
{
    "thumbnails": [
        // Width will be 500px, height will be calculated based on the aspect-ratio
        {
            "type": "resize",
            "name": "resize-500",
            "width": 500,
            "upsize": true, // Optional. Set to false to prevent upsizing
        },
        // Resizes the image to 500x500px
        {
            "type": "resize",
            "name": "resize-500-500",
            "width": 500,
            "height": 500
        },
        // Height will be 500px, width will be auto-calculated
        {
            "type": "resize",
            "name": "resize-500",
            "width": null,
            "height": 500
        }
    ]
}
```

A watermark can also be inserted into each thumbnail. Just define the [watermark-options](/1.2/bread/introduction-1/media-picker#watermark) on the parent and set `watermark` to `true` for each thumbnail you want to insert the watermark to.


# Number

```php
{
    "step" : 0.1,
    "min" : 0,
    "max" : 10
}
```

These are standard attributes for number input field, default value for step is any if not defined.


# Routing

After running the voyager installer you will see a few new routes that have been added to your `routes/web.php` file which look like the following:

```php
Route::group(['prefix' => 'admin'], function () {
    Voyager::routes();
});
```

This is where the Voyager routes will be rendered. You can change the `admin` prefix if you desire, or set any other route configuration you need, such as `middleware` or `domain`.

When creating a new BREAD type and specifying a slug for that BREAD, you can then visit that route from the following link:

```
URL/admin/slug-name
```

As an example, if we have a `products` table and we specified the slug to be `products`. You will now be able to visit the following URL:

```
URL/admin/products
```

{% hint style="info" %}
**Notice**\
You may not see a link to your newly created routes or BREAD inside your admin menu. To create a new link in your admin menu visit the documentation for the [menu section](/1.2/core-concepts/menus-and-menu-builder).
{% endhint %}


# Media Manager

Voyager has a full-fledged Media Manager which allows you to upload files, re-name files, and delete files. You can also add new folders and move files/folders. Basically anything that you would be able to do in any type of Media Manager you can do so in the Voyager Media Manager.

![](/files/-LrOVMDibnyMMYE7oDz-)

You may also drag and drop files onto the 'upload' button to upload multiple files.\
The media manager allows you to create thumbnails and add watermarks to uploaded images through the configuration file.\
Please visit the [media-picker documentation](/1.2/bread/introduction-1/media-picker#watermark) to learn about the configuration options.

{% hint style="info" %}
**Notice on File Upload Size**\
If you are getting an error when trying to upload large files, this may be a setting that needs to be changed in your PHP. Be sure to check `max_file_upload` and `file_upload_size`
{% endhint %}


# Menus and Menu Builder

With Voyager you can easily create menus for your application. In fact the Voyager admin is using the menu builder for the navigation you use on the left hand side.

You can view your current Menus by clicking on the *Tools->Menu Builder* button. You can add, edit, or delete any current menu. This means that you can create a new menu for the header, sidebar, or footer of your site. Create as many menus as you would like.

When you are ready to add menu items to your menu you can click on the builder button of the corresponding menu:

![](/files/-LrOUO_53SnAbZLfHGKQ)

This will take you to the Menu Builder where you can add, edit, and delete menu items.

![](/files/-LrOUO_75VwScr5uM7Ia)

After creating and configuring your menu, you can easily implement that menu in your application. Say that we have a menu called `main`. Inside of any view file we could now output the menu by using the following code:

```php
menu('main');
```

This will output your menu in an unstyled unordered list. If you do use bootstrap to stylize your web app you can pass a second argument to the menu display method telling it that you want to stylize the menu with bootstrap styles like so:

```php
menu('main', 'bootstrap');
```

Taking it one more step further you can even specify your own view and stylize your menu however you would like. Say for instance that we had a file located at `resources/views/my_menu.blade.php`, which contained the following code:

```markup
<ul>
    @foreach($items as $menu_item)
        <li><a href="{{ $menu_item->link() }}">{{ $menu_item->title }}</a></li>
    @endforeach
</ul>
```

Then anywhere you wanted to display your menu you can now call:

```php
menu('main', 'my_menu');
```

And your custom menu will now be output.

## Menu as JSON

If you dont want to render your menu but get an array instead, you can pass `_json` as the second parameter. For example:

```php
menu('main', '_json')
```

This will give you a collection of menu-items.


# Database Manager

Voyager has some awesome database tools which allow you to Add/Edit/Delete or view current database tables. The other cool part of Voyager is that you can add BREAD or (Browse, Read, Edit, Add, & Delete) functionality to any of your tables.

![](/files/-LrOVMEtUes3LIx906e-)

Inside of your admin panel you can visit Tools->Database and you'll be able to view all your current tables in your database. You may also click on 'Create a New Table' to create a new table in your database. All newly created tables will use the charset defined in your [default database connection](https://laravel.com/docs/database#configuration).

![](/files/-LrOVMEwIfTzLIcXY-up)

If you click the table name you can view the current schema. Additionally you can click on the View, Edit, or Delete buttons to perform that action for that table.

You may also choose to Add BREAD (Browse, Read, Edit, Add, & Delete) for any of your database tables. Once a table already has BREAD you may choose to edit the current BREAD or Delete the BREAD for that table.

Read on further about the BREAD builder in the next section.


# Settings

The Settings section allows you to add any site wide settings you would like. You can add an image upload setting for your site logo or a text box for the main headline on your homepage.

![](/files/-LrOUOotWDe5Kd3BtdnR)

In this new version you have the ability to add different groups for different settings. So, if you created a new setting inside of the `site` group and it had a key of `title` you would then be able to reference that setting any where on your site by doing the following:

```php
<?php
echo setting('site.title');
```

Or inside of any blade template like:

```
{{ setting('site.title') }}
```

So, now you can add all kinds of settings in Voyager and reference them in your application.


# Compass

The Compass section is a quick place for you to go for some link references, font references, run some commands or view some logs.

In the first tab you will see a few link resources and you will see all the fonts that you can use inside of Voyager.

![](/files/-LrOVMFr0W0_QXgXFBK_)

In the Command section you can actually run some artisan commands directly from Voyager.

![](/files/-LrOVMFuqU1n75-c7ib8)

And Lastly, under the Logs tab you will be able to view all your application logs.

![](/files/-LrOVMFwFYriPLMNcG8a)


# Roles and Permissions

Voyager comes with Roles and Permissions out of the box. Each *User* has a *Role* which has a set of *Permissions*.

Inside of the dashboard you can choose to Add, Edit, or delete the current Roles. Additionally when you click to edit a particular role you can specify the BREAD permissions.

![](/files/-LrOVMDmwQ581k-_z41H)

New in version 1.0, we've changed Voyager's authorization system to be [more in line with Laravel](https://laravel.com/docs/authorization#authorizing-actions-using-policies)! This means that you can check for permissions in the following ways:

```php
// via user object
$canViewPost = $user->can('read', $post);
$canViewPost = Auth::user()->can('read', $post);

// via controller
$canViewPost = $this->authorize('read', $post);
```

Out of the box there are some permissions you can use by default:

* `browse_admin`: Whether or not the user may browse the Voyager admin panel.
* `browse_database`: Whether or not the user may browse the Voyager database menu section.
* `browse_bread`: Whether or not the user may browse the Voyager BREAD menu section.
* `browse_media`: Whether or not the user may browse the Voyager media section.
* `browse_menu`: Whether or not the user may browse the Voyager menu section.
* `browse_settings`: Whether or not the user may browse the Voyager settings section.
* `read_settings`: Whether or not the user can view or see a particular setting.
* `edit_settings`: Whether or not the user can edit a particular setting.
* `add_settings`: Whether or not the user can add a new setting.
* `delete_settings`: Whether or not the user can delete a particular setting.

Additionally you can `Generate permissions` for every BREAD type you create. This will create the `browse`, `read`, `edit`, `add` and `delete` permission.

As an example, perhaps we are creating a new BREAD type from a `products` table. If we choose to `Generate permissions` for our `products` table. Our permission keys will be `browse_products`, `read_products`, `edit_products`, `add_products` and `delete_products`.

{% hint style="info" %}
**Notice**\
If a menu item is associated with any kind of BREAD, then it will check for the `browse` permission, for example for the `Posts` BREAD menu item, it will check for the `browse_posts` permission. If the user does not have the required permission, that menu item will be hidden.
{% endhint %}

## Using Permissions in your Blade Template files

You can also check for permissions using blade syntax. Let's say for instance that you want to check if a user can `browse_posts`, simple enough we can use the following syntax:

```php
@can('browse', $post)
    I can browse posts
@endcan
```

Or perhaps you need to run an else condition for a permission. That's simple enough:

```php
@can('browse', $post)
    I can browse posts
@else
    I cannot browse posts
@endcan
```

Couldn't be easier, right ;)


# Helper methods

Voyager has several helper functions that are ready to use. Here you can find the list of available function that may speed up your development.

## Thumbnails URL

Voyager will generate thumbnails for Image field type when you specify the [additional field options](/1.2/bread/introduction#additional-field-options).

After you have your thumbnails generated, you may want to display the thumbnails in your view or get the thumbnail URL. In order to do that you need to add `Resizable` traits to your model.

```php
use TCG\Voyager\Traits\Resizable;

class Post extends Model
{
    use Resizable;
}
```

### Display a single image

```php
@foreach($posts as $post)
    <img src="{{Voyager::image($post->thumbnail('small'))}}" />
@endforeach
```

Or you can specify the optional image field name (attribute), default to `image`

```php
@foreach($posts as $post)
    <img src="{{Voyager::image($post->thumbnail('small', 'photo'))}}" />
@endforeach
```

### Display multiple images

```php
@foreach($posts as $post)
    $images = json_decode($post->images);
    @foreach($images as $image)
        <img src="{{ Voyager::image($post->getThumbnail($image, 'small')) }}" />
    @endforeach
@endforeach
```


# Multilanguage

Voyager supports multiple languages for your models.To get started, you need to configure some things first.

## Setup

First you need to define some `locales` in your `config/voyager.php` file and `enable` multilanguage:

```php
'multilingual' => [
        'enabled' => true,
        'default' => 'en',
        'locales' => [
            'en',
            'da',
        ],
    ],
```

After that you need to include the `Translatable` Trait in your model and define the translatable attributes:

```php
use TCG\Voyager\Traits\Translatable;
class Post extends Model
{
    use Translatable;
    protected $translatable = ['title', 'body'];
}
```

Now you will see a language-selection in your Pages BREAD.

## Usage

### Eager-load translations

```php
// Loads all translations
$posts = Post::with('translations')->get();

// Loads all translations
$posts = Post::all();
$posts->load('translations');

// Loads all translations
$posts = Post::withTranslations()->get();

// Loads specific locales translations
$posts = Post::withTranslations(['en', 'da'])->get();

// Loads specific locale translations
$posts = Post::withTranslation('da')->get();

// Loads current locale translations
$posts = Post::withTranslation('da')->get();
```

### Get default language value

```php
echo $post->title;
```

### Get translated value

```php
echo $post->getTranslatedAttribute('title', 'locale', 'fallbackLocale');
```

If you do not define locale, the current application locale will be used. You can pass in your own locale as a string. If you do not define fallbackLocale, the current application fallback locale will be used. You can pass your own locale as a string. If you want to turn the fallback locale off, pass false. If no values are found for the model for a specific attribute, either for the locale or the fallback, it will set that attribute to null.

### Translate the whole model

```php
$post = $post->translate('locale', 'fallbackLocale');
echo $post->title;
echo $post->body;

// You can also run the `translate` method on the Eloquent collection
// to translate all models in the collection.
$posts = $posts->translate('locale', 'fallbackLocale');
echo $posts[0]->title;
```

If you do not define locale, the current application locale will be used. You can pass in your own locale as a string. If you do not define fallbackLocale, the current application fallback locale will be used. You can pass in your own locale as a string. If you want to turn the fallback locale off, pass false. If no values are found for the model for a specific attribute, either for the locale or the fallback, it will set that attribute to null.

### Check if model is translatable

```php
// with string
if (Voyager::translatable(Post::class)) {
    // it's translatable
}

// with object of Model or Collection
if (Voyager::translatable($post)) {
    // it's translatable
}
```

### Set attribute translations

```php
$post = $post->translate('da');
$post->title = 'foobar';
$post->save();
```

This will update or create the translation for title of the post with the locale da. Please note that if a modified attribute is not translatable, then it will make the changes directly to the model itself. Meaning that it will overwrite the attribute in the language set as default.

### Query translatable Models

To search for a translated value, you can use the `whereTranslation` method.\
For example, to search for the slug of a post, you'd use

```php
$page = Page::whereTranslation('slug', 'my-translated-slug');
// Is the same as
$page = Page::whereTranslation('slug', '=', 'my-translated-slug');
// Search only locale en, de and the default locale
$page = Page::whereTranslation('slug', '=', 'my-translated-slug', ['en', 'de']);
// Search only locale en and de
$page = Page::whereTranslation('slug', '=', 'my-translated-slug', ['en', 'de'], false);
```

`whereTranslation` accepts the following parameter:

* `field` the field you want to search in
* `operator` the operator. Defaults to `=`. Also can be the value (Same as [where](https://laravel.com/docs/queries#where-clauses))
* `value` the value you want to search for
* `locales` the locales you want to search in as an array. Leave as `null` if you want to search all locales
* `default` also search in the default value/locale. Defaults to true.


# Overriding files

## Overriding BREAD Views

You can override any of the BREAD views for a **single** BREAD by creating a new folder in `resources/views/vendor/voyager/slug-name` where *slug-name* is the *slug* that you have assigned for that table. There are 4 files that you can override:

* browse.blade.php
* edit-add.blade.php
* read.blade.php
* order.blade.php

Alternatively you can override the views for **all** BREADs by creating any of the above files under `resources/views/vendor/voyager/bread`

## Using custom Controllers

#### Overriding submit button:

You can override the submit button without the need to override the whole `edit-add.blade.php` by extending the `submit-buttons` section:

```
@extends('voyager::bread.edit-add')
@section('submit-buttons')
    @parent
    <button type="submit" class="btn btn-primary save">Save And Publish</button>
@endsection
```

### Using custom Controllers

You can override the controller for a single BREAD by creating a controller which extends Voyagers controller, for example:

```php
<?php

namespace App\Http\Controllers;

class VoyagerCategoriesController extends \TCG\Voyager\Http\Controllers\VoyagerBaseController
{
    //...
}
```

After that go to the BREAD-settings and fill in the Controller Name with your fully-qualified class-name:

![](/files/-LrOVME3022kFwRdRYST)

You can now override all methods from the [VoyagerBaseController](https://github.com/the-control-group/voyager/blob/1.1/src/Http/Controllers/VoyagerBaseController.php)

## Overriding Voyagers Controllers

If you want to override any of Voyagers core controllers you first have to change your config file `config/voyager.php`:

```php
/*
|--------------------------------------------------------------------------
| Controllers config
|--------------------------------------------------------------------------
|
| Here you can specify voyager controller settings
|
*/

'controllers' => [
    'namespace' => 'App\\Http\\Controllers\\Voyager',
],
```

Then run `php artisan voyager:controllers`, Voyager will now use the child controllers which will be created at `App/Http/Controllers/Voyager`

## Overriding Voyager-Models

You are also able to override Voyagers models if you need to.\
To do so, you need to add the following to your AppServiceProviders register method:

```php
Voyager::useModel($name, $object);
```

Where **name** is the class-name of the model and **object** the fully-qualified name of your custom model. For example:

```php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Events\Dispatcher;
use TCG\Voyager\Facades\Voyager;

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        Voyager::useModel('DataRow', \App\DataRow::class);
    }
    // ...
}
```

The next step is to create your model and make it extend the original model. In case of `DataRow`:

```php
<?php

namespace App;

class DataRow extends \TCG\Voyager\Models\DataRow
{
    // ...
}
```


# Overriding Routes

You can override any Voyager routes by writing the routes you want to overwrite below `Voyager::routes()`. For example if you want to override your post LoginController:

```php
Route::group(['prefix' => 'admin'], function () {
   Voyager::routes();

   // Your overwrites here
   Route::post('login', ['uses' => 'MyAuthController@postLogin', 'as' => 'postlogin']);
});
```


# Additional CSS and JS

As of the latest version you can now add additional CSS and JS files to the voyager master blade without having to copy or modify the blade file itself removing potential manual migration headaches later on. The CSS and JS files are added *after* any Voyager assets so you can override styles and functionality comfortably.

This is all handled via the `voyager.php` config file:

```php
// Here you can specify additional assets you would like to be included in the master.blade
'additional_css' => [
    //'css/custom.css',
],
'additional_js' => [
   //'js/custom.js',
],
```

{% hint style="info" %}
The path will be passed to Laravels [asset](https://laravel.com/docs/helpers#method-asset) function.
{% endhint %}


# Enabling Soft-Delete

This is only to assist with enabling soft-deletion for your models within Voyager. Please refer to the [Laravel documentation](https://laravel.com/docs/eloquent#soft-deleting) for specifics.

## Table Configurations in Voyager

When creating a table using the Database Manager you've selected the 'Add Soft Deletes' button and then when adding the BREAD functionality to that table you've added a Model Name, you only have to edit your Model file to fully enable Soft-Delete on that table.

## Editing the Table's Model

A default model will look like this:

```php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;


class YourModelName extends Model
{

}
```

Just turn it into:

```php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;


class Documento extends Model
{
    use SoftDeletes;
    protected $dates = ['deleted_at'];
}
```

And from now on, every time you delete a record from that table, it won't actually be deleted, only the `deleted_at` column will be written with the current timestamp.


# Custom relationship attributes

With Voyager 1.1 you are able to define additional attributes which you can show in a relationship.

For example a `Post` has an `Author` and you want to display the `Users` full-name. To do so, we first need to [define an Accessor](https://laravel.com/docs/eloquent-mutators#defining-an-accessor)

```php
public function getFullNameAttribute()
{
    return "{$this->first_name} {$this->last_name}";
}
```

After that we need to tell Voyager that there is an accessor we want to use:

```php
public $additional_attributes = ['full_name'];
```

Thats it! You can now select `full_name` in your Relationship.


# TinyMCE

If you want to customize TinyMCE within Voyager, you can do so by adding a [additional JS file](/1.2/customization/additional-css-js) to your config.

In this file you have to define a function like

```javascript
function tinymce_init_callback(editor)
{
    //...
}
```

If you need to manipulate TinyMCE **before** it was initialized, you can use

```javascript
function tinymce_setup_callback(editor)
{
    //...
}
```

Now you can control the TinyMCE instance(s) on the page. For all possible variables and functions, please refer to the [TinyMCE documentation](https://www.tinymce.com/docs/api/tinymce/tinymce.editor/).


# Adding custom Formfields

You can easily add a new Formfield to Voyager. In the example below we will add a number form field (which is already included by default in Voyager).

First we create a new class in our project (it doesn't matter where it is placed) called `NumberFormField`

```php
<?php

namespace App\FormFields;

use TCG\Voyager\FormFields\AbstractHandler;

class NumberFormField extends AbstractHandler
{
    protected $codename = 'number';

    public function createContent($row, $dataType, $dataTypeContent, $options)
    {
        return view('formfields.number', [
            'row' => $row,
            'options' => $options,
            'dataType' => $dataType,
            'dataTypeContent' => $dataTypeContent
        ]);
    }
}
```

The `codename` variable is used in the dropdown you see in the BREAD builder. In the `createContent` method we are returning the view that is used to display our form field.

Next, we will create the view specified above.

```markup
<input type="number"
       class="form-control"
       name="{{ $row->field }}"
       data-name="{{ $row->display_name }}"
       @if($row->required == 1) required @endif
             step="any"
       placeholder="{{ isset($options->placeholder)? old($row->field, $options->placeholder): $row->display_name }}"
       value="@if(isset($dataTypeContent->{$row->field})){{ old($row->field, $dataTypeContent->{$row->field}) }}@else{{old($row->field)}}@endif">
```

In the view we can add whatever logic we want.

When we are done with our view, we will tell Voyager that we have a new form field. We will do this in a service provider (in the example below we use the `AppServiceProvider`.

```php
<?php

namespace App\Providers;

use TCG\Voyager\Facades\Voyager;
use App\FormFields\NumberFormField;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    //..

    public function register()
    {
        Voyager::addFormField(NumberFormField::class);
    }
}
```


# Coordinates

With Voyager you are able to store coordinates and select them from a map.\
To do so, you first need to make sure that the column in your table is either `GEOMETRY` or `POINT`.

After that you have to include the Spatial-Trait in your Model and define the column:

```php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use TCG\Voyager\Traits\Spatial;

class Category extends Model
{
    use Spatial;

    protected $spatial = ['your_column'];
}
```

Now you can go to the tables BREAD-settings and set your field to be `Coordinates`.

After that you will get a Map where you can select your Coordinates.

{% hint style="info" %}
Make sure to set the Google Maps API-Key in your [configuration](/1.2/getting-started/configurations#google-maps).\
This is also the place where you can define the default location of your map.
{% endhint %}

## Getting the coordinates

You can get the coordinates from your model by calling

```php
$model->getCoordinates();
```

This will return an array of coordinates with `lat` as the latitude and `lng` as the longitude.


# BREAD accessors

Sometimes you want to format an attribute only for one (or some) of the BREAD-actions.\
For example if you have a `name` field and on the browse-page you want to display something when the field is empty, you define the following in your model:

```php
<?php

public function getNameBrowseAttribute()
{
    return $this->name ?? 'Empty';
}
```

This will display "Empty" if the actual field is empty, or return the value if not.

Likewise you can do the same for the other BREAD-actions:

```php
<?php

public function getNameReadAttribute()
{
    //
}

public function getNameEditAttribute()
{
    //
}

public function getNameAddAttribute()
{
    //
}
```


# Custom guard

Starting with Voyager 1.2 you can define a (custom) guard which is used throughout Voyager.\
To do so, just bind your auth-guard to `VoyagerAuth`.\
Open your `AuthServiceProvider` and add the following to the register method:

```php
$this->app->singleton('VoyagerAuth', function () {
    return Auth::guard('your-custom-guard');
});
```

Now this guard is used instead of the default guard.


# Action buttons

## Action Buttons

Action buttons are displayed when browsing a BREAD next to each row

![](/files/-LrOVMEosh57WIygTPo3)

You can add your own buttons very easily. First we will create an Action-class which extends Voyagers AbstractAction in app/Actions/MyAction.php

```php
<?php

namespace App\Actions;

use TCG\Voyager\Actions\AbstractAction;

class MyAction extends AbstractAction
{
    public function getTitle()
    {
        return 'My Action';
    }

    public function getIcon()
    {
        return 'voyager-eye';
    }

    public function getPolicy()
    {
        return 'read';
    }

    public function getAttributes()
    {
        return [
            'class' => 'btn btn-sm btn-primary pull-right',
        ];
    }

    public function getDefaultRoute()
    {
        return route('my.route');
    }
}
```

Next we need to tell Voyager that we want to use this action. For this open your `app/Providers/AppServiceProvider.php` and search for the `boot()` method

```php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Events\Dispatcher;
use TCG\Voyager\Facades\Voyager;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Voyager::addAction(\App\Actions\MyAction::class);
    }
}
```

After that you will see your new button when browsing any BREAD ![](/files/-LrOVMEtsHypNi-HkCme)

### Showing/hiding actions

If you only want to show your action for special datatypes you can implement a function `shouldActionDisplayOnDataType()` in your action:

```php
<?php

public function shouldActionDisplayOnDataType()
{
    return $this->dataType->slug == 'posts';
}
```

## Mass Actions

Mass actions are called for multiple instances of a model.\
If you want your action to be a mass action, just implement the following method:

```php
<?php

public function massAction($ids, $comingFrom)
{
    // Do something with the IDs
    return redirect($comingFrom);
}
```


# Using HTTPS on yours site

**Symptom:** When visiting your site with HTTPS, images within Voyager fail to load.

**Cause:** Images urls are generated by Voyager using

```php
Storage::disk(config('voyager.storage.disk'))->url($file);
```

If voyager.storage.disk is set to public, and the public disk is the default from Laravel, then the url property in the disk configuration is set to

```php
'url' => env('APP_URL').'/storage',
```

which uses the non-HTTPS APP\_URL value to build an absolute url to the image.

**Solution:** If you remove env('APP\_URL'). from the public disk configuration, then it will render a domain-relative url, which will always use the current domain and protocol.

As an aside, if you need a fully-qualified URL, you could wrap the call to `Voyager::image('...')` with `asset()`, so it would be

```php
asset(Voyager::image('...'))
```

This will return the current protocol, domain, and correct path to that image.


# Missing required parameter

**Symptom:** You get an error page saying

```
Missing required parameters for [Route...]
```

**Cause:** There are two possible causes:\
1\. You dont have a primary-key for your table\
2\. You have a primary-key but it's **not** called `id`

**Solution:** As there are two causes, there are also two solutions: 1. Simply create a field `id` for the table\
2\. Tell your model about your primary-key: `protected $primaryKey = 'your_primary_key';`

Please consider following [Eloquents model conventions](https://laravel.com/docs/eloquent#eloquent-model-conventions)


# Introduction

Welcome to the Voyager documentation for version 1.3. This documentation will teach you how to install, configure, and use Voyager so that way you can create some kick ass stuff!

Hm Hm (cough)… I mean… Arrgg! Ye young scallywag! What say we learn how to steer this ship!

![Voyager Screenshot](https://s3.amazonaws.com/thecontrolgroup/voyager-screenshot.png)

Before installing Voyager you may want to take a quick moment to learn what it is and what it isn't, we'll do that in the next section.


# What is Voyager

Before installing Voyager it is very important to take a quick moment to learn *what it is* & *what it isn't*.

## What it is

* An admin interface for your Laravel app
* An easy way to add/edit/delete data for your app
* A menu builder (build menus in Voyager for your app)
* A media manager for your files
* CRUD/BREAD generator ([learn more about BREAD here](/1.3/bread/introduction))

Voyager is simply an admin for your Laravel app. Whatever you want your app to do on the front-end is completely up to you. You are in control of your application and you can use Voyager to make your life easier by adding data, editing users, creating menus, and many other administrative tasks.

## What it isn't

* A content management system (CMS)
* A blogging platform
* Wordpress (Bleh! 😜)

Voyager is not a CMS or a blogging platform. But it can be used to create a CMS or a blogging platform, but out of the box it is neither of those. As stated in the previous section you have full control on what your application will do and how it will function.

With Laravel & Voyager you can create any kind of application your heart desires. Laravel & Voyager are simply tools to make it easier to build.


# Prerequisites

Before installing Voyager make sure you have installed one of the following versions of Laravel:

* Laravel 5.5
* Laravel 5.6
* Laravel 5.7
* Laravel 5.8
* Laravel 6

Additionally Voyager requires you to use PHP 7.2 or newer.


# Installation

Voyager is super easy to install. After creating your new Laravel application you can include the Voyager package with the following command:

```bash
composer require tcg/voyager
```

Next make sure to create a new database and add your database credentials to your .env file, you will also want to add your application URL in the `APP_URL` variable:

```
APP_URL=http://localhost
DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
```

Finally, we can install Voyager. You can choose to install Voyager with dummy data or without the dummy data. The dummy data will include 1 admin account (if no users already exist), 1 demo page, 4 demo posts, 2 categories and 7 settings.

To install Voyager without dummy data simply run

```bash
php artisan voyager:install
```

If you prefer installing it with the dummy data run the following command:

```bash
php artisan voyager:install --with-dummy
```

{% hint style="danger" %}
**Specified key was too long error**\
If you see this error message you have an outdated version of MySQL, use the following solution: <https://laravel-news.com/laravel-5-4-key-too-long-error>
{% endhint %}

And we're all good to go!

Start up a local development server with `php artisan serve` And, visit the URL <http://localhost:8000/admin> in your browser.

If you installed with the dummy data, a user has been created for you with the following login credentials:

> **email:** `admin@admin.com`\
> **password:** `password`

{% hint style="info" %}
**Quick note**\
A dummy user is **only** created if there are no current users in your database.
{% endhint %}

If you did not go with the dummy user, you may wish to assign admin privileges to an existing user. This can easily be done by running this command:

```bash
php artisan voyager:admin your@email.com
```

If you wish to create a new admin user you can pass the `--create` flag, like so:

```bash
php artisan voyager:admin your@email.com --create
```

And you will be prompted for the users name and password.

## Advanced

This section is meant for users who are installing Voyager on an already existing Laravel installation or for users who want to perform a manual install. If this is not the case, you should go back to the [installation](/1.3/getting-started/installation) documentation or skip this section.

The first thing you should do is publish the assets that come with Voyager. You can do that by running the following commands:

```bash
php artisan vendor:publish --provider="TCG\Voyager\VoyagerServiceProvider"
php artisan vendor:publish --provider="Intervention\Image\ImageServiceProviderLaravelRecent"
```

Next, call `php artisan migrate` to migrate all Voyager table.

{% hint style="info" %}
If you want to change migrations, for example to use a different table for users, don't migrate. Instead copy Voyagers migrations to `database/migrations`, make your changes, turn off the config option `database.autoload_migrations` and then migrate.
{% endhint %}

Now, open your User-Model (usually `app/User.php`) and make the class extend `\TCG\Voyager\Models\User` instead of `Authenticatable`.

```php
<?php

class User extends \TCG\Voyager\Models\User
{
    // ...
}
```

The next step is to add Voyagers routes to your `routes/web.php` file:

```php
<?php

Route::group(['prefix' => 'admin'], function () {
    Voyager::routes();
});
```

Now run\
`php artisan db:seed --class=VoyagerDatabaseSeeder`\
to seed some necessary data to your database,\
`php artisan hook:setup`\
to install the hooks system, and\
`php artisan storage:link`\
to create the storage symlink to your public folder.

After that, run `composer dump-autoload` to finish your installation!


# Upgrading

## Upgrading 1.2 to 1.3

{% hint style="info" %}
Please take a look at our [prerequisites](/1.3/getting-started/prerequisites) before upgrading!
{% endhint %}

### Update your Composer.json

To update to the latest version inside of your composer.json file make sure to update the version of Voyager inside the require declaration inside of your composer.json to:

`tcg/voyager": "1.3.*`

And then run `composer update`

### Changes to VoyagerAuth

The `VoyagerAuth` singleton was introduced in Voyager 1.2 and returned an instance of the guard.\
In Voyager 1.3 this singleton was renamed to `VoyagerGuard` and now returns the name of the guard as a string. Read more on custom guards [here](/1.3/customization/custom-guard)

## Update Configuration

The `voyager.php` configuration file had a few changes.

```
'user' => [
    'namespace' => null,
],
```

was removed. The user-model which will be used in the `voyager:admin` command is now determined based on the [guard](/1.3/customization/custom-guard).

### Troubleshooting

Be sure to ask us on our slack channel if you are experiencing any issues and we will try and assist. Thanks.


# Configurations

With the installation of Voyager you will find a new configuration file located at `config/voyager.php`.\
In this file you can find various options to change the configuration of your Voyager installation.

{% hint style="info" %}
If you cache your configuration files please make sure to run `php artisan config:clear` after you changed something.
{% endhint %}

Below we will take a deep dive into the configuration file and give a detailed description of each configuration set.

## Users

```php
<?php

'user' => [
    'add_default_role_on_register' => true,
    'default_role'                 => 'user',
    'admin_permission'             => 'browse_admin',
    'namespace'                    => App\User::class,
    'redirect'                     => '/admin'
],
```

**add\_default\_role\_on\_register:** Specify whether you would like to add the default role to any new user that is created.\
**default\_role:** You can also specify what the **default\_role** is of the user.\
**admin\_permission:** The permission needed to view the admin dashboard.\
**namespace:** The namespace of your apps User Class.\
**redirect:** Redirect path after the user logged in.

## Controller

```php
<?php

'controllers' => [
    'namespace' => 'TCG\\Voyager\\Http\\Controllers',
],
```

You can specify the default `controller` namespace of Voyager. If you ever wish to override any of the core functionality of Voyager you can do so by duplicating the Voyager controllers and specifying the location of your custom controllers.

{% hint style="info" %}
**Overwrite a single controller**\
If you only want to overwrite a single controller, you might consider adding the following piece of code to your `AppServiceProvider` class in the `register` method.\
`$this->app->bind(VoyagerBreadController::class, MyBreadController::class);`
{% endhint %}

## Model

```php
<?php

'models' => [
    //'namespace' => 'App\\',
],
```

You can specify the namespace or location of your models. This is used when creating the Models from the database section of Voyager. If not defined the default application namespace will be used.

## Assets

```php
<?php

'assets_path' => '/vendor/tcg/voyager/assets',
```

You may wish to specify a different asset path. If your site lives in a subfolder you may need to include that directory to the beginning of the path. This may also be used in case you wish to duplicate the published assets and customize your own.

{% hint style="info" %}
When upgrading to new version of voyager the assets located in the `/vendor/tcg/voyager/assets` directory may need to be overwritten, so if you wish to customize any styles you will want to duplicate that directory and specify the new location of your asset\_path.
{% endhint %}

## Storage

```php
<?php

'storage' => [
    'disk' => 'public',
],
```

By default Voyager is going to use the `public` local storage. You can additionally use any driver inside of your `config/filesystems.php`. This means you can use S3, Google Cloud Storage, or any other file storage system you would like.

## Database

```php
<?php

'database' => [
    'tables' => [
        'hidden' => ['migrations', 'data_rows', 'data_types', 'menu_items', 'password_resets', 'permission_role', 'settings'],
    ],
    'autoload_migrations' => true,
],
```

You may wish to hide some database tables in the Voyager database section. In the database config you can choose which tables would like to hide.\
`autoload_migrations` allows you to exclude Voyagers migration-files from loading when running `php artisan migrate`.

## Multilingual

```php
<?php

'multilingual' => [
    'enabled' => false,
    'default' => 'en',
    'locales' => [
        'en',
        //'pt',
    ],
],
```

You can specify whether or not you want to **enable** mutliple languages. You can then specify your **default** language and all the support languages (**locales**)

Read more about multilanguage [here](/1.3/core-concepts/multilanguage).

## Dashboard

```php
<?php

'dashboard' => [
    'navbar_items' => [
        'Profile' => [
            'route'         => 'voyager.profile',
            'classes'       => 'class-full-of-rum',
            'icon_class'    => 'voyager-person',
        ],
        'Home' => [
            'route'         => '/',
            'icon_class'    => 'voyager-home',
            'target_blank'  => true,
        ],
        'Logout' => [
            'route'      => 'voyager.logout',
            'icon_class' => 'voyager-power',
        ],
    ],
    'widgets' => [
        'TCG\\Voyager\\Widgets\\UserDimmer',
        'TCG\\Voyager\\Widgets\\PostDimmer',
        'TCG\\Voyager\\Widgets\\PageDimmer',
    ],
],
```

In the dashboard config you can add **navbar\_items**, make the **data\_tables** responsive, and manage your dashboard **widgets**.

**navbar\_items** Include a new route in the main user navbar dropdown by including a 'route', 'icon\_class', and 'target\_blank'.

**data\_tables** If you set 'responsive' to true the datatables will be responsive.

**widgets** Here you can manage the widgets that live on your dashboard. You can take a look at an example widget class by viewing the current widgets inside of `tcg/voyager/src/Widgets`.

## Primary color

```php
<?php

'primary_color' => '#22A7F0',
```

The default primary color for the Voyager admin dashboard is a light blue color. You can change that primary color by changing the value of this config.

## Show developer tips

```php
<?php

'show_dev_tips' => true,
```

In the Voyager admin there are developer tips or notifications that will show you how to reference certain values from Voyager. You can choose to hide these notifications by setting this configuration value to false.

## Additional stylesheets

```php
<?php

'additional_css' => [
    //'css/custom.css',
],
```

You can add your own custom stylesheets that will be included in the Voyager admin dashboard. This means you could technically create a whole new theme for Voyager by adding your own custom stylesheet.

Read more [here](/1.3/customization/additional-css-js).

{% hint style="info" %}
The path will be passed to Laravels [asset](https://laravel.com/docs/helpers#method-asset) function.
{% endhint %}

## Additional Javascript

```php
<?php

'additional_js' => [
    //'js/custom.js',
],
```

The same goes for this configuration. You can add your own javascript that will be executed in the Voyager admin dashboard. Add as many javascript files as needed.

Read more [here](/1.3/customization/additional-css-js).

## Google Maps

```php
<?php

'googlemaps' => [
    'key'    => env('GOOGLE_MAPS_KEY', ''),
    'center' => [
        'lat' => env('GOOGLE_MAPS_DEFAULT_CENTER_LAT', '32.715738'),
        'lng' => env('GOOGLE_MAPS_DEFAULT_CENTER_LNG', '-117.161084'),
    ],
    'zoom' => env('GOOGLE_MAPS_DEFAULT_ZOOM', 11),
],
```

There is a new data type called **coordinates** that allow you to add a google map as a datatype. The user can then drag and drop a pin in the Google Maps to save a longitude and latitude value in the database.

In this config you can set the default Google Maps Keys and center location. This can also be added to your .env file.

## Allowed Mimetypes

To allow/disallow mimetypes to be uploaded through the media-manager you can define an array `allowed_mimetypes`:

```php
<?php

'allowed_mimetypes' => [
     'image/jpeg',
     'image/png',
     'image/gif',
     'image/bmp',
     'video/mp4',
],
```

The user can only upload files with the given mimetypes. If you want to allow all types to be uploaded you can use the following:

```php
<?php

'allowed_mimetypes' => '*',
```


# Introduction

When adding or editing the current BREAD for a database table you will first see the BREAD info which allows you to set the Display Names, slug, icon, `Model` and Controller Namespace, Policy Name. You can also choose if you would like to Generate permissions for that BREAD type.

![](/files/-LrOVMIItVyfqzcxmTog)

When you scroll down you will see each of the rows that are associated with that table where you can select where in your views you want to see each of those fields:

* BROWSE (field will show up when you browse the current data)
* READ (field will show when you click to view the current data)
* EDIT (field will be visible and allow you to edit the data)
* ADD (field will be visible when you choose to create a new data type)
* DELETE (doesn't pertain to delete so this can be checked or unchecked)

![](/files/-LrOVMIMWx70F-V7bwRL)

You may also choose to specify what form type you want to use for each field. This can be a TextBox, TextArea, Checkbox, Image, and many other types of form elements.

Each field also has additional details or options that can be included. These types are checkbox, dropdown, radio button, and image.

## Validation

Inside of the *Optional Details* section for each row in your BREAD you can also specify validation rules with some simple JSON. Here is an example of how to add a validation rule for *required* and *max length of 12*

```php
{
    "validation": {
        "rule": "required|max:12"
    }
}
```

Additionally, you may wish to add some custom error messages which can be accomplished like so:

```php
{
    "validation": {
        "rule": "required|max:12",
        "messages": {
            "required": "This :attribute field is a must.",
            "max": "This :attribute field maximum :max."
        }
    }
}
```

You can also define multiple rules the following way:

```php
{
    "validation": {
        "rule": [
            "required",
            "max:12"
        ]
    }
}
```

### Action specific rules

You can define separate validation rules for edit and add:

```
{
    "validation": {
        "rule": "min:3",
        "edit": {
            "rule": "nullable"
        },
        "add": {
            "rule": "required"
        }
    }
}
```

You can find a list of all available validation rules in the [Laravel docs](https://laravel.com/docs/validation#available-validation-rules).

## Tagging

Tagging gives you the possibility to add new items to a Belongs-To-Many relationship directly when editing or adding a BREAD.

To activate this function, you simply have to enable `Tagging` in the relationship details

![](/files/-LrOVMIPmLdNCx2OWB6R)

After that you can enter a free-text into the select and hit enter to save a new relationship.

{% hint style="info" %}
**Be aware:**

This only stores the `display-column` so you have to make sure that all other fields are either nullable or have a default value.
{% endhint %}

## Ordering Bread Items

You can define the default order for browsing BREADs and order your BREAD items with drag-and-drop.\
For this you need to change the settings for your BREAD first:

![](/files/-LrOVMIRYEVrkFMc-KyO)

**Order column** is the field in your table where the order is stored as an integer.\
**Order display column** is the field which is shown in the drag-drop list.\
**Order direction** the direction in which the field is ordered.

After this you can go to your BREAD-browse page and you will see a button **Order.**\
Clicking this button will bring you to the page where you can re-arrange your items:

![](/files/-LrOVMITVM9FMcPrHXnB)

## Scope browse-results

If you want to filter the browse results for a BREAD you can do so by creating a [Scope](https://laravel.com/docs/eloquent#local-scopes) in your model. For example if you want to only show posts that were created by the current user, define a Scope like the following:

```php
<?php
public function scopeCurrentUser($query)
{
    return $query->where('author_id', Auth::user()->id);
}
```

Next, go to the BREAD-settings for `posts` and look for the `Scope` input and select `currentUser`:

![](/files/-LrOVMIVVJyOz1sUmMr8)

After hitting `Submit` you will only see your own posts.


# Relationships

Using the BREAD builder you can easily create Relationships between tables. At the bottom of the page you will see a new button that says 'Create Relationship'

![](/files/-LrOVMHPClygrOaaG2o_)

{% hint style="info" %}
**Notice**\
If you have not yet created the BREAD for the table yet, it will need to be created first and then you can come back after creating the BREAD to add the relationship. Otherwise you'll end up with a notification which looks like the following.
{% endhint %}

![](/files/-LrOVMHTtSeOMaYnk2cj)

So, after the BREAD has already been created you will then be able to create a new relationship. After you click on the 'Create a Relationship' button. You will see a new Modal window that looks like the following:

![](/files/-LrOVMHV_E_9RU05lE6w)

You will first specify which type of relationship this is going to be, then you will select the table you are referencing and which Namespace that belongs to that table. You will then select which row combines those tables.

You can also specify which columns you would like to see in the dropdown or the multi-select.

Now, you can easily create `belongsTo`, `belongsToMany`, `hasOne`, and `hasMany` relationships directly in Voyager.

If you need to set advanced options for `belongsToMany` relationship you can set, after saving relationship, these parameters in details field:

```php
{
    "foreign_pivot_key": "user_id",
    "related_pivot_key": "role_id",
    "related_key": "id"
}
```


# Formfields

Formfields are the hearth of Voyagers BREAD-system.\
Each formfield represents a field in your database-table and one input (or output) in BREAD.\
To tweak your formfields you can insert JSON options which are described in the following pages.

All formfields share a handful options:

## Description

All types can include a description in order to help your future self or other users using your Voyager admin panel to understand exactly what a specific BREAD input field is for, this can be defined in the `Optional Details` JSON input field:

```php
{
    "description": "A helpful description text here for your future self."
}
```

## Display options

There are also a few options that you can include to change the way your BREAD is displayed. You can add a `display` key to your json object and change the width of the particular field and even specify a custom ID.

```php
{
    "display": {
        "width": "3",
        "id": "custom_id"
    }
}
```

The width is displayed on a 12-grid system. Setting it with a width of 3 will span 25% of the width.

The **id** will let you specify a custom id wrapper around your element. example:

```markup
<div id="custom_id">
    <!-- Your field element -->
</div>
```

## Default value

Most formfields allow you to define a default value when adding an entry:

```php
{
    "default" : "Default text"
}
```

## Null Values

You might want to save an input field into the database as a `null` value instead of an empty string.

Simply enough, inside the BREAD you can include the following *Optional Details* for the field:

```php
{
    "null": ""
}
```

This will turn an empty string into a `null` value. However you might want to be able to add both an empty string and a `null` value to the database for that field. However you have to choose a replacement for the `null` value, but it can be anything you wish. For example, if you want a field to change a string (ex. `Nothing`) into a `null` value you could include the following *Optional Details* for that field:

```php
{
    "null": "Nothing"
}
```

Now entering `Nothing` into the field will end up as a `null` value in the database.

## Generating Slugs

Using the bread builder you may wish to automatically generate slugs of a certain input. Lets say you have some posts, which have a title and a slug. If you want to automatically generate the slug from the title attribute, you may include the following *Optional Details*:

```php
{
    "slugify": {
        "origin": "title",
        "forceUpdate": true
    }
}
```

This will automatically generate the slug from the input of the `title` field. If a slug does already exists, it will only be updated if `forceUpdate` is set enabled, by default this is disabled.

## Custom view

You can specify a custom view to be used for a formfield.\
To do so, you have to specify the `view` attribute for your desired field:

```
{
    "view": "my_view"
}
```

This will then load `my_view` from `resources/views` instead of the formfield.

You get plenty of data passed to your view for you to use:

* `$view` can be `browse`, `read`, `edit`, `add` or `order`
* `$content` the content for this field
* `$dataType` the DataType
* `$dataTypeContent` the whole model-instance
* `$row` the DataRow
* `$options` the DataRow details

{% hint style="info" %}
**Developing a custom formfield?**\
If you are developing a custom formfield and want to customize any of the views, you can do so by merging `view` into `$options` in your formfields `createContent()` method.
{% endhint %}


# Checkbox/Multiple Checkbox/Radio

## Checkbox

```php
{
    "on" : "On Text",
    "off" : "Off Text",
    "checked" : true
}
```

In Voyager a Checkbox is converted into a toggle switch, and as you can see above the `on` key will contain the value when the toggle switch is on, and the `off` will contain the value that is set when the switch is off. If `checked` is set to *true* the checkbox will be toggle on; otherwise by default it will be off.

## Multiple Checkbox

```php
{
    "checked" : true,
    "options": {
        "checkbox1": "Checkbox 1 Text",
        "checkbox2": "Checkbox 2 Text"
    }
}
```

You can create as many checkboxes as you want.

## Radio Button

```php
{
    "default" : "radio1",
    "options" : {
        "radio1": "Radio Button 1 Text",
        "radio2": "Radio Button 2 Text"
    }
}
```

The Radio button is exactly the same as the dropdown. You can specify a `default` if one has not been set and in the `options` object you will specify the *value* of the option on the **left** and the *text* to be displayed on the **right**.


# Coordinates

## Optional Details

Set these in the Edit BREAD interface

### showLatLngInput / showAutocompleteInput

Set either of these to `false` to not include that input. Both default to `true`.

```javascript
{
  "showAutocompleteInput": false,
  "showLatLngInput": false
}
```

### onChange

```javascript
{
  "onChange": "myFunction"
}
```

Defines an onChange callback so that you can perform subsequent actions (such as using the Autocomplete Place address to populate another field) after the user changes any of the inputs in this formfield.

onChange callback is debounced at 300ms.

First parameter is `eventType` ("mapDragged", "latLngChanged", or "placeChanged"). Second parameter is `data` object containing `lat`, `lng`, and `place` properties.

```javascript
function myFunction(eventType, data) {
  console.log('eventType', eventType);
  console.log('data.lat', data.lat);
  console.log('data.lng', data.lng);
  console.log('data.place', data.place);
}
```


# Date & Time

```php
{
    "format" : "%Y-%m-%d"
}
```

The date & timestamp input field is where you can input a date. In the JSON above you can specify the `format` value of the output of the date. It allows you to display a formatted `date` in browse and read views, using Carbon's `formatLocalized()` method


# Dropdown

```php
{
    "default" : "option1",
    "options" : {
        "option1": "Option 1 Text",
        "option2": "Option 2 Text"
    }
}
```

When specifying that an input type should be a dropdown you will need to specify the values of that dropdown. In the JSON above you can specify the `default` value of the dropdown if it does not have a value. Additionally, in the `options` object you will specify the *value* of the option on the **left** and the *text* to be displayed on the **right**.


# Images

```php
{
    "resize": {
        "width": "1000",
        "height": null
    },
    "quality" : "70%",
    "upsize" : true,
    "thumbnails": [
        {
            "name": "medium",
            "scale": "50%"
        },
        {
            "name": "small",
            "scale": "25%"
        },
        {
            "name": "cropped",
            "crop": {
                "width": "300",
                "height": "250"
            }
        }
    ]
}
```

The image input has many options. By default if you do not specify any options no problem... Your image will still be uploaded. But, if you want to resize an image, set the quality of the image, or specify thumbnails for the uploaded image you will need to specify those details.

**resize** If you want to specify a size you will need to include that in the `resize` object. If you set either **height** or **width** to null it will keep the aspect ratio based on the width or height that is set. So, for the example above the `width` is set to `1000` pixels and since the `height` is set to `null` it will resize the image width to 1000 pixels and resize the height based on the current aspect ratio.

**quality** If you wish to compress the image with a percentage quality you can specify that percentage in the `quality` key. Typically between 70 and 100% there is little notice of image quality, but the image size may be dramatically lower.

**upsize** This is only valid if you have set your image to be resized. If you specify your image to resized to 1000 pixels and the image is smaller than 1000 pixels by default it will not upsize that image to the 1000 pixels; however, if you set `upsize` to true. It will upsize all images to your specified resize values.

**thumbnails** Thumbnails takes an array of objects. Each object is a new thumbnail that is created. Each object contains 2 values, the `name` and `scale` percentage. The `name` will be attached to your thumbnail image (as an example say the image you uploaded was ABC.jpg a thumbnail with the `name` of `medium` would now be created at ABC-medium.jpg). The `scale` is the percentage amount you want that thumbnail to scale. This value will be a percentage of the *resize* width and height if specified.


# Media Picker

The media picker formfield allows you to upload/delete/select files directly from the media-manager.\
You can customize the behaviour with the following options:

```php
{
    "max": 10,
    "min": 0,
    "expanded": true,
    "show_folders": true,
    "show_toolbar": true,
    "allow_upload": true,
    "allow_move": true,
    "allow_delete": true,
    "allow_create_folder": true,
    "allow_rename": true,
    "allow_crop": true,
    "allowed": [],
    "hide_thumbnails": false,
    "quality": 90,
    "watermark": {
        "source": "...",
        "position": "top-left",
        "x": 0,
        "y": 0
    }
}
```

| Name                  | Description                                                                                                                            | Type   | Default       |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------ | ------------- |
| base\_path            | The start path relative to the filesystem                                                                                              | String | /bread-slug/  |
| rename                | Rename uploaded files to a given string/expression                                                                                     | String | Original name |
| delete\_files         | <p>Delete files if the BREAD entry is deleted.</p><p>Use with caution!</p>                                                             | bool   | false         |
| show\_as\_images      | Shows stored data as images when browsing                                                                                              | bool   | false         |
| min                   | The minimum amount of files that can be selected                                                                                       | int    | 0             |
| max                   | <p>The maximum amount of files that can be selected.</p><p>0 means infinite</p>                                                        | int    | 0             |
| expanded              | If the media-picker should be expanded by default                                                                                      | bool   | true          |
| show\_folders         | Show subfolders                                                                                                                        | bool   | true          |
| show\_toolbar         | Shows/hides the whole toolbar                                                                                                          | bool   | false         |
| allow\_upload         | Allow users to upload new files                                                                                                        | bool   | true          |
| allow\_move           | Allow users to move files/folders                                                                                                      | bool   | true          |
| allow\_delete         | Allow users to delete files                                                                                                            | bool   | true          |
| allow\_create\_folder | Allow users to create new folders                                                                                                      | bool   | true          |
| allow\_rename         | <p>Allow users to rename files.</p><p>Use with caution!</p>                                                                            | bool   | true          |
| allow\_crop           | Allow users to crop images                                                                                                             | bool   | true          |
| hide\_thumbnails      | Hides known thumbnails and shows them as children of the parent image                                                                  | bool   | true          |
| quality               | Sets the quality of uploaded images and thumbnails                                                                                     | int    | 90            |
| allowed               | <p>The allowed types to be uploaded/selected.</p><p>Empty object means all types.</p><p>Files with other types won't be displayed.</p> | Object | \[]           |

## Allowed types

If you want your users to only be able to upload specific file-types you can do so by passing an object with mime-types to the \`allowed\` prop, for example:

```
["image", "audio", "video"]
```

or

```
["image/jpeg", "image/png", "image/bmp"]
```

## Expressions

The `base_path` and `rename` can contain the following placeholders:

* `{pk}` the primary-key of the entry (only for `base_path`)
* `{uid}` the user-id of the current logged-in user
* `{date:format}` the current date in the format defined in `format`. For example `{date:d.m.Y}`
* `{random:10}` random string with N characters

So a `base_path` can, for example, look like the following:

```
{
    "base_path": "/my-bread/{pk}/{date:Y}/{date:m}/"
}
```

## Watermark

A watermark can be added to uploaded images. To do so, you need to define a `source` property relative to Voyagers storage-disk. There are a few optional arguments you can use:\
**position** the position where the watermark is placed. Can be:

* top-left (default)
* top
* top-right
* left
* center
* right
* bottom-left
* bottom
* bottom-right

**x** Relative offset to the position on the x-axis. Defaults to 0

**y** Relative offset to the position on the y-axis. Defaults to 0

**size** the size (in percent) of the watermark relative to the image. Defaults to 15

## Thumbnails

You can generate thumbnails for each uploaded image.\
A thumbnail can be one of three types:

### Fit

Fit combines cropping and resizing to find the best way to generate a thumbnail matching your dimensions.\
You have to pass `width` and can pass `height` and `position`.\
An example for `fit` would be:

```
{
    "thumbnails": [
        {
            "type": "fit",
            "name": "fit-500",
            "width": 500, // Required
            "height": 500, // Optional
            "position": "center" // Optional. Refer to http://image.intervention.io/api/fit
        }
    ]
}
```

### Crop

Crop an image by given dimensions and position. You have to pass `width` and `height` and can pass `x` and `y`.\
An example for `crop` would be:

```
{
    "thumbnails": [
        {
            "type": "crop",
            "name": "crop-500-500",
            "width": 500, // Required
            "height": 500, // Required
            "x": 50, // Optional. Left offset
            "y": 50, // Optional. Top offset
        }
    ]
}
```

### Resize

Resize the image to the given dimensions. You have to pass `width` and/or `height`.\
Some examples for `resize`:

```
{
    "thumbnails": [
        // Width will be 500px, height will be calculated based on the aspect-ratio
        {
            "type": "resize",
            "name": "resize-500",
            "width": 500,
            "upsize": true, // Optional. Set to false to prevent upsizing
        },
        // Resizes the image to 500x500px
        {
            "type": "resize",
            "name": "resize-500-500",
            "width": 500,
            "height": 500
        },
        // Height will be 500px, width will be auto-calculated
        {
            "type": "resize",
            "name": "resize-500",
            "width": null,
            "height": 500
        }
    ]
}
```

A watermark can also be inserted into each thumbnail. Just define the [watermark-options](/1.3/bread/introduction-1/media-picker#watermark) on the parent and set `watermark` to `true` for each thumbnail you want to insert the watermark to.


# Number

```php
{
    "step" : 0.1,
    "min" : 0,
    "max" : 10
}
```

These are standard attributes for number input field, default value for step is any if not defined.




---

[Next Page](/llms-full.txt/1)

