Stuck on SQL Lab 6.2.3 (Cisco Data Analytics Essentials) – Query Not Working

Currently stuck on 6.2.3 SQL Lab: SQL Around the World in the Data Analytics Essentials course (CISCO Networking Academy).

I’ve tried both:

SELECT * 
FROM shapes 
WHERE color = 'red'

and

SELECT * 
FROM shapes 
WHERE color LIKE 'red'

…but I keep getting the same error and now I can’t claim my badge
Anyone know what I might be missing?

enter image description here

Vite API proxy redirects to configured target

I have configured an API proxy in vite.config.ts:

    server: {
        proxy: {
            '/api': {
                target: 'http://nginx_backend:80',
                changeOrigin: true,
                rewrite: (path) => path.replace(/^/api/, ''),
            }
        }
    },

(https://git.var-lab.com/opencal/web-frontend/-/blob/main/vite.config.ts?ref_type=heads#L26)

the endpoint is set here as baseUrl:

const apiClient = axios.create({
    baseURL: '/api',
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    },
});

(https://git.var-lab.com/opencal/web-frontend/-/blob/main/src/services/api.ts?ref_type=heads#L3)

When I use a method like this

export async function getDayAvailabilities(email: string, dayAsString: string, eventTypeId: number): Promise<Availability> {
    try {
        const response = await apiClient.get(`/availability/day/?email=${email}&date=${dayAsString}&event_type_id=${eventTypeId}`);
        return response.data;
    } catch (error) {
        console.error(error);
        throw error;
    }
}

(used here: https://git.var-lab.com/opencal/web-frontend/-/blob/main/src/components/booking/BookingAvailabilities.vue?ref_type=heads#L99)

to request the API behind the proxy, the request is redirected from http://localhost/api/availability/day/[email protected]&date=2025-07-23&event_type_id=1 to http://nginx_backend/availability/[email protected]&date=2025-07-23&event_type_id=1

Reproduction

https://git.var-lab.com/opencal/web-frontend

Steps to reproduce

It can be reproduced by following the setup steps in the readme here https://git.var-lab.com/opencal/local-dev

When the fixtures are loaded, open http://localhost/[email protected] in your browser, select a event type and then a day. In the debug toolbar you will see what appens.

System Info

It runs in docker, see https://git.var-lab.com/opencal/web-frontend/-/blob/main/Dockerfile

Logs

How to plot Google Calendar–like API response (recurring events, exceptions) on a custom frontend calendar?

I’m currently building a backend-first calendar scheduling system (like Google Calendar), and I’m working with the following type of event data returned from my API:

It includes recurring events (RRULE), all-day events (start.date), time-specific events (start.dateTime), and exception instances (e.g. cancelled occurrences of a recurring event).

I am going to replicate the response same as a google calendar api reponse.

Here’s a sample of Google API response:

json
Copy
Edit
it

{
        "kind": "calendar#event",
        "etag": ""3503602610079486"",
        "id": "6butbk1c770g1pnp4fnn2sokbd",
        "status": "confirmed",
        "htmlLink": "https://www.google.com/calendar/event?eid=NmJ1dGJrMWM3NzBnMXBucDRmbm4yc29rYmRfMjAyNTA3MDYgZ2FnYW9xcGhzQG0",
        "created": "2025-07-06T11:24:59.000Z",
        "updated": "2025-07-06T11:28:25.039Z",
        "summary": "Event Daily All Day Event",
        "creator": {
            "email": "[email protected]",
            "self": true
        },
        "organizer": {
            "email": "[email protected]",
            "self": true
        },
        "start": {
            "date": "2025-07-06"
        },
        "end": {
            "date": "2025-07-07"
        },
        "recurrence": [
            "RRULE:FREQ=DAILY"
        ],
        "transparency": "transparent",
        "iCalUID": "[email protected]",
        "sequence": 0,
        "reminders": {
            "useDefault": false
        },
        "eventType": "default"
    },
    {
        "kind": "calendar#event",
        "etag": ""3503602610079486"",
        "id": "6butbk1c770g1pnp4fnn2sokbd_20250708",
        "status": "cancelled",
        "htmlLink": "https://www.google.com/calendar/event?eid=NmJ1dGJrMWM3NzBnMXBucDRmbm4yc29rYmRfMjAyNTA3MDggZ2FnYW9xcGhzQG0",
        "created": "2025-07-06T11:24:59.000Z",
        "updated": "2025-07-06T11:28:25.039Z",
        "summary": "Event Daily All Day Event",
        "creator": {
            "email": "[email protected]",
            "self": true
        },
        "organizer": {
            "email": "[email protected]",
            "self": true
        },
        "start": {
            "date": "2025-07-08"
        },
        "end": {
            "date": "2025-07-09"
        },
        "recurringEventId": "6butbk1c770g1pnp4fnn2sokbd",
        "originalStartTime": {
            "date": "2025-07-08"
        },
        "transparency": "transparent",
        "iCalUID": "[email protected]",
        "sequence": 1,
        "reminders": {
            "useDefault": false
        },
        "eventType": "default"
    },
    {
        "kind": "calendar#event",
        "etag": ""3503602744428542"",
        "id": "10rll18oedfpa2nbh6hrf6ragb",
        "status": "confirmed",
        "htmlLink": "https://www.google.com/calendar/event?eid=MTBybGwxOG9lZGZwYTJuYmg2aHJmNnJhZ2IgZ2FnYW9xcGhzQG0",
        "created": "2025-07-06T11:29:32.000Z",
        "updated": "2025-07-06T11:29:32.214Z",
        "summary": "Test ",
        "creator": {
            "email": "[email protected]",
            "self": true
        },
        "organizer": {
            "email": "[email protected]",
            "self": true
        },
        "start": {
            "dateTime": "2025-07-08T07:30:00Z",
            "timeZone": "UTC"
        },
        "end": {
            "dateTime": "2025-07-08T08:30:00Z",
            "timeZone": "UTC"
        },
        "iCalUID": "[email protected]",
        "sequence": 0,
        "reminders": {
            "useDefault": true
        },
        "eventType": "default"
    },
    {
        "kind": "calendar#event",
        "etag": ""3503603073450078"",
        "id": "6ldsh849d28crn0fl5kl9ne35o",
        "status": "confirmed",
        "htmlLink": "https://www.google.com/calendar/event?eid=Nmxkc2g4NDlkMjhjcm4wZmw1a2w5bmUzNW9fMjAyNTA3MDZUMjAzMDAwWiBnYWdhb3FwaHNAbQ",
        "created": "2025-07-06T11:32:16.000Z",
        "updated": "2025-07-06T11:32:16.725Z",
        "creator": {
            "email": "[email protected]",
            "self": true
        },
        "organizer": {
            "email": "[email protected]",
            "self": true
        },
        "start": {
            "dateTime": "2025-07-06T20:30:00Z",
            "timeZone": "UTC"
        },
        "end": {
            "dateTime": "2025-07-06T20:45:00Z",
            "timeZone": "UTC"
        },
        "recurrence": [
            "RRULE:FREQ=WEEKLY;WKST=SU;BYDAY=SU"
        ],
        "iCalUID": "[email protected]",
        "sequence": 0,
        "reminders": {
            "useDefault": true
        },
        "eventType": "default"
    }

Smoothing scroll animations in js

So my question is extremely simple, i see it on lots of websites
https://www.jordangilroy.com/#work
this one for example is my reference, when you scroll it feels alot smoother and the animations kinda like “catch up” to your scroll. only thing i can find is scroll-behaviour:smooth; which is obviously not what i need.

im very new to js so idk most of the functions ive tried to replicate a scrolling feature.

im not entirely sure how im supposed to show my example so ill just use a screenshot
my attempt
as you can see its kind of like splitting the images between the two parallax backgrounds, but the scrolling and animations feel too rigid.

The code below is mainly just for the image cutting kinda feature so yea. not sure how i can do the smooth animation

//#region history image changer (scroll Event)
const historyContent = document.getElementsByClassName("historyLayout");
const parallaxContent = document.querySelectorAll('section .parallax');
window.addEventListener('scroll', () => {
  let scrollY = window.scrollY;

  const prehistoricContainer = historyContent[0];
  const containerMiddle = (prehistoricContainer.getBoundingClientRect().top - prehistoricContainer.getBoundingClientRect().bottom) / 2;
  const containerHalf = prehistoricContainer.getBoundingClientRect().top - containerMiddle;
  if (containerHalf <= window.innerHeight / 2) {
    for (const content of historyContent) {
      content.style.position = "fixed";
      content.style.top = "0";
      content.style.left = "0";
      content.style.right = "0";
      content.style.bottom = "0";
      if ((scrollY - containerHalf - 1000) <= window.innerHeight / 2) {
        content.style.position = "absolute";
      }
    }
  }

  cuttingImages();
}
);

let cutcounter = 0;
function cuttingImages() {
  let section1 = historyContent[cutcounter];

  let parallax2 = parallaxContent[cutcounter + 1];
  let section2 = historyContent[cutcounter + 1];

  let image1Top = section1.getBoundingClientRect().top;
  let section2Top = parallax2.getBoundingClientRect().top;
  let progress = (image1Top - section2Top) / -966;
  progress = Math.max(0, Math.min(1, progress));
  section1.style.clipPath = 'inset(0 0 ' + (100 - progress * 100) + '% 0)';
  section2.style.clipPath = 'inset(' + (progress * 100) + '% 0 0 0)';
  if (progress === 0 && cutcounter === 0) {
    cutcounter++;
  }
  if (progress === 1 && cutcounter > 0) {
    cutcounter--;
  }
}

//#endregion

i tried scroll-behaviour: smooth; obviously not what i need
i heard about requestanimationframe and wasnt rlly sure how to implement it, i tried it, nothing looks different, there wasnt much difference if at all so not sure either.

Cant filter an array based on another arrays content

I’m willing to do the following:
I have an array with this apparence:

finalFiltrada = [
    {
      "año_cuatri": "1° 1°",
      "codigo": "1.1.1",
      "nombre": "Técnicas de Programación",
      "estado": "Promocionada",
      "año_cursada": "2024 2°C",
      "nota": 8,
      "tiene_apuntes": true,
      "link_apuntes": "111_tecnicas_de_programacion"
    },

]

Depending on the filter you click:showing the filters of the page

I receive an array with the above structure, where the field ‘estado’, can be one of these: ‘Promocionada’, ‘Pendiente’, ‘Cursando’

So I receive the subjects array of objects, but my problem is:
I also receive an array with the checkboxs clicked, looks like this:
dataFiltradaSeleccionada = ['Promocionada', 'Pendiente', 'Cursando']

What I’m currently doing is:

        if (dataFiltradaSeleccionada.length > 0) {
            finalFiltrada = finalFiltrada.filter((e, i) => {

                // if (e.estado === dataFiltradaSeleccionada) {
// this doesnt work because dataFiltradaSeleccionada is maximum 3 positions
                //     console.log("e.estado", e.estado);
                //     console.log("dataFiltradaSeleccionada[i]", dataFiltradaSeleccionada[i]);
                // }

                return e.estado.includes(dataFiltradaSeleccionada)
            })

        }

But this doesn’t work when I clicked more than one checkbox

Web Components: Slots are not working as (I) expected in light DOM

How can I change the following light DOM custom element to show the content of the default slot between (!!!) the two horizontal rulers?
Please be aware, that I cannot use shadow DOM in my use case.

<!DOCTYPE html>
<html lang="en">

<head>
</head>

<body>
  <script>
    class MyComponent extends HTMLElement {
      connectedCallback() {
        this.innerHTML = `
          <hr>
          <slot></slot>
          <hr>
        `;
      }
    }

    customElements.define('my-component', MyComponent);
  </script>

  <my-component>
    This text shall be placed between the two rulers, not below them.
  </my-component>
</body>

</html>

jquery table data on click event

I have a table data from which I want to get id on button click event. I tried two functions using jquery.

// table data with button

<button type="button" value="{{$item->id}}" id="edit_btn" class=" btn btn-primary btn-sm">Edit</button>

<button type="button" value="{{$item->id}}" id="onclick_edit_btn" class=" btn btn-primary btn-sm">oc.Edit</button>

jquery function

$(document).ready(function(){
    
    // first approach
    $(document).on('click', '#edit_btn',function(){
            var category_id = $(this).val();
            alert(category_id);

    });
    
    
    // second approach
    $("#onclick_edit_btn").click(function(){
            var category_id = $(this).val();
            alert(category_id);
  });

});

When I click the edit button with id edit_btn, its giving id for each row of data. But when I click the edit button with id onclick_edit_btn, it’s giving id of only first row. Its not giving id of other rows when clicked, why is it so?
What is the difference between the two functions?

How can I automatically refresh the token and retry the fetch request after receiving a 401 response?

const acceptRequest = async () => {
    try {
      const res = await fetch(`${process.env.NEXT_PUBLIC_SOCKET_SERVER_URL}/acceptRequest`, {
        method: "POST",
        body: JSON.stringify({ id: enemyid }),
        credentials: "include",
        headers: {
          "Content-Type": "application/json",
        },
      });
      if (res.status === 200) toast("Working");
      if(res.status === 401)await refreshTokenFn()
    } catch (err) {
      if (err instanceof Error) toast(err.message);
      setPending(false);
    }
  };

I have a refreshToken function that I can call to refresh the token. I want the fetch request to retry automatically after refreshing the token, without duplicating the entire code.

This is how I am handling it which is not good enough for me.

const acceptRequest = async () => {
    try {
      const res = await fetch(`${process.env.NEXT_PUBLIC_SOCKET_SERVER_URL}/acceptRequest`, {
        method: "POST",
        body: JSON.stringify({ id: enemyid }),
        credentials: "include",
        headers: {
          "Content-Type": "application/json",
        },
      });
      if (res.status === 200) toast("Working");
      if(res.status === 401){
           await refreshTokenFn()
        const res = await     fetch(`${process.env.NEXT_PUBLIC_SOCKET_SERVER_URL}/acceptRequest`, {
        method: "POST",
        body: JSON.stringify({ id: enemyid }),
        credentials: "include",
        headers: {
          "Content-Type": "application/json",
        },
      });
 if (res.status === 200) toast("Working");
}

    } catch (err) {
      if (err instanceof Error) toast(err.message);
      setPending(false);
    }
  };

How to Update an Immutable Signal Object which is itself a AppComponent Property?

I am struggling with a simple plain object, which is itself a property of AppComponent. This object “x” is wrapped as a writable signal.
I want to implement a method which updates the own property of the signal object “x”.

Further the object “x” itself should be immutable.

Here is the code:

import { bootstrapApplication } from '@angular/platform-browser';
import { Component, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-root',
  imports: [FormsModule],
  template: `

   <h1> {{title}}<h1>
    <hr>
   <p> Value of the X Property X: {{x().Value}} <p>
  `,

  styles: ['html { line-height: 1.15;} input{border: 0.1em solid lightgreen;}'],
})
export class AppComponent {
   protected title = 'How to update an Immutable Signal Object which is itsels a AppComponent Proberty? ';

 readonly  x = signal<IVariableBuilder> ({
        variableName: 'X',
        Value: 0,
        unit: ''
});
 
upDateMethod(){
this.x.update(f => f.Value= 1234 )  // Does not work
 }
}

interface IVariableBuilder {
  readonly variableName: string; // to get information, which variable was changed by <input>
  readonly Value: number,
  readonly  unit: string;  
}

bootstrapApplication(AppComponent); 

Also refer to myStackbiltzCode

retrieve data using where condition and sort in descending order

I am trying to retrieve category (id, category_name, status) table data using where condition and sort in descending order for id. I am writing query like::

public function category()
    {
        $category = Category::where('status', 'true');
        return view('admin.services.category', compact('category'));
    }

this is showing error
Attempt to read property "category_name" on array. How to fetch data using where condition as status == true and order id in descending order?

Telegram Bot Not Responding to /start Command

I’m developing a Telegram bot using PHP, and it responds to Telegram updates, but when I send the /start command, it does not react. I’m trying to understand why the bot is not responding to /start.

Key points:
Webhook is enabled and correctly set up with the bot URL (I verified that the URL is correct).
In bot.php, I’m using json_decode(file_get_contents(“php://input”), true) to read the updates from Telegram.
In start.php, I’m handling the /start command, but the bot doesn’t send any message.
I’m using PHP to connect to a MySQL database and store user data in the users table.
I checked the log.txt file, and it correctly receives the updates, but the /start command is not being handled.

Problems I am facing:
The bot does not respond to the /start command.
I’m using send_reply(“sendMessage”, …) to send messages, but nothing happens when /start is sent.
I’m not seeing any errors in the logs when I send /start to the bot.

Anybody would help me?

Index.php can’t find the route/path of the desired files [closed]

Explanation:

I’m making a website (new to this) and wanted to make a system to handle all requests to make maintainece easier.

Idea

When a file needs to go to another path, it would go through index.php and index will reveal the path and direct it there. (A router)
And when the webserver files need to access the database(which is private) they will ask index.php to ask hub.php and hub.php will give the desired information from database.

Issues

Index.php isn’t able to find the path or connect them even though i gave the correct code.

My Files:

Folder/
    ├── database/
    │   ├── accounts/
    │   │   ├── orders/
    │   │   ├── reviews/
    │   │   └── users.json
    │   ├── designs/
    │   └── system/
    │       └── logo.png
    ├── root/
    │   ├── 0/
    │   │   ├── admin.php
    │   ├── 1/
    │   │   └── main.php
    │   ├── 2/
    │   │   ├── catalog.php
    │   │   ├── checkout_system/
    │   │   ├── design.php
    │   │   ├── functions.php
    │   │   └── list-catalog/
    │   ├── 3/
    │   │   └── contact.php
    │   ├── 4/
    │   │   ├── reviews.php
    │   │   └── submit_review.php
    │   ├── 5/
    │   │   ├── bulk-purchase/
    │   │   └── list.php
    │   ├── 6/
    │   │   └── login.php
    │   ├── 7/
    │   │   ├── footer.php
    │   │   └── header.php
    │   └── index.php
    └── hub.php

My index.php code:

<?php
error_reporting(0);
ini_set('display_errors', 0);
define('LOG_FILE', __DIR__.'/security.log');
register_shutdown_function(function() {
    if ($error = error_get_last()) {
        error_log(date('[Y-m-d H:i:s] ').print_r($error,1)."n", 3, LOG_FILE);
    }
});

session_start([
    'cookie_httponly' => 1,
    'cookie_samesite' => 'Strict',
    'sid_length' => 128,
    'sid_bits_per_character' => 6
]);

// Route mapping
$routes = [
    '/' => '/1/main.php',
    '/main' => '/1/main.php',
    '/catalog' => '/2/catalog.php',
    '/design' => '/2/design.php',
    '/contact' => '/3/contact.php',
    '/reviews' => '/4/reviews.php',
    '/submit-review' => '/4/submit_review.php',
    '/login' => '/6/login.php',
    '/logout' => '/6/logout.php',
    '/admin' => '/0/admin.php'
];

// Get requested path
$requestPath = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);

// Find matching route
foreach ($routes as $route => $file) {
    if ($requestPath === $route) {
        $absolutePath = __DIR__.$file;
        
        // 100% file existence guarantee
        if (!file_exists($absolutePath)) {
            error_log("Missing route file: $absolutePath", 3, LOG_FILE);
            http_response_code(500);
            exit('System configuration error. Admin notified.');
        }
        
        // Generate CSRF token (once per session)
        if (empty($_SESSION['csrf_token'])) {
            $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
        }
        
        // Authentication check
        $protectedRoutes = ['/admin', '/submit-review'];
        if (in_array($route, $protectedRoutes) && empty($_SESSION['user'])) {
            header('Location: /login');
            exit;
        }
        
        include $absolutePath;
        exit;
    }
}

// 404 Handling
http_response_code(404);
$contactPath = __DIR__.'/root/3/contact.php';
if (file_exists($contactPath)) {
    include $contactPath;
} else {
    echo '<h1>404 - Page Not Found</h1>';
}

My hub.php code:

<?php
// Armored session
session_start([
    'cookie_httponly' => 1,
    'cookie_samesite' => 'Strict'
]);

// JSON responses
header('Content-Type: application/json');

// Request validation fortress
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    exit(json_encode(['error' => 'POST requests only']));
}

$refererHost = parse_url($_SERVER['HTTP_REFERER'] ?? '', PHP_URL_HOST);
$serverHost = $_SERVER['HTTP_HOST'] ?? '';
if ($refererHost !== $serverHost) {
    http_response_code(403);
    exit(json_encode(['error' => 'Cross-origin requests forbidden']));
}

// CSRF vault
$token = $_POST['csrf_token'] ?? '';
if (!isset($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $token)) {
    http_response_code(403);
    exit(json_encode(['error' => 'Security token mismatch']));
}

function verifyAuth() {
    if (empty($_SESSION['user'])) {
        http_response_code(401);
        exit(json_encode(['error' => 'Authentication required']));
    }
}

try {
    $action = $_POST['action'] ?? '';
    
    switch ($action) {
        case 'login':
            $username = $_POST['username'] ?? '';
            $password = $_POST['password'] ?? '';
            
            // Load users
            $users = json_decode(file_get_contents(__DIR__.'/database/accounts/users.json'), true) ?: [];
            foreach ($users as $id => $user) {
                if ($user['username'] === $username && password_verify($password, $user['password'])) {
                    $_SESSION['user'] = [
                        'id' => $id,
                        'name' => $user['name'],
                        'level' => $user['level'] ?? 1
                    ];
                    session_regenerate_id(true);
                    exit(json_encode(['success' => true]));
                }
            }
            exit(json_encode(['success' => false, 'error' => 'Invalid credentials']));
            
        case 'get_designs':
            $designs = [];
            $path = __DIR__.'/database/designs/';
            
            // Glob with absolute security
            foreach (glob($path.'*.{jpg,png,webp}', GLOB_BRACE) as $file) {
                $designs[] = [
                    'name' => basename($file),
                    'url' => '/database/designs/'.rawurlencode(basename($file))
                ];
            }
            exit(json_encode(['designs' => $designs]));
            
        case 'submit_review':
            verifyAuth();
            $data = [
                'id' => 'rev_'.bin2hex(random_bytes(8)),
                'user_id' => $_SESSION['user']['id'],
                'name' => $_POST['name'] ?? '',
                'rating' => max(1, min(5, (int)($_POST['rating'] ?? 5))),
                'comment' => substr($_POST['comment'] ?? '', 0, 500),
                'date' => date('Y-m-d H:i:s')
            ];
            
            // Write with atomic safety
            $tmpFile = tempnam(sys_get_temp_dir(), 'rev');
            file_put_contents($tmpFile, json_encode($data));
            rename($tmpFile, __DIR__."/database/accounts/reviews/pending/{$data['id']}.json");
            
            exit(json_encode(['success' => true]));
            
        default:
            http_response_code(400);
            exit(json_encode(['error' => 'Invalid action']));
    }
} catch (Throwable $e) {
    http_response_code(500);
    exit(json_encode(['error' => 'System processing error']));
}

Attempted Troubleshooting:

  • I made sure they are the exact path
  • i asked ai if there is error in the code and it said no

How to write a SQL query to produce a result which has more than 2 levels of depth

tell me, is it possible to get all the data from 4 tables with one SQL query?

Here is the DB diagram with connections:
enter image description here

Thus, a product can have 1 category, many configurations in which many options.

I would like to get something like this result after the request:

{
  "product_1": {
    "name": "product1",
    "category": "cat1",
    "equipments": {
      "0": {
        "name": "equip1",
        "options": {
          "options1": "options 1",
          "options2": "options 2",
          "options3": "options 3"
        }
      },
      "1": {
        "name": "equip2",
        "options": {
          "options1": "options 3",
          "options2": "options 2"
        }
      }
    }
  },
  "product_2": {
    "name": "product2",
    "category": "cat2",
    "equipments": {
      "0": {
        "name": "equip1",
        "options": {
          "options1": "options 1",
          "options2": "options 3"
        }
      },
      "1": {
        "name": "equip2",
        "options": {
          "options1": "options 3"
        }
      }
    }
  }
}

Is it possible to get this with one query? I’m already tired of these Join and JSON_ARRAYAGG functions, it doesn’t work, I tried to combine them, nothing… Maybe I’m wasting my time and should I use several queries? Or is it possible to get all the data for all the connections in one query? I’m writing in PHP using PDO. Please help me with my problem.

UPD:

Here is an example of what I tried, this is one of the options. Here I was able to get a value only from two tables “Equipments” and “Options”, then I tried to combine another JOIN and it doesn’t work at all.

$stmt = $link->prepare("select equipment.*, JSON_ARRAYAGG(JSON_OBJECT(
            'name', options.name,
            'descript', options.descript
            )) AS Options FROM equipment
            LEFT JOIN options ON equipment.id=options.equipment_id GROUP BY equipment.id
          ");

Why does bybit api return an empty list after requesting trade history?

I am trying to get my trade history from the Bybit api V5, but it keeps returning an empty list although getting my wallet balance works.

I wrote this code below and although the “getBybitWalletBalance” function works perfectly, the “getBybitTradeHistory” function keeps returning an empty list. My last trade on BTCUSDT perpetuals was a month ago. I also tried the other categories, but they all give the same output.

bybit.php

<?php

    $apiKey = '...';
    $apiSecret = '...';
    $window = "5000";

    // Global
    function bybitSignature($method, $path, $query, $body) {
        global $apiKey, $apiSecret, $window;
        $timestamp = round(microtime(true) * 1000);
        if($method === "GET") {
            return hash_hmac("sha256", $timestamp . $apiKey . $window . $query, $apiSecret);
        } else {
            return hash_hmac("sha256", $timestamp . $apiKey . $window . $body, $apiSecret);
        }
    }

    function bybitCurl($url, $signature) {
        global $apiKey, $window;
        $timestamp = round(microtime(true) * 1000);
        $ch = curl_init();
        
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            "Accept: application/json",
            "X-BAPI-API-KEY: " . $apiKey,
            "X-BAPI-TIMESTAMP: " . $timestamp,
            "X-BAPI-SIGN: " . $signature,
            "X-BAPI-RECV-WINDOW: " . $window
        ));
        
        if(curl_errno($ch)) {
            return curl_error($ch);
        } else {
            return curl_exec($ch);
        }
        
        curl_close($ch);
    }

    // Trade
    function getBybitTradeHistory($category) {
        return bybitCurl("https://api.bybit.com/v5/execution/list?category=" . $category, bybitSignature("GET", "/v5/execution/list", "category=" . $category, ""));
    }

    // Account
    function getBybitWalletBalance($accountType) {
        return bybitCurl("https://api.bybit.com/v5/account/wallet-balance?accountType=" . $accountType, bybitSignature("GET", "/v5/account/wallet-balance", "accountType=" . $accountType, ""));
    }

    var_dump(json_decode(getBybitTradeHistory("linear"), true));

?>

output
array(5) { ["retCode"]=> int(0) ["retMsg"]=> string(2) "OK" ["result"]=> array(3) { ["nextPageCursor"]=> string(0) "" ["category"]=> string(6) "linear" ["list"]=> array(0) { } } ["retExtInfo"]=> array(0) { } ["time"]=> int(1751725711326) }