Fire Emblem Heroes Wiki:Tutorials/Cargo

This wiki uses the Cargo extension for storing and querying data, acting essentially as a database. This allows for automated methods of creating some pages (eg. Lists), reducing the need for manual maintenance across several pages. A list of all Cargo tables can be found at Special:CargoTables.

Without Cargo, there might be the same information across multiple pages maintained manually (eg. Hero stats are used in multiple places). Previously, these pages needed to all be updated manually any time information changed. If all these pages instead use Cargo to grab the information from the Cargo table, we simply only need to change the information within the Cargo table. Then, all the pages pulling data from the Cargo table would pull the new values and automatically update accordingly.

Understanding templates
Cargo tables are declared and stored into via templates, so understanding Cargo also requires a basic understanding of how templates work. See the tutorial section for templates.

General overview
A simplification of Cargo is as follows:


 * Create/declare the Cargo table
 * Store information into the Cargo table
 * Query information from the Cargo table

The following sections will visit each topic more in-depth.

Declaring the Cargo table
To have a table to store information into, we must first create the table and also decide what kind of information we want stored in the table.

This is done inside the  tags in the template. For more details on what those tags do, see the MediaWiki article on Partial Transclusion, but in short, if we don't put the table declaration in those tags, the declare statement will be called wherever the template is called. We only want it called once on the Template page itself.

The tag for declaring the Cargo table is. Inside the, you will then specify:


 * Name of what you want to call the new table using
 * Name and type (eg. Integer, String, Date, etc) of the columns you want to have in the table
 * See Cargo's section for Declaring a table for a full list of types you can specify

Example
Here is the Cargo declaration from Template:Forging Bonds Infobox which stores information about Forging Bonds events.

In this, the above:
 * Names the table
 * Creates five parameters/columns to be in the table
 * Name - The name of an event.
 * This is type, which is essentially just text. Any text will generally be accepted if a column is type  . These columns are indexed, while columns with type   aren't.
 * Accessories - All the bonus Accessories in an event.
 * This is type . This means it can store multiple values of the type specified after. In this case,   (There can also be ,  , etc.). The   represents the character(s) which separate each item in the list which in this case is a comma. Sample list input in this case would look like  . If we wanted to use another symbol, like a semicolon, we could change this to be.
 * Number - A unique numerical index for each event.
 * This is type . It can store 32-bit signed integers; fractional values, as well as integers that are too large (such as Voting Gauntlet scores), should use the type   instead.
 * StartTime - The date and time an event starts on.
 * It has type  so that only Datetime inputs can be accepted (eg.   won't be accepted as input to store into the table since it is not a datetime.)
 * EndTime - The date and time an event ends on.
 * It has type, but accepts the same datetime values as  . The datetime pair usually denotes the start and end times for a single row.

To create this table, you must first save the template and go to More > Recreate Data or add  to the end of the template URL. This option is only available to admins, so if you do not have the permission to create tables, contact an administrator. Every time the  is modified, a table must be recreated for those changes to show up in the actual table.

After the table is created, go to Special:CargoTables to find the table. For this example, here is the ForgingBonds table with all the information we specified from the code snippet above.

Modifying the Cargo table

 * Follow this guide.
 * You can use Special:TagsReport to find all pages that query the table, and make sure that nothing is broken.

Storing information into the Cargo table
After you've created a new table, there won't be any rows of information yet in the table. To store information, we need to add  tags into the template. These will go inside the  tags instead, so that information could get stored only when the template is transcluded in another page.

The  follows a similar format where you:
 * Specify the table name to store info into
 * List out all the parameters/columns you want to store info into and the information you want to store.

Example
Here is the example  for Template:Forging Bonds Infobox.

As mentioned, inside the  we specify:


 * The name of the table we want to store into
 * In this case,
 * All the parameters and what values we want to store into them.

This template stores the template parameters into each field. As a reminder, the triple curly bracket texts are template parameters passed in. The template parameters from the above code are:



These are the parameters we specify when calling the template. The Forging Bonds infobox template actually has more than just these as template parameters such as, but these are the parameters we want stored into the Cargo table. The following is what a Forging Bonds infobox template call would look like, using the Wikicode from Harmony amid Chaos as the example.

Cargo only cares about the parameters we told it to put into the table in the. The following table represents what would be stored into the table:

If you look up this banner in the Forging Bonds Cargo table, you can see that this is the information stored as well. You may notice that all tables have a  column. This column is the page where a template call and the Cargo store happens. In this case, since we called the Forging Bonds infobox template from Harmony amid Chaos, the stored  is also.

Preventing stores
In some cases, it is desirable to reuse a template in situations where Cargo tables must be kept intact, such as inside user pages. Some templates, such as Passive, allow this to be done using the no cargo parameter. (This is used on the Unused content page to display internal skills without affecting skill queries.) To add no cargo support to your template, the whole  section needs to be surrounded inside a conditional statement as follows:

Then, when a page transcludes the template while also supplying  for the template arguments, no rows will be stored by the template.

Since only pages in the main namespace are expected to store rows into Cargo tables through templates, s should also be protected with a namespace check using. This check is required for all Cargo table templates.

Other times, if a  creates fields that would violate the constraints specified in the   field descriptions, such as storing duplicate values on a   column, the store silently fails and the corresponding row is not created.

Querying information from the Cargo tables
The information stored can now be queried anywhere from the Wiki with a the  tag. There are also several other methods to query the Cargo tables (eg., via Lua using  ), but this section will only cover doing a basic Cargo query. For more information on complex queries, refer to the Cargo documentation on querying data.

A basic  expects:


 * The table name you want to query from

This is the only required information you need to specify to query the Cargo table, and it pulls every single row from the Cargo table. However, this isn't particularly useful. Other options you can include to narrow your search include:


 * fields - The columns you want to specify.
 * where - Condition you can specify to filter out results.
 * Conditions follow MYSQL syntax.
 * limit - The max number of results you want returned.
 * Defaults to 100 if not specified.
 * format - The format you want results to be returned in.
 * See Cargo documentation for a full list of formats you can return Cargo queries in.
 * order by - The order you want results to get returned in.

Although not documented on the MediaWiki Cargo page, REGEXP can also be used in place of = or LIKE.

Example
The following is an example  which gets all pages and bonus Accessories of Forging Bonds events which started in 2019, ordered by their StartTime in ascending order in table format.

This code generates the following:

Styling Cargo query outputs
The above example table output is nice, but there are a few styling issues which could use some work. For example, the column names aren't exactly great header names for the table.

There are three main ways the FEH Wiki creates more complex formats to output in order of complexity. A few examples in the Wiki are included. To view the Cargo query code, view the source of those pages.


 * Using  in
 * e.g. Template:Weapon Type Unit Lists
 * Works for simple tables and text displays
 * May inline template and module calls by escaping curly brackets and pipes with formatting templates, e.g. Template:SkillPage
 * May fail if the parameter is too long (Scribunto does not have this issue)
 * Creating a template to use in the Cargo query via
 * e.g. Light Brand's chart and Template:Unit stat comparison chart
 * Could inadvertently slow down page generation if the template performs its own Cargo queries
 * Less flexible than above method
 * Through Scribunto Lua modules
 * e.g. Template:Hero List and Module:HeroList
 * Lua runs much faster than Cargo queries, and a lot of complex data processing can be done in Lua while reducing the number of query calls
 * May also use
 * Queries via Lua do not translate to Cargo display formats directly, so Lua code must also generate the visual layout
 * Invoking the module without a wrapper template can roughly halve the post-expand include size
 * Not recommended for small templates frequently used in plain wikitext as  adds visual noise

Allowed MySQL functions
These are the currently allowed functions on the wiki, non-default functions are bolded: The following functions are not allowed, but their equivalent operators are available:
 * AVG
 * CEIL
 * CONCAT
 * COUNT
 * DATE
 * DATE_ADD
 * DATE_FORMAT
 * DATE_SUB
 * DATEDIFF
 * DAYOFMONTH
 * FLOOR
 * FORMAT
 * GROUP_CONCAT
 * IF
 * IFNULL
 * LCASE
 * LN
 * LOG
 * LOWER
 * MAX
 * MIN
 * MONTH
 * NEAR
 * NOW
 * POWER
 * ROUND
 * SUBSTRING
 * SUM
 * TRIM
 * UCASE
 * UPPER
 * YEAR
 * MOD → %
 * REGEXP_LIKE → REGEXP / RLIKE

Common fields on the wiki

 * |WikiName=String
 * This field is intended to uniquely identify a row where a page name is insufficient (because, for example, a page may store multiple distinct objects into the same table where all rows need to be distinguished in joins). These fields are often parsed through Template:MF for filename use for example. WikiName fields should not contain any symbols or Unicode characters to avoid technological issues. WikiName fields are for internal use only, and terminology guidelines should still be followed when actually displaying names. All WikiName fields should add the  and   constraints.


 * |TagID=String
 * This field represents the internal string identifier of a row in the game assets. The main purpose of including them in the Cargo database is to allow external scripts to map game entities to wiki page names efficiently. They should not be used in queries for wiki content, but can be freely used in code that generates wikitext from game files, e,g, Module:ScenarioArchiveToWiki. All TagID fields should add the  constraint, but not   since rows may be created after new information is released but before game files are available through updates.


 * |Properties=List of String
 * This field represents an unordered set of properties that apply to a given row. If a property is called, the presence of a property can be checked with the following where-clauses:
 * ; Cargo internally translates this to  with a suitable join, and at most one   statement can be used on each table.
 * ; because of this, properties must not be substrings of other properties, to prevent false positives.
 * The opposite can be checked with the following where-clauses:
 * The  command is not a negation of the   command; it returns true if the row contains any property that is not equal to  . The   commands cannot be used as predicates inside the   function as they are purely Cargo extensions.
 * The  command is not a negation of the   command; it returns true if the row contains any property that is not equal to  . The   commands cannot be used as predicates inside the   function as they are purely Cargo extensions.
 * The  command is not a negation of the   command; it returns true if the row contains any property that is not equal to  . The   commands cannot be used as predicates inside the   function as they are purely Cargo extensions.


 * |StartTime=Start Datetime, |EndTime=End Datetime
 * These fields mark a UTC datetime range, and usually represent the time availability of an object. Both datetimes are inclusive; a time point  is included if , or  . To simplify queries, it is permissible to store  and  respectively into rows without explicit start or end times, but only if the null value does not have a special meaning.