PHP validation on repeating elements

Hi,

I'm on V3.0.4

I'm attempting php validation on an element in a repeatable group. I want to check that either the target element or another element in the repeatable group has a value. My problem is retrieving the value of the other element (BookingEnquiry_1_repeat___Members_Staying) is failing. Both elements are integers.

Here's the code I'm using:

$members = JRequest::getVar('BookingEnquiry_1_repeat___Members_Staying');
$total = ($members + $data);
return ($total > 0);

I've attached a capture of the 2 elements as the appear in the Elements list.

What am I doing wrong?
 
if its in a repeatable group then the data will be in an array and not a single value.

if you do

Code:
$members = JRequest::getVar('BookingEnquiry_1_repeat___Member  s_Staying');
print_r($members);
exit;
what do you see for the members value? I would guess its an array. If so then you would need futher code to figure out which repeat group you were validating against etc
 
Can some kind soul please help me with some php on this?
So I'm doing a validation on a repeatable element... how do I access the value of a different element in the same row of the repeatable group?
 
you would have to get the posted data, loop over each set of repeated data , some suedo code might look like this:

PHP:
$post = JRequest::get('post');
$joins = $post['joins'];
$joinid = 3;

// the full element names you want to look at
$oneElement = 'table___elementone';
$twoElement = 'table___elementtwo';

// all the submitted data for the two elements
$oneElementData = $joins[$joinid][$oneElement];
$twoElementData = $joins[$joinid][$twoElement];

//$i is the reference to the current set of repeated data you are looking at
$i = 0;
for ($i = 0; $i < count($oneElementData) $i ++)
{
  echo "one elements data for repeat $i is " . $oneElementData[$i] . "<br>";
  echo "two elements data for repeat $i is " . $twoElementData [$i] . "<br>";
}
exit;
 
Thanks Rob,

A couple of questions on that :)

Would that validation code get run just the once no matter how many sets of repeated data have been entered?

If the validation fails on an element for one set of repeated data (the other sets passing), is there a way to highlight the element in that set only?
 
OK, this reminded me that I never actually resolved this issue when I first ran in to it in Fabrik 2.x.

The basic answer is ... in a repeat group, we call your validation X times, once per repeated instance. And we automagically handle putting the validation fail message on the right repeated instance.

The problem is, we currently don't give your code any way of knowing which repeat instance you are validating. I added something to do that in the main form model, so we pass the repeat instance to the validate() method in the rule, but I never added it to the PHP rule.

So ... I just added that to the PHP validation plugin. So you should now have access to a variable called $repeatCounter, which tells you which instance of a repeat you are currently validating.

So in Rob's example code, to access elementone data for the same repeat instance as the element you are validating (assuming it's in the same group) would be ...

PHP:
$oneElementData = $joins[$joinid][$oneElement][$repeatCounter];

As usual, the $data variable will contain the value for the repeat instance of the element you are currently validating. So, say you wanted to make sure this element was an integer larger than elementone ...

PHP:
return (int)$data > (int)$elementOneData;

And we'll handle putting your failure message on the correct instance.

-- hugh
 
That sounds like it would solve my issues thanks Hugh!
I am using the 3.0.4 installation from the downloads area. Will I be able to just grab the relevant file(s) from github when its available... will it be compatible? What files do I need?
Thanks a heap :)
 
My change should already be in github.

When doing a github update, I always recommend just uploading the whole thing. So grab the 'snapshot' ZIP:

https://github.com/Fabrik/fabrik/zipball/master

... unzip it, and upload EVERYTHING on top of your 3.0.4 install. There's a few things you don't need (like the files at the top level like build.xml, etc. and the fabrikbuild folder), but all the "normal" J! stuff should be uploaded.

Don't rely on any "upload if newer" feature in your ftp client. Just upload everything in "always overwrite" mode. This makes 100% sure that you have a copacetic set of files. Cherry picking certain files from a github update is not recommended, as quite often changes in one file will rely on changes in some other seemingly unrelated file.

It takes a few extra minutes to upload the entire snapshot, but IMHO it's worth the time.

If you are a git power user and like messing with SSH on your server, you can of course fork your own git copy and place it directly in your J! folder tree, and just merge updates from our master as they happen. But I'll leave it up to you if you want to do that, as it's not entirely trivial to set up.

-- hugh
 
Before I move on to the current snapshot, I'm having trouble getting the php validation to work. The following is always returns true, can anyone enlighten me? (BTW I have minimal php skills)

Code:
$post = JRequest::get('post');
$joins = $post['joins'];
$joinid = 5; // I'm presuming this is the record id in the fabrik_joins table?

$element1 = 'Booking_item__Arriving';
$element2 = 'Booking_item__Departing';

$elementData1 = $joins[$joinid][$element1];
$elementData2 = $joins[$joinid][$element2];

$errors = 0;
$i = 0;
for ($i = 0; $i < count($element1data); $i ++)
{
  $date1 = strtotime($elementData1[$i]);
  $date2 = strtotime($elementData2[$i]);
  
  if ($date1 >= $date2) {$errors = $errors ++;}
}
if ($errors > 0) {$result = "true";} else {$result = "false";}
return  $result;
 
Well, that code doesn't exactly apply to what you are trying to do. Rob just gave you something generic as an example.

Try this:

PHP:
$post = JRequest::get('post');
$joins = $post['joins'];
$joinid = 5; // I'm presuming this is the record id in the fabrik_joins table?

$element1 = 'Booking_item__Arriving';
$element2 = 'Booking_item__Departing';

// $repeatCounter comes from the PHP validation plugin itself, and tells us
// which repeat instance of the group we are currently validating
$elementData1 = $joins[$joinid][$element1][$repeatCounter];
$elementData2 = $joins[$joinid][$element2][$repeatCounter];

$date1 = strtotime($elementData1[$i]);
$date2 = strtotime($elementData2[$i]);
  
return $date1 >= $date2;

NOTE - if the element this validation is on, is one of Booking_item__Departing or Arriving, you already have the value you need in $data, so no need to yank it out of the post array.

And yes, $joinid is the numeric ID of the join, which is not entirely obvious. Best place to confirm this is usually the actual HTML source on your page. Examine one of your repeat elements, and it'll have an an HTML ID of something ike join___X___tablename___elementname. The X is the join ID.

-- hugh
 
Oh, note that you'll need to update to latest github, to pick up my change to the PHP validation rule plugin, for the code I gave you to work.

-- hugh
 
Thanks so much for your help on this Hugh.
Sorry to be a nuisance, but I haven't been able to get that code to work yet and I've updated to the latest github snapshot.

Confession: I've renamed the joined table to a more friendly name, and manually updated the database so that everything seems to work fine with inserting, editing and listing records. Do you think this could this be causing any problems? ie is there any hard coding dependent on the structure of the joined table name?

And a question on your code: You have included [$i] in the last couple of calculations... is that correct?
 
OK, I've got this sorted for anyone who has a similar issue. I had a couple of bugs in my code:

  • "$joins = $post['joins'];" should be "$joins = $post['join'];"
  • I didn't have enough underscores in Booking_item___Arriving and Booking_item___Departing
The working code in my case:


Code:
$post = JRequest::get('post');
$joins = $post['join'];
$joinid = 5;

$element1 = 'Booking_item___Arriving';
$element2 = 'Booking_item___Departing';

$elementData1 = $joins[$joinid][$element1][$repeatCounter];
$elementData2 = $joins[$joinid][$element2][$repeatCounter];

$date1 = strtotime($elementData1);
$date2 = strtotime($elementData2);
  
return $date2 >= $date1;
Thanks for your help Hugh and Rob... much appreciated.
 
Just FYI, you could make it a little shorter. For example, if your validation is on the Departing element, you'd do this:

PHP:
return strtotime($formModel->_formData['join'][5]['Booking_item___Arriving'][$repeatCounter]) >= strtotime($data);

:)

-- hugh
 
We are in need of some funding.
More details.

Thank you.

Members online

No members online now.
Back
Top