28

I always lay my add-ons out to match the directory structure of a default ExpressionEngine install. For example, check out Freemember on github. I think this makes it most obvious for customers downloading the add-on (believe it or not we used to get questions about where to copy the files to). In Store, my git directory structure looks like this: /system/...


23

The following list should get you started: ExpressionEngine Add-On Development Docs: links to guidelines, reference material, and tutorials for developing Plugins, Modules, and Extensions for ExpressionEngine ExpressionEngine Add-on Development Recipes: a collection of articles and tutorials to help you learn how to build ExpressionEngine add-ons Add-On ...


20

If you need to access a variable repeatedly then you should generally place it within a constructor method and assign it as a class property, rather than continuously checking config values. This approach also gives you the opportunity to set a default value which you can use class-wide if the config item is not found. <?php class Myplugin { var $...


15

The advantage of using a custom plugin (per-project usually) is that you will invariably come up with several small utility tasks to perform during the course of development (not just query-related). It's far cleaner to house these functions under one roof, in one file, rather than sprinkle your templates with custom queries, PHP blocks, and your /...


13

It is also important to note that the Query Module is not safe if you are allowing any user-entered data. The only thing the Query Module does, besides adjusting for pagination if present, is passes the string through to the CI db class (in EE 2.5.3 this is line 181 of /system/expressionengine/modules/query/mod.query.php ) $query = $this->EE->db->...


12

So given the proportion of EE addons that are sold commercially I think this is a relevant question, I also don't think this is a subjective question because the MIT license is actually pretty clear. The relevant section being: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. "...


12

Adding the following script to the control panel allows one to define a custom state for one or more matrix fields. The following script can be modified as needed and then copy and paste into your custom field's "Field Instructions" box beneath your custom user instructions! Many thanks to @MediaGirl for that trick! Ref: How to add a custom JavaScript to ...


11

In this case, I think building your own settings table is the way to go for sure. Using the settings column should really only be for very minor yes/no types of settings, not storing actual data. Especially when you get into supporting MSM, where you need settings for each site, it can get hairy fast. Plus, then your data is more easily searchable and ...


11

There are a couple of ways to create plugins which return entry IDs like that. The first, and most obvious, is for your plugin to return a pipe-separated list of entries, which is then passed to a channel entries tag. In your plugin file: $tag_vars = array(array('search_entry_ids' => '4|6|12|19')); $this->return_data = $this->EE->TMPL->...


10

If you're looking to stick with CodeIgniter's pattern for OOP (which is very standard) you would have your data methods in one or more models, your view files (for a control panel interface) in a views directory and your two module files (mcp.* and mod.*) would act as your two controllers. As such, your directory structure might look something like this: /...


9

Since ExpressionEngine is based on Codeigniter, you can use the CI Config class to fetch config items. http://codeigniter.com/user_guide/libraries/config.html class Myplugin { public $return_data; function Method() { $this->EE =& get_instance(); $item = $this->EE->config->item('myplugin_config_item'); } ...


9

$variables[] = array('variable_name' => 'Your value'); $variables[] = array('variable_name' => 'Different Value'); $variables[] = array('variable_name' => 'Another one'); $this->return_data = $this->EE->TMPL->parse_variables($this->EE->TMPL->tagdata, $variables); It is important to not manually specify indexes for the $...


8

My opinion is that it very much depends on the add-on. Something like Carthrob, for instance, lends itself perfectly to using the native channel entries table as data can be accessed using the channel entries tag and edited in the CP in the usual way. So in this instance, there is no need to re-invent the wheel. If the structure of the data you need to ...


8

You shouldn't be declaring functions inside your __construct() method. Move sliceurl a bit further down, and call it using $this->sliceurl (since it's part of your class): class Youtube_id_from_url { public $return_data = ""; public function __construct($urltag = NULL) { $this->EE =& get_instance(); if (empty($...


8

You can use Ce_string for this, which is the ultimate swiss army knife. {exp:ce_str:ing htmlspecialchars=":CONST:ENT_QUOTES"}<a href='test'>Test</a>{/exp:ce_str:ing}


8

The ‘p’ in your module’s class name must be lowercased. From http://ellislab.com/expressionengine/user-guide/development/modules.html#the-core-module-file-mod-module-name-php: The Core Module file is used for outputting content via Templates and doing any processing that is required by both the Control Panel and any module tags contained in a template. ...


7

ExpressionEngine does not appear to provide a way to deal with this scenario out-of-the-box. One solution would be to create a custom plugin like the following. I have intentionally named this "Utility Functions" because I plan to add additional functionality as needed. But hopefully this will save some time for future readers. <?php $plugin_info =...


7

Most serious modules I know of create their own settings table. It's not ideal, but EE doesn't really offer any built in solutions for modules. If your module has an extension, as Tom mentioned, you can use that to store a serialized array of settings. Alternatively, I know some modules add a settings column to the exp_modules table (obviously after ...


6

My take: if this is a bespoke add-on for private use, only use exp_channel_entries and exp_channel_data if the data you're storing can added/edited using the standard EE publish/edit screens and follows the conventions of those tables (matching entry_id and channel_id, etc). Otherwise you're setting up any future developer for a whole lot of confusion, and ...


6

Yeah, that's the wrong way to go about it. You want to use the load class and use the view() method. You can even pass variables to the view that can be used programmatically. public function display_field($data) { $vars = array( 'data' => $data, 'some_var' => 'some value', 'some_array' => array( '1', ...


6

You probably don't need to build your own plugin for this. If that logic is all you have to worry about then Switchee and a couple of regular expressions are all you need. {exp:switchee variable="{segment_1}" parse="inward"} {!-- Seg 1 = empty. Embed homepage template. --} {case value="''"} {embed="embeds/homepage"} {/case} {!-- ...


6

$mod_data['module_name'] should be class name of your actual module file (mod.photo_pdf.php), in your case 'Photo_pdf'


6

I think you're looking for this page in the EE Developer docs. Basically, if you only need the JS in the Control Panel (so not on the front-end of the site), put your JS files in the /your_addon_package/javascript/ folder and then use $this->EE->cp->load_package_js('my_file'); to load it. If you need the JS outside of the CP as well, you need to ...


6

This is a bit of an undocumented feature, but it works like this. In your extension, add a class variable called $required_by, with an array of values: $required_by = array('module'); ('module' is actually the only acceptable array value here, as neither plugins nor accessories have installation routines, which are needed for this to work.) Note that ...


6

I've created an extension that'll let you do it. https://github.com/jazonv/SafeCracker-HTML5-Attributes In addition to data-foo="bar", it'll also lets you use autocomplete="no" and novalidate="novalidate". (Inspired by this gist by Objective HTML) Disclaimer: I'm by no means a PHP/Add-on dev. I just wanted to 'have a go' too. Hopefully there's nothing ...


6

While you can't actually parse the tag using your custom module, you can pass parameters to the channel module and run it. Here's a code sample: function your_module_method() { // Set the parameters for the channel:entries tag $this->EE->TMPL->tagparams['entry_id'] = $entry_ids; $this->EE->TMPL->tagparams['dynamic'] = 'no'; ...


6

Converting from EE2 to EE3 is easy. All the syntax's etc. are almost same. You just need to create an extra file named addon.setup.php and done. In your case, follow the points below: Open FTP and go to your site/system/user/addons/ Create a Folder named string. Enter in the folder. Create a file named pi.string.php and put this code inside: $...


5

Sounds like a great idea to me. I've added it to the issue list: https://github.com/croxton/Stash/issues/31


5

That's because SLASH is actually the encoded form of /. Here's how it's set: define('SLASH', '&#47;');


5

The full array of tag params is stored at $EE->TMPL->tagparams. So you can grab them like so: // Get the EE instance $EE = get_instance(); // Get all of the current tag params $all_params = $EE->TMPL->tagparams; From there you can loop through and find all of the params that begin with “search:” like this: // Find all of the search:xyz params $...


Only top voted, non community-wiki answers of a minimum length are eligible