Deprecated error after upgrade PHP Version

I was using below formula in PHP. It was working fine till PHP 7.4. Now I have upgraded to PHP 8.1 and it’s giving error.

<?php
    echo ((float)13.5 + intdiv((float)13.5, (int)10) * (float)2.5 / (int)12);

I’m getting error Exception: Deprecated Functionality: Implicit conversion from float 13.5 to int loses precision

How can I solve this? What is the reason for this error?

Access to an undefined property IlluminateDatabaseEloquentModel:: larastan

i´m trying solve this problem in laravel with larastan

Access to an undefined property                                           
         IlluminateDatabaseEloquentModel::$bloqueante

I´m doing in my class:

/**
 * @property int $id
 * @property bool $bloqueante
 * @property string $mensajeError
 * IlluminateSupportCollection<Validacion> $validacion
 */

This properties it´s my errors. The code that return this message it´s, for example:

$this->validacion = Validacion::where('tipoFicheroControl_id' .....)->first()
.................
$mensaje = json_encode([
                "tipo" => ($this->validacion->bloqueante == 1) ? 'Error' : 'Warning',

I changed my logic in variable $this->validacion. Before this variable it´s defined in locally. Now it´s defined in class with protected.

other similar error, i can solve using: * IlluminateSupportCollection<Validacion> $validacion

In my model i have defined:

/**
 * AppModelsValidacion
 *
 * @property string $clasePHP
 * @property string $mensajeError
 * @property bool $bloqueante
 * @property string $parametrosClase
 * @property bool $habilitada
 * @property EstructuraFichero $columna
 */

and i have fillable array. But in this class always return this message.

Sorry for my bad english, and i hope that anybody can help me.

HttpClient.PostAsync and PHP api

Hello All respected SO members,

I am trying to build an android app with .NET MAUI.
I tried to save a content to MySQL database using HttpClient.PostAsync through PHP Api, however I can not make it work (the response is Success but the data is not saved to the table), while when I tried using POSTMAN to test with the PHP Api, everything is ok and it is able to save into the desired table.

.NET MAUI code

EmployeeData emp = new EmployeeData();
emp.emp_pin= EmpID.Text;

HttpClient cl = new HttpClient();
string js = JsonSerializer.Serialize(emp);
StringContent httpContent = new StringContent(js, Encoding.UTF8, "application/json");
var response = cl.PostAsync(Url, httpContent).Result;
if (response.IsSuccessStatusCode)
{
    DisplayAlert("Success", "Success Record Your Data.", "OK");
}
else
{
    DisplayAlert("Fail", "Please Try Again.", "OK");
}

Model

public class EmployeeData
{
    public string emp_pin{ get; set; }
}

PHP API

<?php
require_once('dbhelper.php');

$json = file_get_contents('php://input');
$data = json_decode($json, true);

$emppin=$data['emp_pin'];
$sql = $conn->prepare("INSERT INTO test (emp_pin) VALUES (?)");
$sql->bind_param('s', $emppin);
$sql->execute();
if ($sql) {
    echo json_encode(array('RESPONSE' => 'SUCCESS'));
} else {
    echo json_encode(array('RESPONSE' => 'FAILED'));
}

Using POSTMAN, the data is successfully saved to the table.
enter image description here

using the JSON Visualizer,
enter image description here

Please highlight to me which part I made a mistake on.

Mockery Throws Error When Mocking Redis Connection: MockeryExceptionBadMethodCallException

I have a command and some methods related to Redis connection are running in it. I want to test some of these methods and for this I want to mock the Redis connection. I approached it like this:

protected function mockRedis(): void
{
    $redisConnection = Mockery::mock(Connection::class);
    app()->instance(Connection::class, $redisConnection);

    Redis::shouldReceive('connection')
        ->once()
        ->andReturn($redisConnection);

    Redis::connection()
        ->shouldReceive('client')
        ->once()
        ->andReturnSelf();

    Redis::connection()
        ->client()
        ->shouldReceive('ping')
        ->once()
        ->andReturn(true);

    Redis::connection()
        ->client()
        ->shouldReceive('close')
        ->once();

    Redis::shouldReceive('subscribe')
        ->once()
        ->with(['socket-data'], Mockery::type('callable'))
        ->andReturnUsing(function ($channels, $callback) {
            $message1 = json_encode([
                'type' => 'alive',
                'interval' => 10,
                'time' => '2023-10-04T10:00:00+00:00',
            ]);

            $message2 = json_encode([
                'type' => 'some_type',
                'data' => 'some_data',
            ]);

            $callback($message1);
            $callback($message2);
        });
}

The lines I want to test are as follows:

// some openswoole methods...
// ...
Redis::connection()->client()->ping();

// ...
Redis::connection()->client()->close();

// ...
Redis::subscribe(['socket-data'], function (string $message) {
    //...
});

Caught error:

1) TestsFeatureRedisSubscribeTest::test_redis_subscribe_command
MockeryExceptionBadMethodCallException: Received Mockery_0_Illuminate_Redis_Connections_Connection::client(), but no expectations were specified

enter image description here

Any idea?

twitter oauth2: An error has occurred. You were unable to authorize access to the application. Go back and try to sign in again

I’m using this package to allow users to authenticate with my app built with Symfony. After making all the settings I got this error when I clicked on the connect with Twitter button. The generated URL is https://twitter.com/i/oauth2/authorize?scope=users.read&code_challenge=uiaHgNctzfAnLY965g_wEiQl0XcIrwa5miK1sl-XqZk&code_challenge_method=S256&state=a0911d18bafd322f423d9ab0dc6b6f32&response_type=code&approval_prompt=auto&redirect_uri=https%3A%2F%2Ftopautosntest.sn-topauto.com%2FConnexion%2Ftwitter%2Fcheck&client_id=NF9GMlI2OFdPUHFDT2NxN1hlQ2c6MTpjaQ .
What I’m doing wrong?

Debug what plugin is changeing woocommerce order status

Something is changing the status of orders in my woocommerce store from processing to pending. I want to log what it is to the file. I have such a code:

function log_woocommerce_order_status_change($order_id, $old_status, $new_status) {
    $current_datetime = date('Y-m-d H:i:s');

    $call_stack = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 5);
    $plugin_info = 'Plugin info not available';

    foreach ($call_stack as $trace) {
        if (isset($trace['file']) && strpos($trace['file'], 'plugins/') !== false) {
            $plugin_info = 'Plugin file: ' . $trace['file'] . ', Line: ' . $trace['line'];
            break;
        }
    }

    $log_message = "[$current_datetime] woocommerce_order_status_changed hook called for order ID $order_id. Old status: $old_status, New status: $new_status. Triggered by: $plugin_info";
    error_log($log_message . PHP_EOL, 3, WP_CONTENT_DIR . '/woocommerce_order_status.log', FILE_APPEND);
}

add_action('woocommerce_order_status_changed', 'log_woocommerce_order_status_change', 10, 3);

But every time the status is changed it gives me the same result:

woocommerce_order_status_changed hook called for order ID 13232. Old status: processing, New status: pending. Triggered by: Plugin file: /home/maisonpa/domains/my-theme/public_html/wp-content/plugins/woocommerce/includes/class-wc-order.php, Line: 405

Is it possible to get the name of the plugin / file that directly calls the function “woocommerce_order_status_changed” and not the file in which it is stored?

Wont display repeater fields

I am trying to make a custom header with ACF, but for this header I need menu items and those menu items need sub items. I have 2 repeater fields one inside the other. But when I try out the code it does not work. But I do not get a error or something like that so I do not know where it goes wrong! Can somebody help me please!

I tried to display it by using this code:

// check for rows (parent repeater)
                if( have_rows('header_menu') ): 

                    // loop through rows (parent repeater)
                    while( have_rows('header_menu') ): the_row(); ?>
                            <?php 
                                $linkMenu = get_sub_field ( 'menu_item_link' , 'options' );
                            $tekstMenu =  get_sub_field('menu_item_naam' , 'options');
                            // Do something...
                            ?>
                            <a href="<?php echo esc_url ($linkMenu); ?>">
                                <?php echo $tekstMenu; ?>
                            </a>
            <?php
                            // check for rows (sub repeater)
                            if( have_rows('menu_item_submenu') ): ?>

                                <?php 

                                // loop through rows (sub repeater)
                                while( have_rows('menu_item_submenu') ): the_row();
 
                                    $nestledLink = get_sub_field( 'nestled_item_link', 'options');
                                    $nestledNaam = get_sub_field('nestled_item_naam', 'options');

                                    // display each item
                                    ?>
                                    <a href="<?php echo esc_url($nestledLink); ?>"<?php echo $nestledNaam; ?></a>
                                <?php endwhile; ?>
  
                            <?php endif; //if( get_sub_field('menu_item_submenu') ): ?>
 

                    <?php endwhile; // while( has_sub_field('header_menu') ): ?>

                <?php endif; // if( get_field('header_menu') ): ?>

But literally nothing happens

Google drive file upload using Service account of

I want to save the file to Google Drive from the php site. For this, I’m using the Api Key (in JSON form) of Service Accounts in the Google developer console Apis & Services to upload files in in Drive folder.
Now the problem is that It takes 8 to 9 seconds to upload files to drive, no matter how fast your internet connection is. I want to optimize it so that It will completely depend on the network speed. In the PHP site, I am using (composer require Google/apiclient:^2.15).

(Upload File)
function uploadFiles($file, $folderName, $fileName, $driveId )
{
try {
    set_time_limit(60);
    $client = new Google_Client();
    putenv('GOOGLE_APPLICATION_CREDENTIALS=./api_key.json');
    $client->useApplicationDefaultCredentials();
    $client->addScope(Drive::DRIVE);
    $driveService = new Drive($client);
    $existingFolder = getFolderByName($driveService, $folderName, $driveId);
    if ($existingFolder) {
        $existingFile = getFileByName($driveService, $fileName, $existingFolder->id);
        if ($existingFile) {
            if (deleteFile($driveService, $existingFile->id)) {
                return uploadFile($driveService, $file, $fileName, $existingFolder->id);
            } else {
                return null;
            }
        } else {
            return uploadFile($driveService, $file, $fileName, $existingFolder->id);
        }
    } else {
        $createdFolder = createFolder($driveService, $folderName, $driveId);
        if ($createdFolder) {
            return uploadFile($driveService, $file, $fileName, $createdFolder);
        } else {
            return null;
        }
    }
} catch (Exception $ex) {
    return 100;
  }
}
(Get Folder Name)
function getFolderByName($driveService, $folderName, $parentFolderId = null)
{
    $query = "name = '$folderName'";
    if ($parentFolderId) {
    $query .= " and '$parentFolderId' in parents";
    }
    $response = $driveService->files->listFiles([
        'q' => $query,
        'fields' => 'files(id)'
    ]);
    if (count($response->files) > 0) {
        return $response->files[0];
    } else {
        return null;
    }
}

(Get File Name)
function getFileByName($driveService, $fileName, $folderId = null)
{
    try {
        $params = [
            'q' => "name='$fileName'",
        ];

        if ($folderId) {
            $params['q'] .= " and '$folderId' in parents";
        }

        $results = $driveService->files->listFiles($params);

        if (count($results->getFiles()) > 0) {
            return $results->getFiles()[0];
        } else {
            return null; // File not found
        }
    } catch (Exception $e) {
        return null; // Error occurred
    }
}

(Delet File If Already Exists)
function deleteFile($driveService, $fileId)
{
    try {
        $driveService->files->delete($fileId);
        return $fileId;
    } catch (Exception $ex) {
        echo "Error deleting file: " . $ex->getMessage();
        return null;
    }
}

(Upload File to Drive)
function uploadFile($driveService, $file, $fileName, $folderId = null)
{
    $filePath = $file['tmp_name'];
    $mimeType = mime_content_type($filePath);
    $fileMetadata = new DriveDriveFile([
        'name' => $fileName,
        'parents' => [$folderId]
    ]);
    // $fileMetadata = new DriveDriveFile([
    //     'name' => $fileName,
    // ]);

    // if ($folderId) {
    //     $fileMetadata->setParents([$folderId]);
    // }
    $content = file_get_contents($filePath);
    $file = $driveService->files->create(
        $fileMetadata,
        array(
            'data' => $content, // Removed the square brackets
            'mimeType' => $mimeType,
            'uploadType' => 'multipart',
            'fields' => 'id'
        )
    );
    return $file->id;
}

(Create Folder If not exists)
function createFolder($driveService, $folderName, $parentFolderId = null)
{
    // Check if the folder already exists
    $existingFolder = getFolderByName($driveService, $folderName, $parentFolderId);

    if ($existingFolder) {
        return $existingFolder->id;
    }
    $folderMetadata = new DriveDriveFile([
        'name' => $folderName,
        'mimeType' => 'application/vnd.google-apps.folder'
    ]);

    if ($parentFolderId) {
        $folderMetadata->setParents([$parentFolderId]);
    }

    $folder = $driveService->files->create($folderMetadata, [
        'fields' => 'id'
    ]);

    return $folder->id;
}

I want to fix the Time it is taking while uploading file to drive.
I’ve tested it on each part one by one, It is taking 9 seconds to uploadFile($driveService, $file, $fileName, $folderId = null) only,, For the first time when no folder is created on drive its creates folder and save file , from here problem starts where it takes that much time

how to insert xml sub-category in php

In adding an xml product feed to my site, I would also like to include the images.

This is how the xml shows the image:

 <images>
 <image>
 <size>
 <![CDATA[ large ]]>
 </size>
 <tag>
 <![CDATA[ default ]]>
 </tag>
 <type>
 <![CDATA[ Default image for the product ]]>
 </type>
 <location>
 <![CDATA[ https://www.website.com/image.jpeg ]]>
 </location>
 </image>
 </images>

This is the code I have so far:

 <?php
 $xml_data = simplexml_load_file("https://website.com/file.xml")
 or die("Error: Object Creation failure");
 foreach ($xml_data->children() as $data)
 {
     if (str_contains($data->category, 'shampoo')) {
      echo "<div class='col-md-4'>";
        echo "<div class='item-xml'>";
            echo "<div class='title-xml'>$data->title</div>";
            echo "<div class='image-xml'><img src='$data->images'></div>";
            echo "<div class='price-xml'>€ $data->price</div>";
            echo "<a href='$data->link' target='_blank'><div class='link-xml'></div></a>";
        echo "</div>";
    echo "</div>";
     }
 }
 ?>

I tried changing this line

            echo "<div class='image-xml'><img src='$data->images'></div>";

into this

 echo "<div class='image-xml'><img src='(array_values($data->images[0]->location))'></div>";

and this (“.” instead of “->”)

 echo "<div class='image-xml'><img src='(array_values($data->images[0].location))'></div>";

But none works.
How can I get to the path of the image url, please?

My Word Press website does not open in laptop mode, its CSS

[enter image description here](https://i.stack.imgur.com/4v9c1.png)

these are website images

When the screen is small (the size of a mobile phone), everything is displayed correctly, and if I enlarge the screen in the same mode (the original size of the computer), everything is still correct, but when I refresh the page in the laptop mode, it seems that the CSS of the site is not loaded

To better understand the problem, see the photos on the site

An uncaught Exception was encountered Type: TypeError Message: Cannot access offset of type string on string

controller code

 public function edit($increment_name) {
        $this->load->model("RequestModel");
     
        $request_data['request'] = $this->RequestModel->editRequest($increment_name);
        
        // Debug the contents of $request_data['request']
        //var_dump($request_data);
        $this->load->view('components/layout');
        $this->load->view('client/edit', $request_data);
       
       
    }

Model code

 public function editRequest($increment_name) {
        $request_query = $this->db->get_where('tblrequest', ['increment_name' => $increment_name]);
    
        $request_data = $request_query->row_array();
        return $request_data;
    }

view code

<?php foreach ($request as $item): ?>
            <li class="list-group-item d-flex justify-content-between" style="margin-top: 20px;">
                <input type="text" class="inputstylenum" name="item_name[]" value="<?= $item['item_name'] ?>" placeholder="Item name" required>
                <input type="number" name="stock_quantity[]" value="<?= $request['stock_quantity']; ?>>" class="inputstylenum" required>
                <input type="number" name="available_quantity[]" value="<?php echo $item['available_quantity']; ?>" class="inputstylenum" required>
                <button type="button" class="remove-btn btn btn-danger">Remove</button>
            </li>
        <?php endforeach; ?>

I want to show the data there are multiple products with the same increment_name. I want to show all items using this loop. am using the CodeIgniter framework.

Trouble with routings and Ajax: Error 404

I’ve been assigned at work with doing some stuff to an already existing webpage, and one of them is implementing more searchbars based on one already there. I have copied almost everything, but for some reason, I end up with error 404 once I try to make said search.

I’ll post now all snippets of code related to the search I’m creating (searchActByEntity) and the one I’m taking as reference (searchActByDate):

web.php

Route::get("searchActByDate", [ActivityController::class, 'searchActByDate']);
Route::get("searchActByEntity", [ActivityController::class, 'searchActByEntity']);

ActivityController.php

public function searchActByDate(Request $request){

        if($request->ajax()) {
            $query = $request->get('searchActivity');
            $activityTypes = TypeActivity::all();
            if(empty($query)) {
                $activities=Activity::orderBy('dateAct', 'desc')
                ->whereDate('dateAct', '<', date('Y-m-d'))
                ->get();
            } else {
                $activities=Activity::orderBy('dateAct', 'desc')
                ->whereDate('dateAct', '<', date('Y-m-d'))
                ->where('dateAct', 'like', '%'.$request->searchActivity.'%')
                ->orwhere('nameAct','like','%'.$request->searchActivity.'%')
                ->get();
            }

            $total = $activities->count();

            $html = view('dashboard.partials.itemListActivity', [
                'activities' => $activities,
                'activityTypes' => $activityTypes,
            ])->render();

            return response()->json([
                'success' => true,
                'html' => $html,
                'total' => $total,
            ], 200);
        }else{
            return response()->json([
                'success' => false,
                'message' => "Something went wrong!",
            ], 403);
        }

    }

    public function searchActByEntity(Request $request) {
        if($request->ajax()) {
            $query = $request->get('searchEntity');
            $activityTypes = TypeActivity::all();
            if(empty($query)) {
                $activities=Activity::orderBy('dateAct', 'desc')
                ->get();
            } else {
                $activities=Activity::orderBy('dateAct', 'desc')
                ->where('entityAct', 'like', '%'.$request->searchEntity.'%')
                ->get();
            }

            $total = $activities->count();

            $html = view('dashboard.partials.itemListActivity', [
                'activities' => $activities,
                'activityTypes' => $activityTypes,
            ])->render();

            return response()->json([
                'success' => true,
                'html' => $html,
                'total' => $total,
            ], 200);
        }else{
            return response()->json([
                'success' => false,
                'message' => "Something went wrong!",
            ], 403);
        }
    }

showAllActivities.blade.php (where the code executes), inside document.ready

function ajaxAntiguas(datos){
            return $.ajax({
                url:"searchActByDate",
                type:"GET",
                data:{'searchActivity':datos},
                success:function(data){
                    $('#search_listAct').html(data.html);

                }
            })
        }
function ajaxEntity(datos) {
            return $.ajax({
                url: "searchActByEntity",
                type: "GET",
                data:{'searchEntity':datos},
                success:function(data){
                    $('#search_listAct').html(data.html);
                }
            })
        }
$("#searchEntity").on('keyup', function() {
                var query = $(this).val();
                ajaxEntity(query);
            });
$('#searchActivity').on('keyup', function(){

                var query = $(this).val();

                if($('#button-past-act').hasClass('seleccionado')){
                    ajaxAntiguas(query);
                }else if($('#button-nulled-act').hasClass('seleccionado')){
                    ajaxNulas(query);
                }else if($('#button-avaliable-act').hasClass('seleccionado')){
                    ajaxDisponibles(query);
                } else {
                    ajaxCall(query);
                }

            });

As you can see, the other is part of a bigger thing, but I don’t think that’s part of the issue. Anything else you need to see, let me know, cause I’m stumped. Thanks in advance!

I can’t perform uploading file using PHP [closed]

So there, my formpost.php this is for submitting the form to the database:

<?php
// Database connection

$conn = new mysqli($servername, $username, $password, $dbname);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

error_reporting(E_ALL);
ini_set('display_errors', 1);

if (isset($_FILES["fileUpload"]) && $_FILES["fileUpload"]["error"] == 0) {

// Function to safely handle user input
function sanitizeInput($data) {
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    return $data;
}

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Sanitize user inputs
    $formTitle = sanitizeInput($_POST["formTitle"]);
    $formDescription = sanitizeInput($_POST["formDescription"]);

    // Check if a file was uploaded
    if (isset($_FILES["fileUpload"]) && $_FILES["fileUpload"]["error"] == 0) {
        $file_name = $_FILES["fileUpload"]["name"];
        $file_tmp = $_FILES["fileUpload"]["tmp_name"];

        // Move the uploaded file to a desired location
        $upload_dir = "uploads/";
        $target_file = $upload_dir . basename($file_name);

        if (move_uploaded_file($file_tmp, $target_file)) {
            // File uploaded successfully, insert data into the database
            $sql = "INSERT INTO your_table_name (Title, Description, FilePath) VALUES (?, ?, ?)";
            $stmt = $conn->prepare($sql);
            $stmt->bind_param("sss", $formTitle, $formDescription, $target_file);

            if ($stmt->execute()) {
                echo "Form data and file uploaded successfully!";
            } else {
                echo "Error inserting data into the database: " . $stmt->error;
            }
        } else {
            echo "Error uploading file.";
        }
    } else {
        echo "File upload failed.";
    }

    // Close the database connection
    $conn->close();
}
?>

and then its always shown HTTP 500 Error, ChatGPT said it was about file_uplouds permission, and its already set to ‘on’ on the PHP Configuration

So, please give me a solution for this, because it always said error as a result

Facing EC2 high CPU utilization while sending Bulk Notifications

I’m using Aws SQS with my Laravel project in which when membership owner create a post in memebership I’m sening Twilio SMS, Email and Firebase push Notifications to all the subscriber of that membership. I’m using Laravel Queue Job to send this notifications. The issue is one membership has 5000+ subscribers so it becomes 15000+ notifications so when my server is processing this requests CPU utilization is going 99% for short period of time and users are getting 500 internal server error from nginx.

Post Creation Queue Dispatch

$membershipSubscriberIdsChunk = $membershipSubscriber->pluck("id")->chunk(30)->toArray();

                    foreach ($membershipSubscriberIdsChunk as $key => $chunk) {
                        dispatch(new SendPostMailNotificationJob($chunk, $mailPost, $membershipTitle, 0))->onQueue("post-email");
                        dispatch(new SendPostPushNotificationJob($chunk, $mailPost->user->name))->onQueue("post-firebase");
                        dispatch(new SendPostSMSNotificationJob($chunk, $mailPost->user->name))->onQueue("post-sms");
                    }

Twilio SMS

$recipients = $fans->filter(function ($item) {
                if ($item->receive_sms && isset($item->phone) && $item->phone) {
                    $countrycode = $item->country_code ?? '+1';
                    $phone = preg_replace("/[^0-9]/", "", $item->phone);
                    $phone = substr($phone, -10);
                    if ($phone) {
                        $item->phoneNumber = $countrycode . $phone;
                        return $item;
                    }
                }
            })->pluck("phoneNumber")->toArray();

            $message = "$this->creatorName has added a new post.";
            $messageOptions = [
                'from' => config('services.twilio.from_number'),
                'body' => $message,
            ];
            Log::channel("post_sms")->info("Twilio SMS Notification Process Start at " . Carbon::now()->format("Y-m-d H:i:s"));
            $twilio = new Client(config('services.twilio.sid'), config('services.twilio.auth_token'));
            foreach ($recipients as $key => $recipient) {
                try {
                    Log::channel("post_sms")->info("$key SMS Start");
                    $twilioResponse = $twilio->messages->create($recipient, $messageOptions);
                    Log::channel("post_sms")->info("$key [$recipient] SMS Done.");
                } catch (Exception $e) {
                    Log::channel("post_sms")->error("$recipient has an error." . $e->getMessage());
                }
            }
            Log::channel("post_sms")->info("Twilio SMS Notification Process Completed at " . Carbon::now()->format("Y-m-d H:i:s") . ".n");

            return response()->json([
                "message" => "Sent Request to Twilio."
            ]);

Firebase Push Notification

$subscribers = MembershipSubscriber::with(["fan"])->whereIn("id", $this->membershipSubscriber)->get();
        Log::channel('post_firebase')->info("Firebase Notification Process Start at " . Carbon::now()->format("Y-m-d H:i:s"));
        $message = $this->creatorName . " has added a new post.";
        $title = "New Post Added";

        if ($subscribers->count()) {
            foreach ($subscribers as $key => $subscriber) {
                if (isset($subscriber->fan) && isset($subscriber->fan->apn_token) && $subscriber->fan->apn_token != "") {
                    $optionBuilder = new OptionsBuilder();
                    $optionBuilder->setTimeToLive(60 * 20);

                    $notificationBuilder = new PayloadNotificationBuilder($title);
                    $notificationBuilder->setBody($message)->setSound('default');

                    $dataBuilder = new PayloadDataBuilder();
                    $dataBuilder->addData(['subscriber_id' => $subscriber->id, 'type' => 'post']);

                    $option = $optionBuilder->build();
                    $notification = $notificationBuilder->build();
                    $data = $dataBuilder->build();

                    $token = $subscriber->fan->apn_token;
                    $downstreamResponse = FCM::sendTo($token, $option, $notification, $data);
                    $responseData = [
                        "numberSuccess" => $downstreamResponse->numberSuccess(),
                        "numberFailure" => $downstreamResponse->numberFailure(),
                        "numberModification" => $downstreamResponse->numberModification(),
                    ];
                    Log::channel('post_firebase')->info("response for token.", $responseData);
                }
            }
            Log::channel('post_firebase')->info("Firebase Notification Process Completed at " . Carbon::now()->format("Y-m-d H:i:s") . "n");
            return response()->json([
                "message" => "Push Notifications sent successfully"
            strong text]);
               

Email

$fans = MembershipSubscriber::with(["fan"])->whereIn("id", $this->membershipSubscriber)->get()->pluck("fan");
        $fans = $fans->where("receive_email", 1);
        if ($fans->count()) {
            Log::channel('post_mail')->info("Mail Notification Main Job Start at " . Carbon::now()->format("Y-m-d H:i:s"));
            Notification::send($fans, (new PostCreatedEmailNotification($this->membershipPost, $this->membershipTitle, $this->jobDelay)));
            Log::channel('post_mail')->info("Mail Notification Main Job Completed at " . Carbon::now()->format("Y-m-d H:i:s") . ".n");
        } else {
            Log::channel('post_mail')->error("Mail Notification Fan User Not Found.");
        }

prevent user to see video in url

I am working on a project for video tutorials like udemy. I encountered a problem that when the user clicks on the video link and copy in the URL field of browser, the video is shown to the browser even if he does not have a subscription. What is the way to prevent this issue?
for example if user has this link http://127.0.0.1:8000/storage/uploads/course_videos_2023-09/16950266052987331_first.mp4 and copy in URL field he can see the video

i try to make a middleware but it doesn’t fix my problem