Civix¶
Introduction¶
The civix
command-line tool is the community-endorsed method for building your CiviCRM extensions.
Follow the installation instructions in the GitHub repository.
After fulfilling the Pre-Requisites, you can verify that all your configuration is correct by running the following command from within your extensions directory with:
civix civicrm:ping
This command should reply with "Ping successful". If the ping is unsuccessful, re-read the civix README.md and do the post-installation configuration.
It is also useful to examine the output of the civix help
command to read about what civix
can do for you.
Help is available on individual commands, e.g.,:
civix help civicrm:ping
Generate a skeletal extension¶
To generate a skeletal extension module, we will use civix generate:module
and pass in the name for our extension. See Extension Names documentation for details of naming conventions.
Start with:
cd $YOUR_EXTENSIONS_DIR
civix generate:module --help
Then use a command like this:
civix generate:module myextension
This command will report that it has created three files, following the standard extension structure.
The command attempts to auto-detect authorship information (your name and email address) by reading your git
configuration. If this fails or is otherwise incorrect, then you may pass explicit values with --author
and --email
.
You can now update your info.xml
. This file initially contains some examples and placeholders which you need to fix. You can edit most of these fields intuitively. If you need detailed specifications, see Extension Reference.
Now that you have created your extension, you need to activate it by navigating to:
Administer » System Settings » Extensions
For more detailed instructions, see Extensions.
Test your knowledge
A small quiz to test your understanding:
Add features¶
There are many different features that you can add to a module-extension at your discretion. A few possibilities:
Add a unit-test class¶
Unit-testing is essential to maintain quality-control over your extension. Ideally you write unit tests as you write your main code - this also helps you to writer cleaner, testable code. When developing a test case for a CiviCRM extension, it is useful to run the test case within an active, clean CiviCRM environment. The combined CiviCRM civix
testing tools will automate this as long as you follow a few basic conventions.
The following steps will create and run a test in your extension.
Explore the full options with:
civix help generate:test
To create a skeletal test-class choose a class name in your extension's namespace (\Civi\Myextension) that ends with the word Test:
civix generate:test \\Civi\\Myextension\\Test
This creates a new directory and a new PHP file:
tests/phpunit
is the base directory for all test classes.tests/phpunit/Civi/Myextension/Test.php
is the actual test class. It should be written according to the conventions of PHPUnit.
To make sure you can run the test civix needs to know where the CiviCRM base install is located.
The skeletal test class does not do anything useful. For more details on how to write a test class:
- Read PHP Unit Manual: Writing Tests for PHPUnit..
- For more about testing in the CiviCRM environment see our testing documentation
To run the tests see the instructions for running PHPUnit tests.
Add a new entity¶
This allows your extension to create its own database tables and expose them to the CiviCRM API.
Consider Custom Fields
An alternative to creating your own database tables with this command would be custom fields.
civix generate:entity MyEntity
This creates a skeletal file for your entityType.php
, and a corresponding APIv4. For complete documentation on
creating entities, see chapter Create entity: step-by-step.
Tip
By default, the generated API will inherit from a base class which includes all CRUD and metadata actions. Read more about APIv4 architecture for help writing custom APIv4 actions.
Test your knowledge
A little quiz to test your knowledge:
Troubleshooting
- Older versions of civix may not automatically add the mixin
entity-types-php@2.0
to yourinfo.xml
file. Ensure that line is present. - In order to auto-install your sql tables, your
info.xml
file must also include an<upgrader>
tag that points to anAutomaticUpgrader
class. The latest version ofcivix
will add this for you, using the following command:
Add a database upgrader, installer and uninstaller¶
If your module requires creating or maintaining SQL tables, then you should create a class for managing database upgrades. The upgrader adds a class for managing installs and upgrades but you then need to edit the file comment out the various upgrade and uninstall functions to make it work. Generally your install script belongs in an sql/
folder in the root of your extension with a name like 'install'.
This civix
command does not require arguments:
civix generate:upgrader
This creates one file and one directory:
CRM/Myextension/Upgrader.php
stores a series of upgrade functions based on a function naming pattern similar to Drupal's hook_update_N. After examining the file's comments for example upgrade functions you can then write your own.- sql
After reviewing the examples and creating your own upgrade functions, you can execute the upgrades through the web interface by visiting the "Manage Extensions" screen. This screen will display an alert with an action-link to perform the upgrades.
Note
The "upgrader" class is a wrapper for hook_civicrm_upgrade which aims to be easy-to-use for developers with Drupal experience. If you need to organize the upgrade logic differently, then consider providing your own implementation of hook_civicrm_upgrade.
Caution
Only use the upgrade system to manage new SQL tables. Do not manipulate core schema.
If you need to create triggers on core SQL tables, use hook_civicrm_triggerInfo. This allows your triggers to coexist with triggers from other modules.
Export a managed entity¶
This command bundles preconfigured data such as CustomFields, Afforms, or SearchDisplays into the extension.
- Create the record(s) you want in CiviCRM (on a live site, or preferably on a demo or test installation).
- On the command line,
cd path/to/your/extension
, thencivix export EntityName id
. (To get the ID of the entity, either look at the URL, look it up in the database, or list it in the API4 explorer). - This will generate a
.mgd.php
file in your extension'smanaged
directory (or when exporting Afforms,.aff.*
files in theang
directory). - Afterwards you can optionally adjust the
update
andcleanup
settings in the generated file.
Example: Export a custom group with all of its custom fields:
civix export CustomGroup 12
civix export SavedSearch 34
civix export Afform nameOfMyForm
Type civix export -h
for more info about the command.
Add custom fields¶
It's often useful for extensions to automatically create custom fields where the extension's data can be stored.
To add custom fields to an entity that already supports them (e.g. Activities, Contacts, etc.), simply follow the civix export
steps above to create your custom group and export it to a .mgd.php
file in your extension.
Dependencies
Some entities belong to optional core extensions (Event, Mailing, Contribution, etc), or optional 3rd-party extensions (Discount, etc.).
In order to programmatically add custom fields to these entities, mark their extensions as required in your extension's info.xml
.
If you wish to create custom fields for an entity that does not support custom fields out of the box you will need to add a new option value to the cg_group_extends
option group.
Documentation for doing so can be found at Enabling Custom Data.
Accessing Custom Fields¶
For setting and getting custom field values, APIv4 explorer is your friend. Try doing get
, and create
and update
within the Explorer and you will see a code example generated.
Caution
Note that custom field values may not always be available when you might expect. For instance, you can't retrieve custom field values in the 'create' operation in the _pre and _post hooks, because the custom field values haven't been stored yet. However, you can retrieve values in the 'edit' operation.
Add a basic quickform web page¶
CiviCRM uses a typical web-MVC architecture. To implement a basic web page, you must create a PHP controller class, create a Smarty template file, and create a routing rule. You can create the appropriate files by calling civix generate:page
.
Once again you can review the output of this command to see the available options:
civix generate:page --help
Generally you will only need to supply the PHP class name and web-path, for example:
civix generate:page MyPage civicrm/my-page
This creates three files:
xml/Menu/myextension.xml
defines request-routing rules and associates the controller ("CRM_Myextension_Page_Greeter") with the web pathcivicrm/my-page
.CRM/Myextension/Page/MyPage.php
is the controller which coordinates any parsing, validation, business-logic, or database operations.templates/CRM/Myextension/Page/MyPage.tpl
is loaded automatically after the controller executes. It defines the markup that is eventually displayed. For more information on the syntax of this file, see the smarty guide.
The auto-generated code for the controller and view demonstrate a few basic operations, such as passing data from the controller to the view.
Note
After adding or modifying a route in the XML file, you must reset CiviCRMs "menu cache". Do this in the CiviCRM user interface (Administer>System Settings>Cleanup Caches and Update Paths), in a web browser by visiting /civicrm/menu/rebuild?reset=1
or, if using Drupal & Drush, by running drush cc civicrm
.
Test your knowledge
A little quiz to test your knowledge:
Add a Quickform Page¶
Caution
The form system (based on QuickForm) is not well documented and the CiviCRM 5.x series have seen a growing number of forms based on Afform. Consider whether creating an Afform could better suit your needs.
CiviCRM uses a typical web-MVC architecture. To implement a basic web form, you must create a PHP controller class, create a Smarty template file, and create a routing rule. You can create the appropriate files by calling civix generate:form
.
The form generation command has similar arguments to civix generate:page
, requiring a class name and a web route:
civix generate:form FavoriteColor civicrm/favcolor
This creates three files:
xml/Menu/myextension.xml
defines request-routing rules and associates the controllerCRM_Myextension_Form_FavoriteColor
with the web pathcivicrm/favcolor
.CRM/Myextension/Form/FavoriteColor.php
is the controller which coordinates any parsing, validation, business-logic, or database operations. For more details on how this class works, see QuickForm Reference.templates/CRM/Myextension/Form/FavoriteColor.tpl
is loaded automatically after the controller executes. It defines the markup that is eventually displayed. For more information on the syntax of this file, see the smarty guide.
The auto-generated code for the controller and view demonstrate a few basic operations, such as adding a <select>
element to the form.
Note
After adding or modifying a route in the XML file, you must reset CiviCRMs "menu cache". Do this in the CiviCRM user interface (Administer>System Settings>Cleanup Caches and Update Paths), in a web browser by visiting /civicrm/menu/rebuild?reset=1
or, if using Drupal & Drush, by running drush cc civicrm
..
Test your knowledge
A little quiz to test your knowledge:
Add a hook function¶
CiviCRM hook functions allow extensions to run extra logic as part of the normal CiviCRM processing. For example, hook_civicrm_buildForm()
allows a module to run logic whenever a web-form is displayed, and hook_civicrm_post()
allows a module to run logic after any entity is saved.
Hook function names follow the Drupal convention of being the module's short-name concatenated to the hook name. This strict but simple naming convention is what allows the CiviCRM core to locate your hook functions and call them at the appropriate times. For example, if our module's main file is myextension.php
and we want to use hook_civicrm_post()
to write to a log file every time a contribution is saved, then our function must be called myextension_civicrm_post()
.
To implement a hook, add a function to the module's main .php
file created earlier with civix generate:module
:
/**
* Implementation of hook_civicrm_post
*/
function myextension_civicrm_post(string $op, string $objectName, int $objectId, &$objectRef) {
switch ($objectName) {
case 'Contribution':
$file = '/tmp/contributions.log';
$message = strtr("Performed \"@op\" at @time on contribution #@id\n", array(
'@op' => $op,
'@time' => date('Y-m-d H:i:s'),
'@id' => $objectId,
));
file_put_contents($file, $message, FILE_APPEND);
break;
default:
// nothing to do
}
}
Note
When you first created the skeletal project, several hook functions were auto-generated in myextension.php
. These functions are usually about one line long – they simply delegate the work to another function. For example myextension_civicrm_config()
delegates work to _myextension_civix_civicrm_config()
. You should feel free to add more code to myextension_civicrm_config()
, but you should preserve the call to _myextension_civix_civicrm_config()
.
Add a resource file¶
To include static resources such as stylesheets, Javascript files, or images place them in your extension directory. To load the files at runtime, see the examples in the Resource Reference.
Upgrade civix¶
What happens when a new version of civix
comes out? Your extension should continue to work as-is -- after all, civix
is just a code-generator.
However, if you generate an extension with one version of civix
(e.g. v16.03), and if you upgrade (e.g. v18.03), and if you run a new generator,
then you could encounter problems. This is because generators and templates evolve over time -- in particular, new templates may rely on new
helpers and stubs in <mymodule>.php
and <mymodule>.civix.php
.
Fortunately, these changes are rare; they tend to have limited impact; and there's documentation for them. From time-to-time, you should check UPGRADE.md for suggestions on updating your code to match the current templates.
Legacy functions¶
Add a case type¶
The generate:case-type
command is now deprecated in favor of exporting a case type as a managed entity.
Legacy documentation can be found in the civix (legacy) chapter.
Add a report¶
The civix generate:report
command is no longer recommended because most of the functionality of CiviReport is replaced by SearchKit.
For archived documentation on the command see Civix (legacy) - Add a report.
Add a custom search (legacy)¶
Legacy Custom Searches are now deprecated. Archived documentation is on this page: Civix (legacy) - Add a custom search.