1

I have a question regarding passing data to a php session when an the element is clicked. the data that needs to be passed is looped in a foreach loop which is what i am having difficulty with.

I want the page to refresh in order to change the language on the entire page. I have ajax examples below which arent the logical solution to my problem(as pointed out by a few users)

<?php foreach($languages as $single_language){?>
    <li>
        <a class="d-flex align-items-center <?php if($_SESSION['languages_id'] ==     $single_language["id"]){ echo "disabled"; }?>" data-id="<?php echo $single_language["id"]?>" data-direct="<?php echo $single_language["directory"]?>" id="language_selection_<?php echo $single_language["id"]?>" href="#">
            <img src="<?php echo $single_language['short_name']. '.png' ?>" />
            <span class="ps-2"><?php echo $single_language["name"]; ?></span>
        </a>
    </li>
<?php } ?>

Data stored in languages that i need to pass is id and directory. E.g. $single_language["id"] = 4 and $single_language["directory"] = dutch. There are 3 'languages' that are selectable and when selected should display the according flag.

Ive tried using ajax:

$('[id^=language_selection_]').click(function(){
    var Lid = $(this).data('id');
    var direct = $(this).data('direct');

    $.ajax({
        type: 'post',
        success: function(response){
            <?php 
                $_SESSION['languages_id'] = $_POST['Lid'] ;
                $_SESSION['language'] = $_POST['direct'];
            ?>
        }
     });       

which did not store any data into my session. the second option of ajax i used was:

$('[id^=language_selection_]').click(function(){
    var Lid = $(this).data('id');
    var direct = $(this).data('direct');
    $.ajax({url: "ajax_sidebar.php?Lid="+Lid+"&direct="+direct, success: function(result){
        alert('test');
    }
});

and ajax_sidebar.php has

<?php 
session_start();
$_SESSION['languages_id'] = $_GET['Lid'];
$_SESSION['language'] = $_GET['direct'];
?>

which also did not seem to work, it did not change the session at all and never reached the alert.

when i put this within the foreach the code does work and the last value out of the 3 gets saved, not the one that gets clicked: $_SESSION['languages_id'] = $single_language["id"] ; $_SESSION['language'] = $single_language["directory"];

Ive seen a few other options online which all seemed to give me an error one way or another so im hoping that someone can help me out.

Amy
  • 33
  • 7
  • 2
    Remember that PHP runs on the server before the page is sent to the browser, javascript runs after the page is sent to the browser. That means that in the second bit of code, PHP has already run before the ajax is triggered, and if you look at the source in the browser, your success function is actually empty. – aynber May 04 '23 at 12:32
  • 1
    For your third/fourth bit, if you didn't get the alert, then you probably didn't get a success response. Open up your browser's developer console and watch both the console tab and the Network tab when you attempt the ajax request. Are there any messages in the console? Is the Network request actually attempted, and what is the status code? – aynber May 04 '23 at 12:33
  • @ADyson Thank you for your comment, Ive taken a look at the network tab and it does give the correct payload. It appeared that the url to my ajax file was incorrect. i now do get the alert but the session isnt updated with the new values. – Amy May 04 '23 at 12:50
  • 1
    `the session isnt updated with the new values`...how do you know? Where/when/how are you testing that? You don't seem to echo the new session values back in the PHP script which processes the AJAX rquest, and your JS code makes no attempt to read what was sent back, either. – ADyson May 04 '23 at 12:51
  • 1
    If clicking the landing page is reloading the page - then there is no point in using ajax. Furthermore - does it reload before or after the ajax call is done? if it's before then that's why it isn't updated – ABR May 04 '23 at 12:58
  • You can do that, or you can make each language button part of a form which submits the data as POST. Just the same as any time you want to send data to PHP from the browser really. It probably doesn't matter much either way if you use GET or POST, in this case. – ADyson May 04 '23 at 13:06

4 Answers4

1

First of all make it clear that you want to do it with a page refresh or without a page refresh, as Ajax is irrelevant in the case of page refresh.

Now Ajax way: The alert is not working because of an empty response as you haven't set any response in your PHP code to send to your Ajax code

You can do it in multiple ways but here is the POST method way:

a) post method with string response

$('[id^=language_selection_]').click(function(){     
    var Lid = $(this).data('id');
    var direct = $(this).data('direct');
    $.ajax({
        url: "ajax_sidebar.php",
        data:{"Lid": Lid, "direct": direct},
        success: function(result){
            console.log(result);        
        }   
    }); 
}); 

And then php code (ajax_sidebar.php):

<?php  
session_start(); 
$_SESSION['languages_id'] = $_POST['Lid']; 
$_SESSION['language'] = $_POST['direct']; 
echo "done"; 
exit; 
?>

b) post method with JSON response:

$('[id^=language_selection_]').click(function(){     
    var Lid = $(this).data('id');
    var direct = $(this).data('direct');
    $.ajax({
        url: "ajax_sidebar.php",
        dataType:'json',
        data:{"Lid": Lid, "direct": direct},
        success: function(result){
            alert($.parseJson(result.msg));         
        }   
    }); 
}); 

And then php code (ajax_sidebar.php):

<?php  
session_start(); 
$_SESSION['languages_id'] = $_POST['Lid']; 
$_SESSION['language'] = $_POST['direct']; 
echo json_encode(['status'=>1,'msg'=>'successfully updated']); 
exit; 
?>

Now with page refresh, Single page PHP code (no Ajax/jQuery code required):

<?php

session_start();
<?php foreach($languages as $single_language){?>
    <li>
        <a class="d-flex align-items-center <?php if($_SESSION['languages_id'] == $single_language["id"]){ echo "disabled"; }?>" id="language_selection_<?php echo $single_language["id"]?>" 
        href="<same page url>?Lid=<?php echo $single_language["id"]?>&direct="<?php echo $single_language["directory"]?>">
            <img src="<?php echo $single_language['short_name']. '.png' ?>" />
            <span class="ps-2"><?php echo $single_language["name"]; ?></span>
        </a>
    </li>
<?php } ?>

<?php
if(!empty($_GET['Lid']) && !empty($_GET['direct'])){
    $_SESSION['languages_id'] = $_GET['Lid'];
    $_SESSION['language'] = $_GET['direct'];
}

Note: on this single php code file make sure session_start(); will be on top of the file.

Alive to die - Anant
  • 70,531
  • 10
  • 51
  • 98
0

In this code:

<?php 
                $_SESSION['languages_id'] = $_POST['Lid'] ;
                $_SESSION['language'] = $_POST['direct'];
 ?>

you just setted once session keys by data taken from the post and then send all html with this code to client side. You do this on server side and that operations just creating empty js function because nothing will be returned by above or returned undefined.

You must write on js language something like this:

$.ajax({
        type: 'post',
        data: { lid: Lid, direct },
        url: '/save-something-on-server-side.php',
        dataType: 'json',
        success: function(response){
           console.log('success')
        }
     });     

And on php server route, e.g. file save-something-on-server-side.php you should save data to session:

$_SESSION['languages_id'] = $_POST['Lid'];
$_SESSION['language'] = $_POST['direct'];
0

On the page with the for loop add this in the top.

session_start();

if(isset($_GET['LID'])){
    $_SESSION['languages_id'] = $_GET['Lid'];
}
if(isset($_GET['direct'])){
    $_SESSION['language'] = $_GET['direct'];
}

Add make the changes in the forloop creating the hyperlinks

    <?php 
if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on'){
    $url = "https://";   
}else{
    $url = "http://";   
}  
    $url.= $_SERVER['HTTP_HOST'];   

    $url.= $_SERVER['REQUEST_URI'];    
    
    $content = '';
foreach($languages as $single_language){
    $content .= 
    '<li>
        <a 
            class="d-flex align-items-center '. ($_SESSION['languages_id'] == $single_language["id"] ?  "disabled" : '') .' " 
            data-id="'.$single_language["id"].'" 
            data-direct="'. $single_language["directory"].'" 
            id="language_selection_'.$single_language["id"].'" 
            href="'.$url . '?LID=' . $single_language["id"] . '&direct=' . $single_language["directory"].'"
        >
            <img src="' . $single_language['short_name'] . '.png" />
            <span class="ps-2">'. $single_language["name"].'</span>
        </a>
    </li>';

} 
echo $content;
?>

Then you can remove the event listerner from javascript entirely.

This code is untested so there might be minor typos.

Edited to use direct hyperlinks proposed by @ADyson

ABR
  • 134
  • 5
  • 1
    You _could_...but why not just use a hyperlink directly? The script seems unnecessary. – ADyson May 04 '23 at 13:23
  • That's a really good point, I think i got caught up in previous answers before it was clarified. Let me edit to reflex that. – ABR May 04 '23 at 13:24
-1

You cannot run PHP code in JavaScript, that's not how the relationship between JavaScript and PHP works. PHP generates html and JavaScript code, which will then be run on the client side. If you want your JavaScript to modify something in you PHP (the session in your case) you will have to do an http post request with that data, then do something with that data in PHP.

Do a POST request and send the Lid and direct values

$('[id^=language_selection_]').click(function (event) {
    event.preventDefault(); //prevent the page from reloading when clicking on the anchor tag
    var Lid = $(this).data('id');
    var direct = $(this).data('direct');

    $.ajax({
        type: 'post',
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        data: "Lid=" + Lid + "&direct=" + direct,
        success: function() {location.reload();} //reload the page after a successfull POST request
    });
});

in PHP, check if the request is a POST request, then check if Lid and direct are set in the $_POST superglobal, if they are then you can change the session values with the ones posted from the client.

<?php

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if(!isset($_POST['Lid']) || !isset($_POST['direct'])) {
       die("Missing Lid and/or direct");
    }
    
    session_start();
    $_SESSION['languages_id'] = $_POST['Lid'];
    $_SESSION['language'] = $_POST['direct'];
}
  • `location.reload();` ... this would really defeat the point of using AJAX. Either OP should not bother with AJAX, or they should have some JS code which updates the page directly following a successful response to the AJAX request. – ADyson May 04 '23 at 12:52
  • you can replace location.reload() with whatever you want obviously – Brad Script May 04 '23 at 19:16
  • Yes...but then your code wouldn't update the language on the page, because it does nothing except the session values, so there would be no visible result until the user manually refreshes. Then the OP is back where they started. So no, you can't replace location.reload() without doing something else actively to update the page. If that's your suggestion then you could edit the answer to show what you mean. – ADyson May 04 '23 at 19:19