Skip to content

Mixins: Introduction

Analogy: A PHP "class" can incorporate multiple "traits". Similarly, a CiviCRM "extension" can incorporate multiple "mixin"s.

CiviCRM mixins allow extensions to re-use prepared behaviors. They are enabled and disabled via info.xml. For example:

<extension type="module">
  <mixins>
    <mixin>menu-xml@1.0.0</mixin>
    <mixin>mgd-php@1.0.0</mixin>
  </mixins>
</extension>

This example enables two mixins (menu-xml and mgd-php). These are feature-flags: by enabling the flag, your extension gets access to more services and more functionality.

The implementation of each mixin comes from a PHP file, such as mixin/menu-xml@1/mixin.php or mixin/mgd-php@1/mixin.php. CiviCRM will find and load the appropriate PHP files.

Mixins follow an open architecture, enabling you to write new mixins or use the library of standard mixins.

Mixins always have version numbers. In the info.xml example, it declares a version-constraint ("menu-xml@1.0.0"). In the PHP file, it declares a version-code ("1.0.0").

CiviCRM notes the requested version and loads a compatible version.

Tip: CiviCRM v5.45+ includes full support for mixins. Older releases require a polyfill.

CiviCRM v5.45+ includes the full, built-in system for finding and activating mixins.

Many mixins may be used on older CiviCRM versions if the extension includes the polyfill. civix automatically adds the polyfill if you declare <compatibility> with an older version of CiviCRM.

However, the polyfill lacks some features. See the polyfill documentation for a full comparison.

Tip: If you edit info.xml, then you also need to flush caches.

The list of mixins is stored in a cache. Therefore, if you do anything that affects the list of active mixins, then you need to flush the cache.

cv flush
Tip: Standard mixins can be managed via civix.

Instead of editing info.xml directly, you can call commands like civix mixin and civix upgrade to manage standard mixins. This has some advantages:

  • Civix has a data-set with curated compatibility information.
  • If your target version of CiviCRM lacks support for a specific mixin, then civix exports a copy ("polyfill" or "backport") for use on older systems.
  • If your target version of CiviCRM is entirely incompatible with the mixin, then civix can update the minimum-version.
  • Civix gives more general advice. For example, if a piece of extension code duplicates the functionality of a mixin, then it may suggest how to migrate.
Tip: Standard mixins benefit from transparent maintenance-updates.

The standard mixins are included with CiviCRM. Whenever you upgrade CiviCRM, you will also get a copy of the latest version of each standard mixin. Mixins are loaded by version-precedence, so these newer files will supercede any older ones.

It is usually not necessary for extension-authors to republish an extension for minor mixin maintenance. Users can get the updates transparently from civicrm-core.

However, there are some cases where you may wish to explicitly update and republish your extension:

  • Civix Upgrade: Civix may prod you to upgrade a mixin. Mixins distributed this way go through an extra round of testing to ensure they are suitable for use in a range of environments..

  • Major Changes: Major contract changes do not have transparent updates. If you are using v1.x and want v2.x, then this will likely require some code-updates and republication.

  • Specific Reliance: If a newer mixin adds a feature or bugfix that is specifically important to your extension, then you may wish to bundle the newer version. This means that all your users will get the update (regardless of which version of CiviCRM they use).

Tip: Semantic Versioning: Duplicate mixin-files are resolved based on version-precedence.

On any particular deployment, CiviCRM may find multiple copies of the same mixin. For example:

  • my_ext_a/mixin/menu-xml@1.0.0.mixin.php
  • my_ext_b/mixin/menu-xml@1.0.4.mixin.php
  • my_ext_c/mixin/menu-xml@1.3.0.mixin.php
  • civicrm/mixin/menu-xml@2/mixin.php

Which file will be loaded? This is determined by declared requirements and Semantic Versioning (SemVer).

Suppose the extension (my_ext_b) declares this requirement:

<mixin>menu-xml@1.0.4</mixin>

CiviCRM will load the mixin-file with the highest compatible version. Consider each possible file:

  • menu-xml@1.0.0.mixin.php: This does not satisfy the requirement for 1.0.4. It's too old.
  • menu-xml@1.0.4.mixin.php: This satifies the requirement for 1.0.4 (exactly). It is a valid possibility.
  • menu-xml@1.3.0.mixin.php: This also satisifies the requirement for 1.0.4. (Under SemVer, MINOR updates are drop-in compatible.) It is also newer.
  • menu-xml@2/mixin.php: This does not satisfy the requirement for 1.0.4. (Under SemVer, MAJOR updates are not drop-in compatible.) It's too new.

So menu-xml@1.3.0.mixin.php is the highest compatible version on this system. That's what CiviCRM will load.

For more information, you can see the subchapters here as well as: