Asked  7 Months ago    Answers:  5   Viewed   40 times

From time to time I have to pass some variables from PHP to JS script. For now I did it like this:

var js-variable = "<?php echo $php-variable; ?>";

But this is very ugly and I can't hide my JS script in .js file because it has to be parsed by PHP. What is the best solution to handle this?

 Answers

44

If you don't want to use PHP to generate your javascript (and don't mind the extra call to your webserver), use AJAX to fetch the data.

If you do want to use PHP, always encode with json_encode before outputting.

<script>
    var myvar = <?php echo json_encode($myVarValue); ?>;
</script>
Wednesday, March 31, 2021
 
Shobit
answered 7 Months ago
69

just use php to print some dynamic javascript

<script>
var myVar = "<?php echo json_encode($_COOKIE['somevalue']);?>";
</script>
Wednesday, March 31, 2021
 
shivam
answered 7 Months ago
30

I've never heard of a standard way to "pass" information between PHP and Javascript, as they are a server-side and client-side language, respectively. I would personally use a hybrid of your second and third solutions.

Store the post id in a data-postindex attribute (data attributes are newish, and the "right" way to store small amounts of data). But I would still just use a JSON array for the rest, as storing lots of data in data-attributes (and escaping them!) is potentially problematic. PHP has a json_encode function that takes care of all the escaping and such for you - just build a PHP array (say, $postdata) like you normally would, and then throw this in your post template:

<script type="text/javascript">
    globalPostArray.push(<?php echo json_encode($postdata) ?>);
</script>

Where $postdata is something like the following:

$postdata = array(
    'nid' => 5,
    'authorId' => 45
    ...etc...
);

It should be easy enough to generate such an array from your existing code.

I wrote a blog post a while back about my implementation of this kind of thing, but it sounds like all you need is a pointer at json_encode.

Wednesday, March 31, 2021
 
fardjad
answered 7 Months ago
12

Look at the generated HTML, for each select element a hidden field is generated that ensures that the appropriate key will be present in the data.

Multiple fields with the same name will cause multiple hidden fields to be generated where the last one will overwrite the former ones.

This can be avoided using the hiddenField option for the additional fields, so that the hidden initializer field is only generated for the first input. Quote from the docs:

If you want to create multiple blocks of inputs on a form that are all grouped together, you should use this parameter on all inputs except the first. If the hidden input is on the page in multiple places, only the last group of input’s values will be saved.

Also you should define a unique ID for both inputs, otherwise you'll end up with invalid HTML as the helper will produce duplicate IDs.

And last but not least your parentheses are probably a little wrong, the selected key is nested in the div key, which I guess is wrong in case this is ment to define the selected entries.

echo $this->Form->input('location', array(
    'id'       => 'location1',
    'type'     => 'select',
    'multiple' => 'checkbox',
    'options'  => $location_options1,
    'div'      => array('class' => 'col-xs-12 col-sm-6 form-group', 'style'= > 'margin-bottom:0;')
    'selected' => $user_location_alert_tag_ids
))); 
echo $this->Form->input('location', array(
    'id'          => 'location2',
    'type'        => 'select',
    'multiple'    => 'checkbox',
    'options'     => $location_options2,
    'div'         => array('class' => 'col-xs-12 col-sm-6 form-group'),
    'selected'    => $user_location_alert_tag_ids
    'hiddenField' => false
)));
Saturday, May 29, 2021
 
QuantumMechanic
answered 5 Months ago
37

Ok, here is what I think is happening:

Your not using the super useful HABTM relation magic. Instead of treating this table as a mere relation table, cake goes to the defined model an sees the relations you have defined and primaryKeys and displayFields, etc.

That's ok when you have a complicated HABTM table. But if that's the case, your data array is all messed up, because your not adding a Question and Qset separately. What I mean is, your not doing

$data = array('Question'=>array('title'=>'new_question'),
              'Qset'=>array('name'=>'lets say qset'));
$this->Question->saveAll($data);

Doing that, you let cake resolve the HABTM association for you, and that data structure would be ok. But you have your own QsetsQuestion model in you model folder. So the data you save should be like with any other table, like so

$data = array('qset_id'=> $qset_id,
              'question_id'=> $question_id);
$this->Question->QsetsQuestion->save($data);

And that creates a new id in qsets_questions table, with the new relation, just like you want.

Be careful, though, since your using your own model for this, if you don't set you validations correctly, you might have the same pair of foreign keys a lot of times, because by default cake just check that the id must be unique.

[EDIT] After a bit of clarification, the solution above does solve the "problem", but isn't actually the reason for this behavior.

Cakephp has a feature

By default when saving a HasAndBelongsToMany relationship, Cake will delete all rows on the join table before saving new ones. For example if you have a Club that has 10 Children associated. You then update the Club with 2 children. The Club will only have 2 Children, not 12.

So when you want to add a new row, cake deletes all previous associations and add the new ones. A way to solve this is to find all the Qsets that belong to a question and add them to the $data array (with the addition of the new question association you want to add). This link helped me to understand HABTM associations (look for "Challenge IV").

I know the solution I gave before helped you with the "problem", but it was made under the impression you had a QsetsQuestion model file somewhere. Since you don't, the solution would be to get all Questions associated and add them as a new array. Or actually create a QsetsQuestion model, and make the associations like this:

Qset hasMany QsetsQuestion
QsetsQuestion belongsTo Qset, Question
Question hasMany Qsets.

Or change the behavior of cake... None of them seems pretty, I know.

So, summary for solutions:

  • Every time you want to save a new Qset-Question association, retrieve the previously stored associations, put it in the array to be saved, and save them

    //find previously associated Qsets, lets say it's 1,2,3 and 4
    $data = array('Question'=>array('id'=>1),
              'Qsets'=>array('Qsets'=>array(1,2,3,4, $new_qset));
    $this->Question-save($data);
    

Note there's no QsetsQuestion, since it doesn't exists. This should be the first option since the HABTM model is not complex

OR

  • Create QsetsQuestion in your model folder and change the associations as indicated above. The save part on the controller would be

    $data = array('qset_id'=>1, 'question_id'=>1)
    $this->Question->QsetsQuestion->save($data);    //also works with $this->Qset->QsetsQuestion
    

It is much more simple (maybe), but you have to create a new file, and remember to check that there's no previous similar association (check if 2-2 tuple exists before inserting it). Simple validation rules should work.

OR

  • Change cakephp behavior for this... I don't like this one.
Saturday, May 29, 2021
 
uiroshan
answered 5 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :