I have a node with 450-500 fields which I have already splitted in small forms that are being load via ajax.
Anyway, when I get the node form before splitting it, the function _field_invoke
(at field.attach.inc
) is taking such a long time that makes the server return a timeout. I'm working in a 1 core 2.2MHz 3.5 GB
Is there any way to speed on this function? Otherwise, what alternatives do I have to speed on the load of a form with 450-500 fields?
EDIT (@Neograph734 comment)
We have a main form with 30 fields, most of them y-n that are used to select sub-forms. The form started to grow as the project was going on, and ended with 10 sub-forms form 30 to 50 fields each one.
We tried to split into different nodes and content types, but we could not find any viable solution: it must be a single document with digital signatures on each form that must be sync one each other, and the whole document follows a status that enables signatures to certain users (when a user has signed every signature field in all sub-forms, then the next user can start to sign). But in fact this is not the question here, as even if there were a better solution, we have no budget now to refactor the whole project, so we have to deal with a form of ~450 fields.
Right now we have rewritten drupal_build_form
functionality to store every prepared sub-form in the cache and load them via ajax. So when a user requests the complete node, we give them the whole node but just the first 30 fields are rendered. We provide empty hidden <div>
's that will be filled via javascript with corresponding sub-forms, on demand.
Basically we keep the forms obtained after drupal_retrieve_form
, drupal_prepare_form
and drupal_process_form
on the cache, but we assign a known cid
and we store it via cache_set
, so later on we can recover them, remove the fields that we don't want to render, render it and deliver it via ajax. In this way we do not render the whole form at once, but we do it on demand.
At first time we tried to remove the fields that were not going to be used by the user, but we found that we could not submit the form: Drupal said that there were missing fields (when a node is saved, the form must be submitted with all fields, even if they are with an empty value, otherwise it raises an error on node save).
So basically what we are doing is:
Node load (get via browser or ajax) -> look in
cache_form
table if we find pre-cached form or sub-form, theircid
are likeform_form-petra_node_form-p0
,form_form-petra_node_form-pa
, etc... andform_state_form-petra_node_form-p0
and so on.If we find the pre-cached form, we load it and pass it through
drupal_prepare_form
, we remove not caching keys (form_state_keys_no_cache()
) and thendrupal_process_form
. This is mostly the same asdrupal_build_form
does. Then we save the new form tocache_form
(withcache_set
, an expire time of 3 hours and a random generatedcid
as it would dodrupal_build_form
) in order to recover it later in post phase. If this is a sub-form, we merge the rendered sub-form with the parent one obtained via browser get (ajax is in charge of doing so).If the form is not there, we prepare it from scratch and save it to
cache_form
as pre-prepared form with expire = 0. Then we follow the same way described just before. This will nearly never happen, as we have installed a cron task that runs once a day and checks if the pre-prepared forms are there or not, and if not, the job prepares them.If it is a post, we recover the cached form with
form_get_cache
and we process it withdrupal_process_form
So basically we have rewritten drupal_build_form
in order to have "static pre-cached forms". This increased speed significatively but right now we are trying to achieve F1 speed with this system.
_field_invoke
does a lot of things, and it calls a lot of other functions too.I have a node with 450-500 fields
SAY WHAT???:O
. A node should never have this amount of fields. Whoever built this site definitely took the wrong approach.