The Developer Guide includes detailed instructions on declaring a new entity which begins with this:

If you want your extension to store data in the database, then you will need to create a new entity.

The steps include:

  1. create XML schema
  2. create DAO
  3. create BAO
  4. create SQL to create/drop your table
  5. create Api

I must confess that I have stowed new data in a more lightweight way on several extensions - e.g. I've created an API Entity that handles the SQL itself, skipping the creation of XML, DAO and BAO.

I am sure there are good reasons for the detailed set of steps but it's not clear to me what benefits they bring?

In black-box thinking, an extension that needs to use a new table needs to be able to create the table, provide an Api for using it, delete the table on uninstall. Are there cases, e.g. a table for a very extension-specific use case, when it is sensible to avoid the overhead of all the extra boilerplate code (schema, DAO, BAO)?

4 Answers 4


If you want your extension to store data in the database, then you will need to create a new entity.

IMHO, this line miscommunicates a little. The value of generate:entity comes when you want to define an entirely new entity with a full CRUD functionality in APIv3. There are times when you'd do this. But if that's not the goal, then there are certainly other ways to store data which may be simpler, e.g.

  • You can often store data using a core entity (like Activity or Contact), possible with custom fields.
  • You might create a bare SQL table and generate the SQL code in your own way.

IMHO, the docs for generate:entity should not negate the value of these other approaches.


The benefit of going through the pain of DAO and co is not obvious for me neither, and I have to confess skipping them and doing it the same way as you did.

One key reason would be to benefit from all the security that the DAO handles by default: are you sure your extension is done properly and you properly escape all the SQL?

On other reason might be documentation: it might be easier to find which fields exist/are mandatory based on the schema/BAO. Eg. on the API explorer, are all the fields for your extension properly shown and do they have their description?

I know that some work was done to use a more modern SQL abstraction than the one we have, but I don't think it is something that we could use in extensions. Would be super useful IMO.

  • Thanks, Xavier, yeah, I've just used $result = CRM_Core_DAO::executeQuery($sql, $queryParams); a lot with placeholders and typed params. I get it that schema is useful for API documentation, I had a hunch that was something to do with it. But the dance you have to do to get there is pretty elaborate! May 11, 2017 at 10:54

I'm guessing that if it wasn't so painful (e.g. if there was a CLI command or similar that created the boilerplate and so on) then you would just follow the guidance and not question the reasons.

I have skipped them in the past, esp. for more trivial extensions, but went to the effort recently, on a more complex extension.

Not having to worry as much about security (as Xavier mentioned) is one reason. Allowing exposure to BAO level hooks like https://docs.civicrm.org/dev/en/master/hooks/hook_civicrm_pre/ might be another (though I haven't thought too much about this reason).

Following CiviCRMs conventions is possibly another. Though having said that. I do agree with the sentiment of the question and we should be trying to work out which conventions are useful and which aren't.

  • Thanks, Michael, can you elaborate about the BAO level hook example? May 11, 2017 at 11:43

Another reason to have full-blown entities that make use of core-like DAOs is that you inherit a bunch of API magic, like the ability to do API joins across tables, the use of get options, etc.

  • Yeah, I had a hunch it might bring that in. Thanks. May 16, 2017 at 18:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.