· 9 years ago · Feb 02, 2017, 07:34 PM
1Using Views Data
2================
3
4As you're probably aware, if you want Views to acknowledge any of your fields, filters, sorts, or contextual filters; you have to declare their existence in the _hook\_views\_data_ within your module. This is a brief guide into how to utilise this functionality.
5
6This guide assumes you have already setup your Views integration using the _API_ hook and you are ready to start declaring fields and other related items for your custom data. The basic structure of the array that is returned by the Views data hook is as follows:
7
8 <Table Name>
9 |-| <Field Name>
10 |--| <Field Info>
11 |
12 |-| <Field Name>
13 |--| <Field Info>
14 ...etc
15
16The tables are the primary keys in the array and their respective fields are contained in each table. Tables have their own section that specifies various pieces of information about that table to Views so it knows how to access the table (a primary key field), if there are any access query alterations that need to occur, a human readable name, if this table is a new _base_ table, as well as any relationships that this table may have to other tables in the database. Below is a basic table declaration:
17```php
18<?php
19 // Define the base group of this table. Fields that don't
20 // have a group defined will go into this field by default.
21 $data['node']['table']['group'] = t('Content');
22
23 // Advertise this table as a possible base table
24 $data['node']['table']['base'] = array(
25 'field' => 'nid',
26 'title' => t('Content'),
27 'weight' => -10,
28 'access query tag' => 'node_access',
29 'defaults' => array(
30 'field' => 'title',
31 ),
32 );
33?>
34```
35The field items contain all of the information related to each field, declaring titles and descriptions, as well as the class names of the handlers that are to be used. Below is an example of a complete field declaration for the Node ID field (ignore the <?php and ?>).
36```php
37<?php
38// nid
39$data['node']['nid'] = array(
40 'title' => t('Nid'),
41 'help' => t('The node ID.'), // The help that appears on the UI,
42 // Information for displaying the nid
43 'field' => array(
44 'handler' => 'views_handler_field_node',
45 'click sortable' => TRUE,
46 ),
47 // Information for accepting a nid as an argument
48 'argument' => array(
49 'handler' => 'views_handler_argument_node_nid',
50 'name field' => 'title', // the field to display in the summary.
51 'numeric' => TRUE,
52 'validate type' => 'nid',
53 ),
54 // Information for accepting a nid as a filter
55 'filter' => array(
56 'handler' => 'views_handler_filter_numeric',
57 ),
58 // Information for sorting on a nid.
59 'sort' => array(
60 'handler' => 'views_handler_sort',
61 ),
62);
63?>
64```
65This example should provide a good guide as to how to implement a Views data entry for a basic field that is stored in an SQL database. You can see that the table name is _node_ and the field name is _nid_. There is a title and help fields to provide the name and description text for the Views UI.
66
67Additionally you can see that this field can be used as a normal field for displaying its contents, as an argument (or contextual filter) to the View, a filter to limit the results of the View, as well as being able to be used to sort the view.
68
69Within each of those items; _field_, _argument_, _filter_, _sort. There is a _handler_ entry that contains the class name of the handler that will be used for this item. These can also contain additional metadata that we'll touch on later. For now be aware that you must consider how your item will be used within Views, and you have to declare the respective handlers here. Otherwise your item will not be available.
70
71## Some Examples...
72
73### Declaring your own data.
74
75To begin with, lets try to expose our contrived SQL table below to Views.
76
77 mydata_table
78 |-- _id (int)
79 |-- name (varchar)
80 |-- created (int)
81 |-- contents (text)
82 |-- metainfo (varchar)
83
84Within your _hook\_views\_data_ create the entry for the table:
85
86```php
87<?php
88// Declare our table as a new base table to construct Views from.
89$data['mydata_table']['table'] = array(
90 // Specify a group name for the table.
91 'group' => t('My Bonus Content'),
92 'base' => array(
93 'field' => '_id' // Set our primary key field.
94 'title' => t('My Bonus Content Table'),
95 ),
96);
97?>
98```
99That is enough for Views to know that we are declaring a new base table, a _base_ table is the starting point for a View. It is the table from which the View will attempt to load all data that does not come from a relationship to another table. Other base tables include _Node_ (aka Content) and _Taxonomy Term_.
100
101Now we can start to setup our various fields. For starters lets setup our _\_id_ field. We want this field to be visible in the View, so we'll need a field handler, and we want to be able to pass it in as an argument, so we'll need an argument handler as well.
102```php
103<?php
104$data['mydata_table']['_id'] = array(
105 // Give the field a label.
106 'title' => t('My Bonus Content ID'),
107 // Add some help or description text to describe
108 // to the user what this field is. and what it represents.
109 'help' => t('The unique ID of this bonus content.'),
110 // Add our FIELD declaration.
111 'field' => array(
112 // The numeric field handler is suitable.
113 'handler' => 'views_handler_field_numeric',
114 // The handler name must match the class name exactly.
115 ),
116 // We also want to be able to provide it as argument.
117 'argument' => array(
118 // Views provides a handler for this too!
119 'handler' => 'views_handler_argument_numeric',
120 ),
121);
122?>
123```
124That is it for our _\_id_ field declaration! Simple isn't it? If we were to create a View now, we would have an additional choice for the type of data or _base table_ that we're using, our 'My Bonus Content Table'. Within that we would now be able to display the _\_id_ for every entry in that table in a View, or limit our View using an argument that is based on our _\_id_.
125
126But that alone is a bit boring so we should go ahead and create items for the rest of the fields on our table. Remember that not all of your database fields will make sense in a View in the same way. The _name_ field from earlier would make sense as a field to be displayed, but not as an argument to the view. However we might want to be able to sort on the _name_ so that it is displayed alphabetically. So we'd keep the _field_ entry and swap the handler to be <code>views_handler_field</code>. Drop the _argument_ entirely, and add a _sort_ using the <code>views_handler_sort</code> handler.
127
128For a full list of the handlers that are available from Views, have a look in the <code>handlers</code> folder within the Views module itself.
129
130### Field Options and Extra Data
131
132Within both the table and field declarations it is possible to add addtional data which is used by various handlers to provide extra functionality to your fields and table without needing to write in any additional _PHP_ code. We will only cover a few basic examples here as there is simply too much to cover in a single document and remember that to see what is being used or what is available always consult the handler code itself. It is the best documentation for this.
133
134#### Click Sorting (Simple)
135
136The simplest example of this additional data is the <code>click sortable</code> key in a _field_ declaration. You can see an example of this on the _nid_ field snippet from earlier. Add <code>'click sortable' => TRUE,</code> underneath the _handler_ item in your _field_ array. Now when your field is displayed in a table or similar display plugin, the option will be available for the display to be sorted on this field by clicking on the column heading.
137
138#### Additional Fields (Advanced)
139
140If you're creating a custom handler for your field that is a the result of a calculation using a couple of different fields. It is possible to declare within the Views data for this field that whenever it is added to the View, to also make sure to include the data from the additional fields. So when your handler code is run, the data you need is already there without any extra effort on your part. The _additional fields_ array is added to handler section where it is required.
141
142Using our table from earlier... Our _contents_ field contains the basic data stored on our bonus content item, however the formatting information is stored on the metainfo field on the same row. We _could_ include code to pull that information from the database everytime the handler is run in our handler but that would be another database query for everytime the field appears in the View, which is horrible. So let's just add the following under our _handler_ entry in the _field_ section for our _contents_ field:
143```php
144<?php
145'additional fields' => array(
146 // Provide a useful name for the data we're acquiring.
147 'formatting_info' => array(
148 // Tell Views what table it's on.
149 'table' => 'mydata_table',
150 'field' => 'metainfo',
151 ),
152),
153?>
154```
155That's it! Now inside our _field_ handler for this field there will be an array called <code>additional fields</code> that will be keyed by the names provided above and they will contain the data from specified field and table.
156```php
157<?php
158// From within your handler.
159$this->additional_fields['formatting_info'];
160?>
161```
162
163#### Virtual Fields (Advanced)
164
165The final item we're going to discuss is the creation of _virtual_ fields within Views data. These are fields that whilst based on stored information are not actually entries in the database. This is a powerful feature of Views that allows you to move often used functionality and display components into easy to use handlers. One possible use case is a clever price handler that uses various pieces of information to alter how the price is presented based on other information. However we don't want to add this overhead every time the field is used as the raw information is useful as well. So we'll create a _virtual_ price field that suits our needs.
166
167To do this you declare another field entry on the same table where the original field exists, with the addition of the <code>real field</code> key that tells Views which field this one is based on:
168```php
169<?php
170// Give our field a 'machine name' or id to use. This should not
171// match any other field name, existing or virtual. It must be unique.
172$data['mydata_table']['fancy_price_field'] = array(
173 // Title and help fields as normal.
174 'title' => t('Self Formatting Price'),
175 'help' => t('This field will attempt to format itself!'),
176 // The real field value must be a selectable field in the query. It
177 // cannot be another virtual field.
178 'real field' => 'price_field',
179 'field' => array(
180 'handler' => 'views_handler_field_fancy_price',
181 // Capture some addtional formatting field info.
182 'additional fields' => array(
183 // We can drop the table declaration if the additional fields
184 // are on the same table as this field.
185 'local_currency',
186 'currency_symbol',
187 ),
188 ),
189);
190?>
191```
192Now within the <code>views_handler_field_fancy_price</code> handler we will automatically have the <code>price_field</code> information as if this was the price field. Combined with the <code>additional_fields</code> information we can do the hard work in the <code>render</code> step without ever having to worry about selecting the additional information, or overloading the base <code>price_field</code> with options that are more easily contained in a different handler configuration.
193
194### Solr Views Data !
195
196This section covers some of the caveats involved in extending the Solr Views integration.
197
198The most significant part of the Solr Views data declaration is ensuring that the base table value is correct. Within a Solr View the base table is one of the configured Solr environments on that site, identified by the machine name of that instance. So we can't afford to hardcode a base table name because there is just no way of knowing ahead of time. Thankfully the Apache Solr module helps us out here by providing a list of the configured environments, simply call <code>apachesolr_load_all_environments();</code> for an array with all the information you need.
199
200Then following the example provided by the core <code>apachesolr_views</code> module we then create a Views data list of our fields for every configured environment. The snippet based on the <code>apachesolr_views</code> implementation is as follows:
201```php
202<?php
203$data = array();
204$environments = apachesolr_load_all_environments();
205
206foreach ($environments as $env_id => $env_info) {
207 $name = $env_info['name'];
208 $base_table = 'apachesolr__' . $env_id;
209
210 // Example field.
211 $data[$base_table]['ss_string_field'] = array(
212 // You know this bit already. ;)
213 );
214}
215?>
216```
217That's about the only tricky thing to remember when creating Views data to be used for Solr Views. The other important things to note are:
218* Look in the <code>apachesolr_views/handers</code> directory to find the list of available base handlers. Most of these extend the base Views handlers and provide the tweaks and changes necessary to deal with Solr information and syntax.
219* You are still able to create _virtual_ fields as the <code>real field</code> key still works, remembering that you have to use the exact Solr field ID that is indexed. So remember that if that is not a field you control, you should check if the module that provides it is enabled before trying to add your field.
220* The <code>additional fields</code> array is available as well, however you have to declare each item as its own array. So <code>array('placeholder' => array('table' => $base_table, 'field' => $field_id)),</code>.
221* Relationships and Joins are not supported and will be ignored, or might create terrible errors.