At their most basic level, the default views are just PHP files with snippets of html:

<h1>Hello, World!</h1>

Assuming this view is located at /views/default/hello.php, we could output it like so:

echoelgg_view('hello');

For your convenience, Elgg comes with quite a lot of views by default.
In order to keep things manageable, they are organized into subdirectories.
Elgg handles this situation quite nicely. For example, our simple view might live in
/views/default/hello/world.php, in which case it would be called like so:

echoelgg_view('hello/world');

The name of the view simply reflects the location of the view in the views directory.

Elgg automatically adds the magic numbers you see there for cache-busting and
sets long-term expires headers on the returned file.

Warning

Elgg may decide to change the location or structure of the returned URL in a
future release for whatever reason, and the cache-busting numbers change
every time you flush Elgg’s caches, so the exact URL is not stable by design.

The best way to serve third-party assets is through views. However, instead of manually copy/pasting
the assets into the right location in /views/*, you can map the assets into the views system via
the "views" key in your plugin’s elgg-plugin.php config file.

The views value must be a 2 dimensional array. The first level maps a viewtype to a list of view
mappings. The secondary lists map view names to file paths, either absolute or relative to the Elgg root directory.

If you check your assets into source control, point to them like this:

Elgg core uses this feature extensively, though the value is returned directly from /engine/views.php.

Note

You don’t have to use Bower, Composer Asset Plugin, or any other script for
managing your plugin’s assets, but we highly recommend using a package manager
of some kind because it makes upgrading so much easier.

You might be wondering: “Why /views/default/hello/world.php instead of just /views/hello/world.php?”.

The subdirectory under /views determines the viewtype of the views below it.
A viewtype generally corresponds to the output format of the views.

The default viewtype is assumed to be HTML and other static assets necessary to
render a responsive web page in a desktop or mobile browser, but it could also be:

RSS

ATOM

JSON

Mobile-optimized HTML

TV-optimized HTML

Any number of other data formats

You can force Elgg to use a particular viewtype to render the page
by setting the view input variable like so: https://mysite.com/?view=rss.

You could also write a plugin to set this automatically using the elgg_set_viewtype() function.
For example, your plugin might detect that the page was accessed with an iPhone’s browser string,
and set the viewtype to iphone by calling:

elgg_set_viewtype('iphone');

The plugin would presumably also supply a set of views optimized for those devices.

Views in plugin directories always override views in the core directory;
however, when plugins override the views of other plugins,
later plugins take precedent.

For example, if we wanted to customize the hello/world view to use an h2
instead of an h1, we could create a file at /mod/example/views/default/hello/world.php like this:

<h2>Hello, <?=$vars['name'];?></h2>

Note

When considering long-term maintenance, overriding views in the core and bundled plugins has a cost:
Upgrades may bring changes in views, and if you have overridden them, you will not get those changes.

There may be other situations in which you don’t want to override the whole view,
you just want to prepend or append some more content to it. In Elgg this is called extending a view.

For example, instead of overriding the hello/world view, we could extend it like so:

elgg_extend_view('hello/world','hello/greeting');

If the contents of /views/default/hello/greeting.php is:

<h2>How are you today?</h2>

Then every time we call elgg_view('hello/world');, we’ll get:

<h1>Hello, World!</h1><h2>How are you today?</h2>

You can prepend views by passing a value to the 3rd parameter that is less than 500:

// appends 'hello/greeting' to every occurrence of 'hello/world'elgg_extend_view('hello/world','hello/greeting');// prepends 'hello/greeting' to every occurrence of 'hello/world'elgg_extend_view('hello/world','hello/greeting',450);

All view extensions should be registered in your plugin’s init,system event handler in start.php.

elgg_register_plugin_hook_handler('view_vars','page/elements/comments','myplugin_alter_comments_limit');functionmyplugin_alter_comments_limit($hook,$type,$vars,$params){// only 10 comments per page$vars['limit']=elgg_extract('limit',$vars,10);return$vars;}

elgg_register_plugin_hook_handler('view','navigation/breadcrumbs','myplugin_alter_breadcrumb');functionmyplugin_alter_breadcrumb($hook,$type,$returnvalue,$params){// we only want to alter when viewtype is "default"if($params['viewtype']!=='default'){return$returnvalue;}// output nothing if the content doesn't have a single linkif(false===strpos($returnvalue,'<a ')){return'';}// returning nothing means "don't alter the returnvalue"}

This is then used in the provided listing functions.
To automatically display a list of blog posts (see the full tutorial), you can call:

echoelgg_list_entities(['type'=>'object','subtype'=>'blog',]);

This function checks to see if there are any entities; if there are, it first
displays the navigation/pagination view in order to display a way to move
from page to page. It then repeatedly calls elgg_view_entity on each entity
before returning the result.

Note that elgg_list_entities allows the URL to set its limit and offset options,
so set those explicitly if you need particular values (e.g. if you’re not using it for pagination).

Elgg knows that it can automatically supply an RSS feed on pages that use elgg_list_entities.
It initializes the ["head","page"] plugin hook (which is used by the header)
in order to provide RSS autodiscovery, which is why you can see the orange RSS
icon on those pages in some browsers.

If your entity list will display the entity owners,
you can improve performance a bit by preloading all owner entities:

If you want to show a message when the list does not contain items to list, you can pass
a no_results message. If you want even more controle over the no_results message you
can also pass a Closure (an anonymous function).

In the first example, we are displaying a list of groups a user is a member of using the default group view.
In the second example, we want to display a list of groups the user was invited to.

Since invitations are not entities, they do not have their own views and can not be listed using elgg_list_*.
We are providing an alternative item view, that will use the group entity to display
an invitation that contains a group name and buttons to access or reject the invitation.

Since 2.3 you can render lists as tables. Set $options['list_type']='table' and provide an array of
TableColumn objects as $options['columns']. The service elgg()->table_columns provides several
methods to create column objects based around existing views (like page/components/column/*), properties,
or methods.

In this example, we list the latest my_plugin objects in a table of 3 columns: entity icon, the display
name, and a friendly format of the time.

See the Elgg\Views\TableColumn\ColumnFactory class for more details on how columns are specified and
rendered. You can add or override methods of elgg()->table_columns in a variety of ways, based on views,
properties/methods on the items, or given functions.