Questions About Search Form

talkinggoat

Member
I am trying to create a search form, to recover records for end-users, but it's not working. I have followed the directions on the page http://fabrikar.com/forums/index.php?wiki/create-a-search-form/. There are some questions I have, that are probably the reason why it's not working.

  • "make sure they are visible to the user and/or have correct default values" What are the correct default values? Are these the default values for the searchform or default values, as in, when I create a new element?
  • "Edit your searchform" What part of the searchform? The form or group? I'm guessing form, since the next instruction referrs to Jump Page...
  • "Jump page: insert the link to your list you want to filter" Where do I get this link? Can it be relative or absolute?
Thank you.
 
"default values": the ones you need/want to set for searching
"Edit your searchform": yes, searchform
"Jump page":
for details for the redirect plugin see http://fabrikar.com/forums/index.php?wiki/redirect-form-plugin/
with a search form you typically want to filter a list, so see also http://fabrikar.com/forums/index.php?wiki/filtering-lists-tables/#filtering-via-the-url

Do you really need a search form?
Standard list filtering can easier be done via list filters (search all, element filters).
 
If I wanted to have a user enter their ID and Phone# to pull up their rescue ticket, and their id is 1234 with the phone number 1234567890, I would use:
index.php?option=com_fabrik&view=list&listid=3&rescue_request__id[value][]=1234&rescue_request__primary_phone[value][]=1234567890&rescue_request__id[join]=AND

Or would it be:

index.php?option=com_fabrik&view=list&listid=3&rescue_request__id[value][]=1234&rescue_request__primary_phone[join]=AND&rescue_request__primary_phone[value][]=1234567890&rescue_request__primary_phone[join]=AND

Both records have to match, to return a value.

Just tried:
/index.php?option=com_fabrik&view=list&listid=3&resetfilters=1&rescue_requests__primary_phone[value]=1234567890

But it returns the entire table, not the row I am looking for.

I figured out there are 3 underscores between the table and the key, requests and primary, in this example.
 
Last edited:
The shorthand would just be ...

&rescue_request___id=1234&rescue_request___primary_phone=1234567890&resetfilters=1

... as it'll default the 'join' to AND, and assume just an element name without [value] is the value.

You need to &resetfilters=1 to make sure we clear any previous session filters and just apply the ones on the query string.

One thing that worries me is you are using rescue_request___id .... hopefully you haven't changed the main 'id' element in any way, left that as the 'internalid' element (and the PK of the list), and added another element to use as your unique ID?

-- hugh
 
I have deleted and re-created the lists, a couple times, now. That's probably why it's doing that, I'm guessing.

So, this needs to be a search form that returns only the data I'm requesting, that corresponds to the ID and Phone, otherwise, anyone could simply clear the filter and gain access to the entire database of rescue requests. Is it even possible to restrict access, this way? Am I going about this the correct way?
 
I can't recall if you said your users have to register first or not? If so, you can restrict access by having a 'user' element on the form, and a pre-filter on the List:

WHERE
Field:user(raw)
Condition: EQUALS
Value:{$my->id}
Type: text

... which will restrict all access of the list data to the logged on user who's ID matches that of the user element. This applies to direct form/details view access as well, not just filtering of lists. So if user A tries to directly load a form belonging to user B, Fabrik will barf.

To prevent people from just removing filters and seeing the whole list, you can set "Require filtering" on the list settings, so any attempt to view the list without a filter gets a "Please apply a filter".

However, I don't really see any reason people should ever see (or have access to) the list itself. Better to do it with a little custom code. Probably a search form like you are doing, but with a submit script that checks to see if the id/email matches, and if it does, generate a token, store it in the session data, and redirect to the actual rescue form itself (rather than a list) with that token on the query string, with an onLoad script that checks the query string token against the session token.

It'd be easier for me to just write that for you directly, rather than do it here. But the gist of it would be ....

A PHP plugin on the search form, running 'onBeforeProcess', which does something like ...

Code:
// get the search ID and email
$searchId = $formModel->formData['___search_id'];
$email = $formModel->formData['___email'];

// look them up in the rescue_request table
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('id')
   ->from('rescue_request')
   ->where('search_id = ' . $db->quote($searchId))
   ->where('email = ' . $db->quote($email));
$db->setQuery($query);
$rowid = $db->loadResult();

// either redirect to rescue_request form, or back to search
$app = JFactory::getApplication();
if (!(empty($rowid)) {
   // we found it, so create a token (hash the search id, email and rowid
   $token = md5($searchId . $email . $rowid);
   // store the token in the server session
   $session = JFactory::getSession();
   $session->set('rescue.token', $token);
   // redirect to rescue form, appending token as query string arg
   $app->redirect('index.php?option=com_fabrik&view=form&id=123&rowid=' . $rowid . '&rescuetoken=' . $token;
}
else {
   // redirect back to search form with msg
   $app->enqueueMessage('Sorry, we didn't find anything, try again');
   $app->redirect('index.php?option=com_fabrik&view=form&formid=321');
}

... then on the rescue_request form, a PHP script 'onLoad' ...

Code:
// only check token if it's not a new form.
// can add a check here for membership of admin group as well, so admins can edit
if (!$formModel->isNewRecord()) {
   // recreate the token from the data being loaded
   $formToken = md5($formModel->['rescuew_request___search_id'] . $formModel->data['rescue_request___email'] .             $formModel->data['rowid']);
   // get (and clear) the session token
   $session = JFactory::getSession();
   $sessionToken = $session->get('rescue.token');
   $session->clear('rescue.token');
   // get the url token
   $app = JFactory::getApplication();
   $urlToken = $app->input->get('rescuetoken', '');

   if (!($formToken === $sessionToken && $sessionToken === $urlToken)) {
      // whoa!  they aren't the same, so bail back to the search form
      $app->enqueueMessage('Sorry, eomthing went wrong, try again');
      $app->redirect('index.php?option=com_fabrik&view=form&formid=321');
   }
}

So the flow is ...

Hit search form, submit
During search form submission, if a matching row is found, create a token, save it in session, redirect to load the form with token on the query string.
During loading the main form, makes sure the session and query string token match, plus generate the same token from the actual form data just for added heck of it.

-- hugh
 
Last edited:
Also, when the rescue request is first created, you can calculate that hash and create a direct link to the form in the email / text, so they don't have to go through the search form, but you still have the added security of the hash.

Also ... as we're discussing this in a public forum, probably change that hash up a little in your actual production code.

-- hugh
 
Sorry, Hugh. I've been busy at work. Again, thank you for helping.

When someone navigates to the website to lodge a rescue request, they should not have to create an account, simply enter in all their information. Once they enter it in, we would like them to be able to check on the status of their rescue, see if someone has been assigned, etc. The only people that should have accounts are our people. Will that still work with what you submitted, above?

Thank you,
C
 
We are in need of some funding.
More details.

Thank you.

Members online

Back
Top