Developer Training at CiviCRM Paris

Gepubliceerd
2026-10-26 22:14
Written by
chrp - member of the CiviCRM community - view blog guidelines

The CiviCRM developer training took place at the CiviCRM Paris conference.

I had been programming a CiviCRM extension for a few weeks, as a learning project. It's a simple search engine extension. I learned on my own, solved my issues as they occurred. I followed the developer and user guides. I made good progress, but I could still benefit from a proper training by experts.

In this session, Jaap Jansma and Alain Benbassat showed us how to customize and extend CiviCRM. Noah Miller attended the session to help us with the practical exercises.

The session took two days. The first day walked us progressively through CiviCRM customization, administration and creating an extension. The second day took us deeper into integrating with CiviCRM using hooks and custom API actions. It ended by introducing us to the community aspects of extensions: packaging, distribution and contributing to the core of CiviCRM.

Impressions and learnings

When I registered to attend the developer training, I thought I wouldn't learn much: I already read practically all the user and developer documentation I could find. I had already implemented a small extension. That project showed me the entire CiviCRM stack: PHP code, SQL database, administration, instance deployment.

But I actually gained knowledge that I didn't find in the documentation.

Legacy code and approaches

The CiviCRM project started years ago. Since then, developers have introduced several approaches and technologies into the codebase. It means that the documented approach for extending CiviCRM sometimes overlaps older, newer or alternate approaches.

For example, developers can write PHP modules by following either the legacy CiviCRM approach, or the current standard PHP module system. The choice depends on the purpose of the module.

Hooks constitute another example: A plain CiviCRM hook only requires creating a function with a certain name, to let CiviCRM automatically pick up the function. The new approach involves events. It requires registering the new hook explicitly. It involves writing a certain type of class that injects a function into a dictionary. The dictionary specifies the type of the hook and the new function.

Note: Hooks execute custom functions without the explicit intervention of the user. It makes log messages critical, in order to collect feedback while developing these functions.
Indeed, during the training, I broke my CiviCRM instance several times... I learned the hard way that CiviCRM appends the error messages of the extension to the log file of the instance.

I think this kind of historical knowledge doesn't necessarily belong in the documentation. This makes community events and training sessions all the more valuable.

Idioms, habits and processes

Most software communities follow certain idioms or habits: WordPress favors hooks and filters ("Code is Poetry"). Python promotes "one obvious way to do it", Java promises to "write once, run anywhere"...
I guess for developers, the CiviCRM way would mean enabling organizations to "build, engage, and organize their constituents".

This could explain how users and developers set up or extend CiviCRM. I realized it during the training, by learning to design search pages using the SearchKit and FormBuilder extensions. SearchKit allows organizations to design search calls and display their results. FormBuilder allows organizations to design forms. It allows combining forms with SearchKit elements to build complete search forms, without programming.

Before trying this approach, I programmed a custom search form by myself and from scratch: I wrote a JavaScript component for a specific form interface. I also wrote a specific search call by directly using the CiviCRM backend API in JavaScript.

Now I know that another, more idiomatic approach involves creating a custom CiviCRM entity, a customizable form in FormBuilder and a customizable search in SearchKit. This approach involves less programming, and it enables organizations to configure the new search form.

I had already written an extension before the training. But my extension hadn't moved past the pre-release stage: I didn't know how to deploy it to a production instance. Moreover, I didn't know how to publish it to the official CiviCRM extension catalog.
During the training, I learned which people and tools to involve in the release process.

Next steps

I liked writing the custom JavaScript user-interface code of my search extension...
However, I'll remove this custom code in favor of using SearchKit and FormBuilder: Less code means fewer bugs.
Besides, users appreciate the flexibility provided by SearchKit and FormBuilder. I know it for sure: They said it in sessions and at lunch!
At that stage, most of my extension will consist of hooks to make the default CiviCRM entities support full-text search.

Currently, these custom hooks use the plain hook approach. I'll migrate these custom hooks to the events approach I learned here.
I already tried the events approach without success earlier, but I encountered issues that I could not debug.
Now I know how to print logs and find the error messages of the extension: I will make the events approach work.

Once my extension becomes ready for release, I know where to publish the code.
Once it becomes ready for publication, I know how to add it to the CiviCRM extension catalog.

Now my path seems clear: Let's get back to work!

Discussion

Join the discussion on Mattermost

No comments yet.