
A custom search is a method of providing new functionality within the standard CiviCRM navigation structure. This chapter looks at how to develop a Custom Search.
Custom searches produce a screen showing a set of contacts, from where you can execute actions such as sending email, printing mailing labels, and all the other actions that are available for contact search results within CiviCRM. The results page displays the same as any other search results page, such as results delivered from an Advanced Search, however, a predefined set of functions controls which information is delivered to the result page.
Custom Searches follow the Hollywood principle, "Don't call me, I'll call you." In this case CiviCRM calls your functions at the appropriate time.
In this section we will create a new custom search called "BirthdaySearch" that will find all contacts whose birthdays fall in June.
Custom searches are written using PHP and SQL. Very little knowledge of PHP is needed, as you start with a template file and only make minor changes. In many cases the only changes are the SQL Select statement and which columns to display in the results.
Before writing the code, it is important to plan and test the SQL query and verify the results. It is valuable at this stage to review the database tables and test the SQL select statements within the database using an SQL tool such as PHPMyAdmin.
It may be helpful for you to review the information at:
It is important to include the contact_id field from the table civicrm_contact in your select statement. Even if you do intend to display the contact_id field, include it. The reason is that the view and edit links need the value for the cid attribute of the url. Without a value, you can not edit or view information about the contact. Follow the select statement below for guidance.
Your custom search files can be stored almost anywhere, but you must tell CiviCRM where these files are.
Start by opening the file BirthdaySearch.php in a text editor. The first change needed is to change the class declaration to:
class CRM_Contact_Form_Search_Custom_UpcomingBirthdays
implements CRM_Contact_Form_Search_Interface {
if ( $onlyIDs ) {
$select = "DISTINCT civicrm_contact.id as contact_id,
civicrm_contact.display_name as name";
} else {
$select = "DISTINCT civicrm_contact.id as contact_id, CONCAT(
monthname(civicrm_contact.birth_date) , ' ', day(civicrm_contact.birth_date))
as sort_name , civicrm_contact.display_name as name, 'birthday' as oc_type" ;
}
$from = $this->from( );
$where = $this->where( $includeContactIDs ) ;
$sql = "SELECT $select FROM $from WHERE $where ";
⁞
Before you can run the custom search, CiviCRM needs to be informed that it exists. This is accomplished by the following steps:
The new Birthday Search should now appear in (and can be run from) the list of custom searches in the navigation menu. It will also appear on the page reached by going to Search > Custom Searches.
The new custom search will not appear in the black navigation menu unless the navigation menu is edited. This can be done by going to Administer > Customize > Navigation Menu.
Always test the following behaviors of the new search:
Once you’ve created your custom search, you can start packaging it. Let's say you will be doing an activity search.You need to prepare the info file as described in the Extensions Framework Chapter.
Sample info.xml file
<?xml version="1.0" encoding="UTF-8" ?> <extension key="org.civicrm.activity" type="search"> <callback>ActivitySearch</callback> <name>Activity Search</name> <description> This custom search allows to search through activities and returns activities as results (not contacts as regular search). </description> <url>http://civicrm.org</url> <license>AGPL</license> <maintainer>CiviCRM Core Team <noreply@civicrm.org></maintainer> <releaseDate>2010-09-01</releaseDate> <version>1.0</version> <compatibility> <ver>3.3</ver> <ver>3.4</ver> </compatibility> <develStage>beta</develStage> <comments>For support, please contact project team on the forums. (http://forum.civicrm.org)</comments> </extension>
Then once you have the info file, you can start putting the extension package together. We'll choose "org.civicrm.activity" to be the unique identifier of the extension, so we need to give the same name to the directory that will contain our extension. Once you've created that, put the info.xml file in it.
Remember the "callback" section in info file? We've put the value "ActivitySearch" in there. Now it's time to prepare our custom search PHP class to fit in the package. First of all, put it in the file named exactly after the callback value minus the file extension part. So now we have a second file in our extension directory: ActivitySearch.php. The name of the class that is inside this file should be constructed the following way: "Extension_<Type>_<key>_<callback>" - which means in our case it will be: Extension_Search_org_civicrm_activity_ActivitySearch. It's rather long, but we want to avoid any problems with class name duplication. Please also note, that the extension type is capitalised, but extension key is not.
Ok, we've got the info file, there is a custom search class ready, so the last thing is a template. Just create a subdirectory of org.civicrm.activity named templates and put your template file there. You should name the template the same as your PHP file - so it should be ActivitySearch.tpl.
You should end up with the following structure:
org.civicrm.activity/ |-- ActivitySearch.php |-- README.txt |-- templates | `-- ActivitySearch.tpl `-- info.xml