PHP Laravel, error screen shows sensitive information

I have a PHP application using Laravel, whenever there is an error, the system will open a screen containing the error details with db connection details, the database name even the password. How can I prevent the application from showing this sensitive information.
Thank you

Showing records/data from another database table based on the id in laravel

Hello Please I am trying to view the records of a user based on the user id I used as a foreign key in another table in laravel. Basically I want the name of the userID to show.

This is my Controller

    public function index()
    {
       
        
        $id = User::all();
        $organisedTrips = organisedTrip::where('userID', '=', $id)->get();
    
        $organisedTrips = organisedTrip::paginate(4);
        return view('welcome', compact('organisedTrips'));
        
    }

The user table

The table where I made the userID a foreign key from the user's table

How to make curl to the same server lightning fast?

I’m trying to create a proxy site AAA.com and relay the traffic to BBB.com in the backend via PHP cURL, and again relay the response from BBB.com to AAA.com visitors. Both sites are on the same server. Below is the code:

$proxied_site = 'https://BBB.com';

$proxied_site_parsed = parse_url($proxied_site);

$ch = curl_init();

$proxied_url = $proxied_site . $_SERVER['REQUEST_URI'];

curl_setopt($ch, CURLOPT_URL, $proxied_url);

curl_setopt($ch, CURLOPT_RESOLVE, array(
    "{$proxied_site_parsed['host']}:443:170.249.199.178",
));

curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $_SERVER['REQUEST_METHOD']);
$requestHeaders = [];
foreach (getallheaders() as $name => $value) {
    if ($name == 'Host') {
        $value = $proxied_site_parsed['host'];
    }
    $requestHeaders[] = "$name: $value";
}

curl_setopt($ch, CURLOPT_HTTPHEADER, $requestHeaders);

if (in_array($_SERVER['REQUEST_METHOD'], ['POST', 'PUT', 'DELETE'])) {
    curl_setopt($ch, CURLOPT_POSTFIELDS, file_get_contents('php://input'));
}

curl_setopt($ch, CURLOPT_ENCODING, '');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);

$response = curl_exec($ch);

$response_header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$responseHeaders = substr($response, 0, $response_header_size);
$responseBody = substr($response, $response_header_size);

foreach (explode("rn", $responseHeaders) as $header_line) {
    
    if (stripos($header_line, 'HTTP/') === 0 || stripos($header_line, 'Set-Cookie:') === 0) {
        header($header_line, false);
    } else {
        header($header_line);
    }
}

curl_close($ch);

echo $responseBody;

After some benchmarking, cURL still needs about 0.006 seconds of network time to get to the site BBB.com on the same server.

My question is, is it possible to make it faster? Can I make it lightning-fast and as fast as 0.00006 since they are both on the same server?

I tried using IP:

$ch = curl_init('XXX.XXX.XXX.XXX');

And CURLOPT_RESOLVE:

curl_setopt($ch, CURLOPT_RESOLVE, array(
    "{$proxied_site_parsed['host']}:443:XXX.XXX.XXX.XXX",
));

But neither worked and the network around time was still about 0.006s.

Is this possible with cURL at all? Or at least make it 0.0006s?

If not, why?

OpenSwoole: use UDP server to push messages into a channel

I’m trying to get started with OpenSwoole and I’m using the built-in UDP server. I’d like to push any received messages into a channel so that another coroutine can process them. I’ve Googled extensively and can’t find an obvious way of doing it.

This is the code that I currently have:

// Create a channel with space for 1000 messages
$chan = new OpenSwooleCoroutineChannel(1000);

co::run(function () use ($chan){

    // Listener
    go(function() use ($chan) {
        // Read from channel
        while (1) {
            $data_read = $chan->pop();
            echo ("Data read: $data_readn");
        }
    });
});

// UDP server

// Set coroutine options before the server is started
OpenSwooleCoroutine::set([
        'enable_coroutine' => true
]);

// Start a new UDP server on 12.0.0.1, listening on port 9502
$server = new OpenSwooleServer('127.0.0.1', 9502, OpenSwooleServer::POOL_MODE, OpenSwooleConstant::SOCK_UDP);

// Setup the incoming data event callback, called 'Packet'
$server->on('Packet', function ($server, $data, $clientInfo) use ($chan)
{
    echo ("Data written: $datan");
    $chan->push($data);
});

// Start the server and begin accepting incoming requests
$server->start();

But when I run it I get the error:

===================================================================
 [FATAL ERROR]: all coroutines (count: 1) are asleep - deadlock!
===================================================================

How do I wrap the UDP server up into a coroutine ? I thought that it already ran as one or have I missed something obvious ?

Adding initialize to body tag if I am using a specific ACF block

I am making a ACF block that includes a google map and I need to add:

onload="initialize()"

to the body tag.
Can I use PHP to add that code conditionally if a unique ACF block is being used on the page?

I tried this:

function check_if_block_exist($block_handle) {
  $post = get_post(); 

  if(has_blocks($post->post_content)) {
    $blocks = parse_blocks($post->post_content);

    foreach( $blocks as $block ) {
      if($block['blockName'] === $block_handle) {
        return true;
      }
    }
    return false;
  }
}

But it didn’t work.

PHP message: Notice: Undefined variable: DATABASE_USER_HOST

I’m getting this error even though I haven’t actually declared DATABASE_USER_HOST:

Notice: Undefined variable: DATABASE_USER_HOST in /home/jm4bwakj91is/public_html/student_dashboard.php on line 16

I double-checked the whole code, and I didn’t use DATABASE_USER_HOST. I also tried using error_reporting(E_ALL & ~E_NOTICE);.

Laravel Search by swapping origin and destination forms

I have a project to check shipping rates using Laravel 11, I already have a table with prices that have been determined from origin to destination.

enter image description here

I use a search form with these 2 fields, but how can I swap the search, for example origin 1 to destination 2 or origin 1 to destination 2, and the results are still in the same column. And if the origin and destination are different then the results should not be displayed or will be null. For example, origin 3 to destination 2.

I use the get method but the search results do not match what is in the database table.
enter image description here
Why does a search with input that does not match the data table still appear with a different origin and destination? The result should be null because it is not in the column?

I have tried the following code but it doesn’t work as I expected. And This is some of the code I used

From Search

<form action="{{ url('rates') }}" method="GET">
      @csrf
      <div class="form-row align-items-center row">
          <div class="col-md-5">
              <label>Origin</label>
              <select class="form-control single-select-field" name="origin">
                 <option selected>Origin...</option>
                   @foreach ($cities as $city)
                   <option value="{{ $city->id }}">{{ $city->id}}</option>
                   @endforeach
              </select>
            </div>
          <div class="col-md-5">
            <label>Destination</label>
            <select class="form-control single-select-field" name="destination">
               <option selected>Destination...</option>
                  @foreach ($cities as $city)
                    <option value="{{ $city->id }}">{{ $city->id }}</option>
                  @endforeach
            </select>
          </div>
          <div class="col-md-6 my-3">
             <button type="submit" class="btn btn-warning btn-block">Check Rates</button>
          </div>
         </div>
 </form>

Rates Controller

$origin = $request['origin'];
$destination = $request['destination'];
$result = RouteModel::where(['origin' => $origin, 'destination' => $destination])->orWhere(['destination' => $origin, 'origin' => $destination])->first();
return $result;

Thank you for the help

Encrypt Query Parameter in Flutter and decrypt in PHP to get Data

The IV and the key are up here.


 // Verschlüsselt den Job-Parameter
  String encryptJob(String job) {
    final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
    final encrypted = encrypter.encrypt(job, iv: iv);
    return encrypted.base64; // Base64-String des verschlüsselten Textes
  }

  String encryptMessage (String message){
    final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc));
    final encrypted = encrypter.encrypt(message, iv:iv);
    return encrypted.base64;
  }

Future<void> fetchData() async {
    final message = '&function=';

    // Verschlüsselung des Job-Parameters
    final encryptedJob1 = encryptJob('job=$job1');
    final encryptedJob2 = encryptJob('job=$job2');
    final encryptedJob3 = encryptJob('job=$job3');
    final encryptedJob4 = encryptJob('job=$job4');


    //IV und verschlüsselte Daten für die URL korrekt kodieren
    final encodedIV = Uri.encodeComponent(iv.base64);
    final encodedJob1 = Uri.encodeComponent(encryptedJob1);
    final encodedJob2 = Uri.encodeComponent(encryptedJob2);
    final encodedJob3 = Uri.encodeComponent(encryptedJob3);
    final encodedJob4 = Uri.encodeComponent(encryptedJob4);
    final encryptedMessage = encryptMessage('$message$encodedJob4');

    // Jetzt den IV korrekt in Base64 umwandeln und in die URL einfügen
    final webServiceURl = 'http://localhost/get_encrypt_request.php?iv=$encodedIV$message$encodedJob4';
    final url = Uri.parse(webServiceURl);
    final response = await http.get(url);

    print('$urln');
    print(response.body);

    setState(() {
      data = response.body;
    });

    if (response.statusCode == 200) {
      print('Erfolgreiche Antwort');
    } else {
      print('Fehler beim Abrufen der Daten: ${response.statusCode}');
    }
  }

My Task is to encrypt the queryParamters that no plaintext can be seen affter the ?.
I can encrypt my job but not my queryparameter in that case the message per se.
And after that the queryparameter must than be decrypt in php and send me the data from the job.

// Empfange den IV und die verschlüsselten Daten
$iv = isset($_GET['iv']) ? $_GET['iv'] : '';
$data = isset($_GET['function']) ? $_GET['function'] : '';
  final encryptedMessage = encryptMessage('$message$encodedJob4');

In this line you can see that i have tried to put the message with the job but than for the job it is a “double encryption” and that is indeed not that sence.

    final webServiceURl = 'http://localhost/get_encrypt_request.php?iv=$encodedIV$encryptedMessage';

When i change the queryparameters to this for sure it doesn’t work.

Getting correct run order in a while($x = $y->fetch_assoc()){} loop

Just started playing around with php and mysql, loading small images from a database and stumbled across this little problem. Can anyone help me get the right display order and explain why what I’m doing doesnt work? What I want is this:

Database contains x items.
<img 1>
Text under image.
<img 2>
Text under image.

But with this code:

if ($result->num_rows > 0) {
echo "Database contains ".$result->num_rows." items.";
// output data of each row
while($row = $result->fetch_assoc()) {

  $src = "data: ".$row['jpgornot'].";base64,".$row['pic'];

  echo "<img src = '" . $src . "'><br><br>";
  echo "Text under image.";
}

}

I get:

<img 1>
Database contains x items.
<img 2>
Text under image.
Text under image.

How to display a new table (2) after click on row table (1) for view details

I have a table with a list of players, by clicking on the players row I would like to display a table below with the player’s details. I can do it but when I click the table with the players… display twice player’s table and below the table with the details. Where is the error? Thanks

          <?php
          require_once('./php/config.php');

          $q_classifica = "SELECT * FROM giocatori ORDER BY punti DESC";
          if($r_classifica = $conn->query($q_classifica))
          {
              $indice=1;

              echo '<div class="box-class1 roboto-bold">
              <table style="width: 380px; height: 60px;" border="0" cellpadding="2" cellspacing="2" class="scrolldown prova">
              <thead><tr>
              <th style="width: 60px"></th>
              <th style="width: 205px"></th>
              <th style="width: 86px"></th>
              <th style="width: 29px"></th>
              </tr></thead><tbody>';
              
              while ($row1 = $r_classifica->fetch_array())
              {
                  echo '
                  <tr class="mia" id="' . $row1['ID'] . '">
                  <td style="width: 60px"><a href="https://wa.me/' . $row1['cell'] . '?text=Ciao...%20vorrei sfidarti!!!%20al%20torneo"><img style="width: 17px; height: 19px;" alt="ball" src="ball.png"></a>   ' . $indice . '</td>
                  <td style="width: 205px">' . $row1['nome'] . '</td>
                  <td style="width: 86px">' . $row1['punti'] . '</td>';
            
                      $infortunio = $row1['infortunio'];
                      if($infortunio==si){echo '<td style="width: 29px"><img style="width: 30px; height: 22px;" alt="infortunato" src="ambulanza.png"></td></tr>';}
                      else{
                      echo '<td></td></tr>';
                          }
                      $indice++;
              }
              echo "</tbody></table></div>";

          }else{
              echo "Errore impossibile eseguire la query $q_classifica. " . $conn->error;
              }
          ?>

          <script>
          $(document).ready(function(){
              $('.mia').click(function(){
                      id_player = $(this).attr('id')
                      $.ajax({url: "home.php",
                      method:'post',
                      data:{player_id:id_player},
                    success: function(result){
                      $(".modbody").html(result);
          }});
                // $('#myModal').modal("show");

              })
          })
          </script>

          <div class="modbody">
          <?php

          if(isset($_POST["player_id"]))
          {

          $output = '';


          $a_giocatore = "SELECT nome FROM giocatori WHERE giocatori.id = '".$_POST["player_id"]."'";
          $result = $conn->query($a_giocatore);
          while ($row = mysqli_fetch_assoc($result))
              {
                  $giocatore= $row['nome'];
              } 

          $output .= '
          <H2><div style="text-align: center;" class="roboto-black-italic box-giocatore1">' . $giocatore . '</H2></div>';


          $q_partita = "SELECT * FROM partite WHERE (giocatore_1 = '$giocatore' OR giocatore_2 = '$giocatore') AND (vittoria = '$giocatore') AND (punteggio IS NOT NULL) ORDER BY data DESC";
          if($r_partita = $conn->query($q_partita))
              {
                  $output .= '
                  <table style="text-align: center;" border="0" cellpadding="2" cellspacing="1" class="vinte">
                      <thead>
                          <tr>
                              <th style="vertical-align: top; width: 105px;"><br></th>
                              <th style="vertical-align: top; width: 105px;"><img alt="up" src="vi.png"><br></th>
                              <th style="vertical-align: top; width: 70px;"><br></th>
                              <th style="vertical-align: top; width: 70px;"><br></th>
                          </tr>
                      </thead>';
              
                  while ($row1 = $r_partita->fetch_array())
                  {
                      $data = $row1['data'];
                      $timestamp_data = strtotime($data); // converte data in formato leggibile a video, cercare modo di mettere nomi in ITA
                      $formato = 'j M Y'; 
                      $resultd = date($formato, $timestamp_data); // converte data in formato leggibile a video, cercare modo di mettere nomi in ITA
                      $output .= '
                      <tbody>
                          <tr>
                              <td class="roboto-regular-italic"><font size="1">' . $row1['giocatore_1'] . '</font></td>
                              <td class="roboto-regular-italic"><font size="1">' . $row1['giocatore_2'] . '</font></td>
                              <td class="roboto-regular-italic"><font size="1">' . $row1['punteggio'] . '</font></td>
                              <td class="roboto-regular-italic"><font size="1">' . $resultd . '</font></td>
                          </tr>';
                  }
                  $output .= '
                      </tbody>
                  </table>';
              }


          $q_partita2 = "SELECT * FROM partite WHERE (giocatore_1 = '$giocatore' OR giocatore_2 = '$giocatore') AND (sconfitta = '$giocatore') AND (punteggio IS NOT NULL) ORDER BY data DESC";
          if($r_partita2 = $conn->query($q_partita2))
              {
                  $output .= '
                  <table style="text-align: center;" border="0" cellpadding="2" cellspacing="1" class="perse">
                      <thead>
                          <tr>
                              <th style="vertical-align: top; width: 105px;"><br></th>
                              <th style="vertical-align: top; width: 105px;"><img alt="up" src="sc.png"><br></th>
                              <th style="vertical-align: top; width: 70px;"><br></th>
                              <th style="vertical-align: top; width: 70px;"><br></th>
                          </tr>
                      </thead>';
                      
                  while ($row1 = $r_partita2->fetch_array())
                  {
                      $data2 = $row1['data'];
                      $timestamp_data2 = strtotime($data2); // converte data in formato leggibile a video, cercare modo di mettere nomi in ITA
                      $formato2 = 'j M Y'; 
                      $result2 = date($formato2, $timestamp_data2); // converte data in formato leggibile a video, cercare modo di mettere nomi in ITA
                      $output .= '
                      <tbody>
                          <tr>
                              <td class="roboto-regular-italic"><font size="1">' . $row1['giocatore_1'] . '</font></td>
                              <td class="roboto-regular-italic"><font size="1">' . $row1['giocatore_2'] . '</font></td>
                              <td class="roboto-regular-italic"><font size="1">' . $row1['punteggio'] . '</font></td>
                              <td class="roboto-regular-italic"><font size="1">' . $result2 . '</font></td>
                          </tr> ';
                  }
                  $output .= '
                      </tbody>
                  </table>';
              }

          echo $output;
          unset ($giocatore);

          }
          ?>
          </div>

I tried to send the url via post in the same page but the first table appears twice. I would like to do this process without reloading the page, thanks

BEFORE CLICK

AFTER CLICK

Dynamic pagination using JavaScript Datatable is not working? [closed]

Upon reinitializing warning is shown and existing pagination is missing, current pagination show the default 50 records only.

I have alternatively implemented another pagination which is working,but I require the in built javascript pagination.

Below is my HTML code-

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Data</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <script src="https://code.jquery.com/jquery-3.7.1.js"></script>
    

<!-- Styles -->
<link href="assets/css/style.css" rel="stylesheet">
<style>
    #pagination a {
        padding: 5px;
        text-decoration: none;
        color: #007bff;
    }
    #pagination .current {
        padding: 5px;
        font-weight: bold;
        color: #000;
    }
    #loading-message {
        text-align: center;
        display: none;
    }
</style>
 <title> Dashboard</title>
<div class="content-wrap">
    <div class="container mt-5">
        <h5>Journal Subscriptions and Revenue</h5>
        <table id="bootstrap-data-table-export" class="table table-striped table-bordered">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Cust_No_</th>
                    <th>Journal_ID</th>
                    <th>Content_Year</th>
                    <th>Subject</th>
                    <th>Journal_Title</th>                
                    <th>Type_of_Subscription</th>
                </tr>
            </thead>
            <tbody id="table-body">
                <!-- Data will be loaded here -->
                <?php  foreach ($results as $row): ?>
        <tr>
            <td><?= htmlspecialchars($row['Name']); ?></td>
            <td><?= htmlspecialchars($row['Cust_No_']); ?></td>
            <td><?= htmlspecialchars($row['Journal_ID']); ?></td>
            <td><?= htmlspecialchars($row['Content_Year']); ?></td>
            <td><?= htmlspecialchars($row['Subject']); ?></td>
            <td><?= htmlspecialchars($row['Journal_Title']); ?></td> 
            <td><?= htmlspecialchars($row['Type_of_Subscription']); ?></td>
                                                                
        </tr>
        <?php endforeach; ?>
            </tbody>
        </table>

        <!-- Pagination Links -->
        <div id="pagination">
            <!-- Pagination links will be loaded here -->     
            <?php if ($page > 1): ?>
                <a href="?page=<?= $page - 1; ?>">Previous</a>
            <?php endif; ?>

            <span>Page <?= $page; ?> of <?= $totalPages; ?></span>

            <?php if ($page < $totalPages): ?>
                <a href="?page=<?= $page + 1; ?>">Next</a>
            <?php endif; ?>                  
        </div>
    </div>
    <div id="loading-message">
        <p>Loading more data...</p>
    </div>
</div>
<script>
    let currentPage = 1;
    let totalPages = 1;
    let loading = false;

    function loadData(page) {
        $.ajax({
            url: 'journal_data_19.php',
            type: 'GET',
            data: { page: page },
            dataType: 'json',
            success: function(data) {
                if (data.error) {
                    alert('Error: ' + data.error);
                    return;
                }
                totalPages = data.totalPages;
                currentPage = data.currentPage;

                const tableBody = $('#table-body');
                tableBody.empty(); // Clear existing data

                data.results.forEach(row => {
                    tableBody.append(
                        `<tr>
                            <td>${row.Name}</td>
                            <td>${row.Cust_No_}</td>
                            <td>${row.Journal_ID}</td>
                            <td>${row.Content_Year}</td>
                            <td>${row.Subject}</td>
                            <td>${row.Journal_Title}</td>
                            <td>${row.Type_of_Subscription}</td>
                        </tr>`
                    );
                });

                updatePagination();
            },
            error: function(xhr, status, error) {
                console.error('AJAX Error:', status, error);
            }
        });
    }

    function updatePagination() {
        const paginationElement = document.getElementById('pagination');
        if (paginationElement) {
            let paginationHtml = '';

            // Previous button
            if (currentPage > 1) {
                paginationHtml += `<a href="#" onclick="loadData(${currentPage - 1}); return false;">Previous</a> `;
            }

            // Page numbers
            for (let i = 1; i <= totalPages; i++) {
                if (i === currentPage) {
                    paginationHtml += `<span class="current">${i}</span> `;
                } else {
                    paginationHtml += `<a href="#" onclick="loadData(${i}); return false;">${i}</a> `;
                }
            }

            // Next button
            if (currentPage < totalPages) {
                paginationHtml += `<a href="#" onclick="loadData(${currentPage + 1}); return false;">Next</a>`;
            }

            paginationElement.innerHTML = paginationHtml;
        } else {
            console.error('Pagination element not found');
        }
    }

    function loadMoreData(page) {
        if (loading) return; // Prevent multiple requests at the same time
        loading = true;
        $('#loading-message').show();

        $.ajax({
            url: 'journal_data_19.php',
            type: 'GET',
            data: { page: page },
            dataType: 'json',
            success: function(data) {
                if (data.error) {
                    alert('Error: ' + data.error);
                    return;
                }
                totalPages = data.totalPages;
                currentPage = data.currentPage;

                const tableBody = $('#table-body');

                // Append the fetched rows to the table
                data.results.forEach(row => {
                    tableBody.append(
                        `<tr>
                            <td>${row.Name}</td>
                            <td>${row.Cust_No_}</td>
                            <td>${row.Journal_ID}</td>
                            <td>${row.Content_Year}</td>
                            <td>${row.Subject}</td>
                            <td>${row.Journal_Title}</td>
                            <td>${row.Type_of_Subscription}</td>
                        </tr>`
                    );
                });

                loading = false;
                $('#loading-message').hide();
            },
            error: function(xhr, status, error) {
                console.error('AJAX Error:', status, error);
                loading = false;
                $('#loading-message').hide();
            }
        });
    }

    $(document).ready(function() {
        loadData(currentPage); // Initial load

        // Event listener for scrolling
        $(window).scroll(function() {
            if ($(window).scrollTop() + $(window).height() >= $(document).height() - 100 && !loading && currentPage < totalPages) {
                loadMoreData(++currentPage);
            }
        });
    });




    //JAVASCRIPT PAGINATION SECTION---------------------$(document).ready(function() {
    $('#bootstrap-data-table-export').DataTable({
        "processing": true,
        "serverSide": true,
        "ajax": {
            "url": "journal_data_19.php",
            "type": "GET",
            "dataSrc": function (json) {
                // Check if json.data exists and contains data
                if (json.data && json.data.length > 0) {
                    return json.data;
                } else {
                    console.error('No data found or incorrect format');
                    return [];
                }
            },
            "error": function (xhr, error, thrown) {
                console.error('An error occurred while fetching data:', error);
            }
        },
        "pageLength": 50,
        "lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "All"]],
        "columns": [
            { "data": "Name" },
            { "data": "Cust_No_" },
            { "data": "Journal_ID" },
            { "data": "Content_Year" },
            { "data": "Type_of_Subscription" },
            { "data": "Journal_Title" },
            { "data": "Subject" }
        ],
        "paging": true,
        "searching": true,
        "ordering": true,
        "dom": 'Bfrtip',
        "buttons": ['copy', 'csv', 'excel', 'pdf', 'print'],
        "scrollY": "500px",
        "scrollCollapse": true,
        "responsive": true
    });
});

    </script>
<script src="assets/js/lib/jquery.nanoscroller.min.js"></script>
<!-- nano scroller -->
<script src="assets/js/lib/menubar/sidebar.js"></script>
<script src="assets/js/lib/preloader/pace.min.js"></script>
<!-- sidebar -->

<!-- bootstrap -->

<script src="assets/js/scripts.js"></script>
<!-- scripit init-->
<script src="assets/js/lib/data-table/datatables.min.js"></script>
<!-- <script src="assets/js/lib/data-table/buttons.dataTables.min.js"></script> -->
<script src="assets/js/lib/data-table/dataTables.buttons.min.js"></script>
<script src="assets/js/lib/data-table/buttons.flash.min.js"></script>
<script src="assets/js/lib/data-table/jszip.min.js"></script>
<script src="assets/js/lib/data-table/pdfmake.min.js"></script>
<script src="assets/js/lib/data-table/vfs_fonts.js"></script>
<script src="assets/js/lib/data-table/buttons.html5.min.js"></script>
<script src="assets/js/lib/data-table/buttons.print.min.js"></script>
<script src="assets/js/lib/data-table/datatables-init.js"></script>

This is my PHP code-

<?php
session_start();
ob_start(); // Start output buffering

if (!isset($_SESSION['loggedin'])) {
    header('Location: index.html');
    exit;
}

ini_set('max_execution_time', 0); // No time limit

$DATABASE_HOST = 'localhost';
$DATABASE_USER = 'root';
$DATABASE_PASS = '';
$DATABASE_NAME = 'destination_db';

// Number of records to display per page
$limit = 50;

// Get the current page number from the AJAX request
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
if ($page < 1) $page = 1; // Ensure page number is at least 1

// Calculate the offset for the SQL query
$offset = ($page - 1) * $limit;

// Parameters from DataTables
$start = $_GET['start'];
$length = $_GET['length'];
$searchValue = $_GET['search']['value']; // For search filtering

try {
    $pdo = new PDO("mysql:host=$DATABASE_HOST;dbname=$DATABASE_NAME;charset=utf8", $DATABASE_USER, $DATABASE_PASS);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Get the total number of records
    $totalStmt = $pdo->query('SELECT COUNT(*) FROM journal_subscription js 
                              JOIN journal_revenue jr 
                              ON js.Cust_No_ = jr.Ship_to_no_ 
                              AND js.Type_of_Subscription = jr.Type_of_Sales 
                              AND js.Content_Year = jr.Content_Year 
                              AND js.Journal_ID = jr.Journal_ID');
    $totalRows = $totalStmt->fetchColumn();
    $totalPages = ceil($totalRows / $limit);

    // Prepare the SQL query with LIMIT and OFFSET
    $stmt = $pdo->prepare('SELECT js.Cust_No_, js.Name, js.Journal_ID, js.Content_Year, js.Type_of_Subscription, jr.Subject, jr.Journal_Title
FROM journal_subscription js
JOIN journal_revenue jr
ON js.Cust_No_ = jr.Ship_to_no_
AND js.Type_of_Subscription = jr.Type_of_Sales
AND js.Content_Year = jr.Content_Year
AND js.Journal_ID = jr.Journal_ID
LIMIT :limit OFFSET :offset');
    
    // Bind parameters
    $stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
    $stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
    
    // Execute query
    $stmt->execute();
    
    // Fetch results
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);

    // Return JSON response
    echo json_encode([
        'results' => $results,
        'totalPages' => $totalPages,
        'currentPage' => $page
    ], JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
   
} catch (PDOException $e) {
    header('Content-Type: application/json');
    echo json_encode(['error' => $e->getMessage()]);
}
ob_end_clean(); // End output buffering and clean output
?>

Output

Can’t get current session’s database row on Laravel

I am trying to store the user’s geolocation information in an extra column on sessions table.
I use Fortify for authentication.
I created an extra column on sessions table for that.
migration:

public function up(): void
    {
        Schema::table('sessions', function (Blueprint $table) {
            $table->json('geolocation')->after('user_agent')->nullable();
        });
    }

Then I created a Session model which accesses the session table:

<?php
namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;

class Session extends Model
{
    use HasFactory;

    protected $casts = [
        'id' => 'string',
        'user_agent' => 'collection',
        'geolocation' => 'collection'
    ];

    protected $fillable = [
      'geolocation',
      'created_at'
    ];
}

I created a listener for successfull login event. In the handle method, I try to get the session id to match the session with the row on the database. However session()->id() or session()->getId() return a different value which does not exist in the sessions table.

The question is;
What should I do in order to be able to update the active session’s database column?
What alternative approach might be tried?

I try to match the user’s active session with the row on the sessions table and update a column of it.

Adding a new column on ‘customers’ tab on Restrict Content Pro – Agree terms

I am using Restrict Content Pro and I am trying to introduce a new column to my customers table on the WordPress dashboard.

I want the column to be named something like ‘Agreed Terms’ and for each customer it should output the result of whether that customer agreed to terms which I think is currently either ‘none’ or the date in which the user signed up.

The agree to terms is in reference to whether the user accepts email communication and it isn’t required to tick.

Does anybody know how to do this? Thanks.

I have managed to get to the point of actually adding the column, however, I have been unable to pull any of the content through. I have looked online at the documentation but wasn’t able to find any kind of function or hook that allows me to get the result of the terms agreed.

This is the code I have come up with so far

function ag_rcp_customers_list_table_columns( $columns ) 
{
  $key = 'terms'; // All lowercase, no spaces. Your unique ID for your column.
  $name = __( 'Agree Terms', 'rcp' ); // Label to be displayed on the column header. Spaces are okay.
  $columns[ $key ] = $name;

  return $columns;
}

add_filter( 'rcp_customers_list_table_columns', 'ag_rcp_customers_list_table_columns' );

function ag_rcp_customers_list_table_column_company( $value, $customer ) 
{
  $terms = rcp_get_membership_meta( $customer->get_id(), 'agree-terms', true );
  
  return $terms;
}

add_filter( 'rcp_customer_list_table_column_company', 'ag_rcp_customers_list_table_column_company', 10, 2 );

This code was taken from the documentation from restrict content pro but applied to memberships. I have tried to tailor it towards customers instead.

documentation is here: documentation

Custom PHP settings PHP-FPM best practice [closed]

I am setting up a LEMP server (Ubuntu/Nginx/PHP) with PHP-FPM, and I was wondering what is the best practice for modifying global PHP settings? There seems to be a few options:

  1. Edit /etc/php/8.3/fpm/php.ini directly.
  2. Edit /etc/php/8.3/fpm/php-fpm.conf directly.
  3. Edit /etc/php/8.3/fpm/pool.d/www.conf directly (although this is normally per site files).
  4. Create a file /etc/php/8.3/fpm/conf.d/GLOBAL.ini.

I did some research, but couldn’t find any useful suggestions. I am guessing it’s not that important, but surely there are some strong opinions? I am inclined to use the last option #4, because that seems the most tidy. Thanks for suggestions.

Laravel 11 API: Always got unauthenticated message

I am using Laravel 11 for API with sanctum for authorization. Login works fine but logout always get unauthenticated with Http Status 401.

How to solve this problem and return HTTP status 200 as it suppose to do?

Here are my code and Postman’s API request

AuthController

    public function logout(Request $request)
    {
        $request->user()->currentAccessToken()->delete();

        return response()->json([
            'message' => 'Logged out successfully',
        ],200);
    }

routes/api.php

Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->group(function () {
    Route::post('/logout', [AuthController::class, 'logout']);
});

Postman

{
    "name": "Logout",
    "request": {
        "method": "POST",
        "header": [
            {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
            },
            {
                "key": "Content-Type",
                "value": "application/json"
            },
            {
                "key": "Accept",
                "value": "application/json",
                "type": "text"
            }
        ],
        "url": {
            "raw": "{{base_url}}/api/logout",
            "host": [
                "{{base_url}}"
            ],
            "path": [
                "api",
                "logout"
            ]
        }
    },
    "response": []
},

Thanks in advance.

I tried adding gaurds but npt working
config/auth.php

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'sanctum',
            'provider' => 'users',
        ],
    ],