{"id":4087,"date":"2019-03-24T18:24:28","date_gmt":"2019-03-24T18:24:28","guid":{"rendered":"https:\/\/help.perfexcrm.com\/?p=4087"},"modified":"2025-10-16T11:11:50","modified_gmt":"2025-10-16T11:11:50","slug":"module-basics","status":"publish","type":"post","link":"https:\/\/help.perfexcrm.com\/module-basics\/","title":{"rendered":"Module Basics"},"content":{"rendered":"\n<div class=\"st-alert st-alert-info \">The modules documentation is valid starting from version <b>2.3.2<\/b><\/div>\n\n\n\n<p>Perfex CRM modules use the Codeigniter PHP framework code base like controllers, models, language files, libraries, views etc&#8230; if you are already familiar with the Codeigniter framework, you will be able to easily get started, if not we recommend you to visit their official <a href=\"https:\/\/codeigniter.com\/\">website <\/a>and <a href=\"https:\/\/codeigniter.com\/docs\">documentation<\/a>.<\/p>\n\n\n\n<p>Additionally, we added a bunch of helper functions, features, action hooks and filters that will make the process of creating and integrating modules easier.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Modules location &amp; Name<\/h3>\n\n\n\n<p>All modules should be added in the <strong>modules <\/strong>folder in your root directory where Perfex CRM is installed and <strong>each module must have a unique folder name and init file with the same name as your module folder name<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"> Creating your first module<\/h3>\n\n\n\n<div class=\"st-alert st-alert-info \">Before start to develop a module, make sure that you set <a href=\"https:\/\/help.perfexcrm.com\/faq\/how-to-set-debug-mode\/\">development mode<\/a> in order to see any errors and functions\/hooks deprecation warnings.<\/div>\n\n\n\n<p>To get started and create your first module, follow the steps below.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Navigate to Perfex CRM installation and open the <strong>modules <\/strong>directory<\/li>\n\n\n\n<li>Create a new directory and name it after your module (e.q. <strong>sample_module<\/strong>)<\/li>\n\n\n\n<li>Create a new PHP file <strong>with the same name as the module directory<\/strong>, in this case, <strong>sample_module.php,\u00a0<\/strong>this\u00a0file\u00a0will\u00a0act\u00a0as\u00a0&#8220;<strong>init file&#8221;<\/strong>\u00a0for\u00a0this\u00a0module.<\/li>\n<\/ul>\n\n\n\n<p>In this case, the module is already created and registered but it does not do anything yet nor have any name or descriptions added, we will add the module metadata like name, description, URL, author via a PHP block comment which will act as module headers.<\/p>\n\n\n\n<p>The module headers should be added only in the init module file.<\/p>\n\n\n\n<p>Now open the sample_module.php file we created before and add the following comment at the top of the file:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>&lt;?php\n\n\/**\n * Ensures that the module init file can't be accessed directly, only within the application.\n *\/\ndefined('BASEPATH') or exit('No direct script access allowed');\n\n\/*\nModule Name: Sample Perfex CRM Module\nDescription: Sample module description.\nVersion: 2.3.0\nRequires at least: 2.3.*\n*\/<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">&lt;?<\/span><span style=\"color: #D8DEE9FF\">php<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"> * Ensures that the module init file can&#39;t be accessed directly, only within the application.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"> *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">defined<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">BASEPATH<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">or<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">exit<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">No direct script access allowed<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/*<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">Module Name: Sample Perfex CRM Module<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">Description: Sample module description.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">Version: 2.3.0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">Requires at least: 2.3.*<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">*\/<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>After you save the file, you can navigate in your Perfex CRM admin area to <strong>Setup-&gt;Modules<\/strong> and you will be able to see your module listed.<\/p>\n\n\n\n<p>The comment will act as a file header for the module, you should check the <a href=\"https:\/\/help.perfexcrm.com\/module-file-headers\/\">file headers guide<\/a> if you want to get more familiar.<\/p>\n\n\n\n<div class=\"st-alert st-alert-warning \">Make sure that you always add the <b>Module Name<\/b> header<\/div>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"57\" src=\"https:\/\/help.perfexcrm.com\/wp-content\/uploads\/2019\/02\/sample-module-1024x57.png\" alt=\"\" class=\"wp-image-4089\" srcset=\"https:\/\/help.perfexcrm.com\/wp-content\/uploads\/2019\/02\/sample-module-1024x57.png 1024w, https:\/\/help.perfexcrm.com\/wp-content\/uploads\/2019\/02\/sample-module-300x17.png 300w, https:\/\/help.perfexcrm.com\/wp-content\/uploads\/2019\/02\/sample-module-768x42.png 768w, https:\/\/help.perfexcrm.com\/wp-content\/uploads\/2019\/02\/sample-module-60x3.png 60w, https:\/\/help.perfexcrm.com\/wp-content\/uploads\/2019\/02\/sample-module-150x8.png 150w, https:\/\/help.perfexcrm.com\/wp-content\/uploads\/2019\/02\/sample-module.png 1067w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div class=\"st-alert st-alert-warning \">It&#8217;s very important to <strong>make sure that your module folder name and the .php file name are the same<\/strong>, otherwise, your module won&#8217;t be shown in the modules list<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Basic Hooks<\/h3>\n\n\n\n<p>You will need to implement few basic hooks when creating new module, like <a href=\"https:\/\/help.perfexcrm.com\/common-module-functions\/#register_activation_hook\">register_activation_hook(),<\/a> <a href=\"https:\/\/help.perfexcrm.com\/common-module-functions\/#register_deactivation_hook\">register_deactivation_hook()<\/a> and <a href=\"https:\/\/help.perfexcrm.com\/common-module-functions\/#register_uninstall_hook\">register_uninstall_hook()<\/a><\/p>\n\n\n\n<p>If you are familiar with WordPress, you will probably know the work that these hooks do.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Adding Hooks<\/h3>\n\n\n\n<p>You can add hooks in your module .php files with:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>hooks()->add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1);\nhooks()->add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1);\nhooks()->do_action($tag, $arg = '');\nhooks()->apply_filters($tag, $value, $additionalParams);<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #88C0D0\">hooks<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #88C0D0\">add_action<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">tag<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">function_to_add<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">priority<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">10<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">accepted_args<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">hooks<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #88C0D0\">add_filter<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">tag<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">function_to_add<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">priority<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">10<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">accepted_args<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">hooks<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #88C0D0\">do_action<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">tag<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">arg<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;&#39;<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">hooks<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #88C0D0\">apply_filters<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">tag<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">value<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">additionalParams<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>You can add your own filters and actions so you can use them in your module implementation also, adding actions and filters will help other modules to interact with your module and extend the module functionalities.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Prefix Custom Functions<\/h3>\n\n\n\n<p>You should <strong>always prefix any custom functions<\/strong> and classes to prevent any conflicts with Perfex CRM default functions or classes or with any other modules.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Using Codeigniter Instance in module files<\/h3>\n\n\n\n<p>Probably you will want to use the Codeigniter framework instance in your module init file or any other modules files that are not extending the framework base classes. <\/p>\n\n\n\n<p><strong>$this<\/strong>, only works within your controllers, your models, or your views.<\/p>\n\n\n\n<p>You can achieve this anywhere in your files with the following code:<\/p>\n\n\n\n<p>First, assign the CodeIgniter object to a variable:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>$CI = &amp;get_instance();<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">CI<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&amp;<\/span><span style=\"color: #88C0D0\">get_instance<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #81A1C1\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Once you\u2019ve assigned the object to a variable, you\u2019ll use that variable&nbsp;<em>instead<\/em>&nbsp;of<strong> $this<\/strong><\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>$CI  =&amp;get_instance();\n\n$CI->load->helper('module_name\/helper_name');\n$CI->load->library('module_name\/library_name');<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">CI<\/span><span style=\"color: #D8DEE9FF\">  <\/span><span style=\"color: #81A1C1\">=&amp;<\/span><span style=\"color: #88C0D0\">get_instance<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">CI<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #D8DEE9\">load<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #88C0D0\">helper<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">module_name\/helper_name<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">CI<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #D8DEE9\">load<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #88C0D0\">library<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">module_name\/library_name<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Database Prefix<\/h3>\n\n\n\n<p>From version 2.3.0 Perfex CRM have option to define custom database tables prefix.<\/p>\n\n\n\n<p>The default table prefix in Perfex CRM is <strong>tbl<\/strong><\/p>\n\n\n\n<p>You should always use our custom function <strong>db_prefix()<\/strong> to get the database prefix when querying the database, this will ensure that in case the user changed the database prefix, your module will still work with the new user prefix.<\/p>\n\n\n\n<p>Here is an example from the <strong>Goals Tracking<\/strong> module <strong>install.php<\/strong> file.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#d8dee9ff;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>&lt;?php\n\ndefined('BASEPATH') or exit('No direct script access allowed');\n\nif (!$CI->db->table_exists(db_prefix() . 'goals')) {\n    $CI->db->query('CREATE TABLE `' . db_prefix() . \"goals` (\n  `id` int(11) NOT NULL,\n  `subject` varchar(191) NOT NULL,\n  `description` text NOT NULL,\n  `start_date` date NOT NULL,\n  `end_date` date NOT NULL,\n  `goal_type` int(11) NOT NULL,\n  `contract_type` int(11) NOT NULL DEFAULT '0',\n  `achievement` int(11) NOT NULL,\n  `notify_when_fail` tinyint(1) NOT NULL DEFAULT '1',\n  `notify_when_achieve` tinyint(1) NOT NULL DEFAULT '1',\n  `notified` int(11) NOT NULL DEFAULT '0',\n  `staff_id` int(11) NOT NULL DEFAULT '0'\n) ENGINE=InnoDB DEFAULT CHARSET=\" . $CI->db->char_set . ';');<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">&lt;?<\/span><span style=\"color: #D8DEE9FF\">php<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">defined<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">BASEPATH<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">or<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">exit<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">No direct script access allowed<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">!$<\/span><span style=\"color: #D8DEE9\">CI<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #D8DEE9\">db<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #88C0D0\">table_exists<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #88C0D0\">db_prefix<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">.<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">goals<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #ECEFF4\">))<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">CI<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #D8DEE9\">db<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #88C0D0\">query<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #81A1C1\">CREATE<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #81A1C1\">TABLE<\/span><span style=\"color: #A3BE8C\"> `<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">.<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">db_prefix<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">.<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">goals` (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">  `id` int(11) NOT NULL,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">  `subject` varchar(191) NOT NULL,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">  `description` text NOT NULL,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">  `start_date` date NOT NULL,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">  `end_date` date NOT NULL,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">  `goal_type` int(11) NOT NULL,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">  `contract_type` int(11) NOT NULL DEFAULT &#39;0&#39;,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">  `achievement` int(11) NOT NULL,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">  `notify_when_fail` tinyint(1) NOT NULL DEFAULT &#39;1&#39;,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">  `notify_when_achieve` tinyint(1) NOT NULL DEFAULT &#39;1&#39;,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">  `notified` int(11) NOT NULL DEFAULT &#39;0&#39;,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">  `staff_id` int(11) NOT NULL DEFAULT &#39;0&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #A3BE8C\">) ENGINE=InnoDB DEFAULT CHARSET=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">.<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">CI<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #D8DEE9\">db<\/span><span style=\"color: #81A1C1\">-&gt;<\/span><span style=\"color: #D8DEE9\">char_set<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">.<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">;<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Create Module Options<\/h3>\n\n\n\n<p>Perfex CRM has <g class=\"gr_ gr_7 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar only-ins replaceWithoutSep\" id=\"7\" data-gr-id=\"7\">table<\/g> in database <strong>options <\/strong>for storing various settings for internal usage and settings that are used in features. We have developed custom PHP functions that will perform queries to fetch options from database.<\/p>\n\n\n\n<p>Option names are strings, and they must be unique so that they do not conflict with either Perfex CRM or other Modules. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>add_option($name, $value, $autoload)<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #88C0D0\">add_option<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">name<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #88C0D0\"> <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">value<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #88C0D0\"> <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">autoload<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p><strong>$name<br><\/strong>Required (string). The name of the option to be added, make sure it&#8217;s unique and prefixed with E.q. your module name.<br><br><strong>$value<br><\/strong>The option value (string)<\/p>\n\n\n\n<p><strong>$autoload<\/strong><br>(integer) 1 or 0<br>Whether this option should be autoloaded with all other options, if you are using the option too much time in the view, the best is to autoload it to prevent multiple queries in order to get the option. Defaults to 1<\/p>\n\n\n\n<p>Keep in mind that <strong>add_option  <\/strong>function won&#8217;t create the option if the option name already exists in the options table.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>get_option($option_name);<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #88C0D0\">get_option<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">option_name<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Retrieve an option from database, <strong>$option_name<\/strong> (string) your option name.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>update_option($option_name, $new_value);<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #88C0D0\">update_option<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">option_name<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #88C0D0\"> <\/span><span style=\"color: #81A1C1\">$<\/span><span style=\"color: #D8DEE9\">new_value<\/span><span style=\"color: #ECEFF4\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The <strong>update_option <\/strong>function will update the option value, since version 2.3.3, when you call <strong>update_option if the option not exists, Perfex CRM will create this option.<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Perfex CRM modules use the Codeigniter PHP framework code base like controllers, models, language files, libraries, views etc&#8230; if you are already familiar with the Codeigniter framework, you will be able to easily get started, if not we recommend you to visit their official website and documentation. Additionally, we added a bunch of helper functions, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[54],"tags":[],"class_list":["post-4087","post","type-post","status-publish","format-standard","hentry","category-modules"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/help.perfexcrm.com\/wp-json\/wp\/v2\/posts\/4087","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/help.perfexcrm.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/help.perfexcrm.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/help.perfexcrm.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/help.perfexcrm.com\/wp-json\/wp\/v2\/comments?post=4087"}],"version-history":[{"count":0,"href":"https:\/\/help.perfexcrm.com\/wp-json\/wp\/v2\/posts\/4087\/revisions"}],"wp:attachment":[{"href":"https:\/\/help.perfexcrm.com\/wp-json\/wp\/v2\/media?parent=4087"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/help.perfexcrm.com\/wp-json\/wp\/v2\/categories?post=4087"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/help.perfexcrm.com\/wp-json\/wp\/v2\/tags?post=4087"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}