What is a recommended design pattern for processing data from an API response in Yii2?

My Yii2 application (in PHP 7, so unfortunately I do not have strict types) receives from an API call responses which should be nested arrays looking like:

$response = [
  'session' => [
     'userData' => ['user_id' => 232, ...],
     'sessionData => ['status' => 'ONGOING', 'details' => 'Some details here...', ...],
     'additionalData' => [...]
  ]
]

Currently in my application logic, when I receive the response I manually check that each field exists and is of the required type. So for example I start by checking that $response['session'] exists and is an array, and I throw an exception if it doesn’t, so something like:

if (!array_key_exists($response, 'session')) {
    throw new Exception('Invalid response: missing "session" key in response array.');
}
if (!is_array($response['session'])) {
   throw new Exception('Invalid response: "session" is not an array in response array.');
}

Then I check for $response['session']['userData'] and I check that it’s an array, and so on. When I am certain that $response['session']['userData']['user_id'] exists, I also check that it is an integer, so I also do validation for the primitive received types.

I would like to decouple this logic from my main application, by having a separate model which stores all the primitive properties I want from the response and validates the primitive ones.

My problem is that I’m uncertain what would be the best design pattern to implement this.

My initial thought was to build a DTO-Hydrator-like pattern, so:

  1. A model (DTO) having as fields only the ‘primitive’ properties such as user_id, status, details, etc, but not the arrays like session, userData. This model would only be responsible for validation of the primitive fields (so checking that user_id is an integer for instance, checking that ‘status’ is in an array of admissible statuses, etc.)
  2. A Hydrator model which is responsible for checking that all desired
    primitive fields exist, and of course, that everything ‘in-between’
    exists, and then loading the primitive fields into the DTO.

However, this approach seems overly complicated. For one thing, I would have to instantiate both the DTO and the Hydrator each time I have to handle a response in my application logic, which would still make that logic too cumbersome for what I want. Ideally I would like to only do something like
$model->process($response)
in my application logic, but in a way that is also an endorsed design pattern. So is there a way to do this without the (seeming) overcomplication of the DTO-Hydrator pattern?

Drupal config sync but database drifting, how to automate ‘database migration’?

I am using drupal11.

Specifically, I am using the paragrpahs module where on fresh install of the module it will create the module related entity tables in the database. Then I export my config settings and save/commit. However, on a fresh install of my repo when I use drush config import to sync the configs, I get an error that the paragraph entity tables do not exist. I can fix this if I manually fix the database schema (drifting behind the code config) with a drupal drush entity update module. But, I dont want to have to manually check which tables are missing and manually input them. How to fix this issue? In a non drupal app I usually have a database migration tool to track all database schema changes.

Docker does not download the specified image

Docker-Compose is not downloading the specific version of PHP that I want. I want the version “php:8.4.5-fpm” and it only downloads the “latest” version. I tried several things, but I can’t get it to download the specific image, it only downloads the “latest” image.

docker-compose.yml

version: "3.9"

services:
  nginx:
    build:
      context: ../nginx  # Caminho para a pasta Nginx (relativo à pasta docker-compose)
    ports:
      - "80:80"
    volumes:
      - ../app:/var/www/html  # Monta a pasta app como /var/www/html (relativo à pasta docker-compose)
    depends_on:
      - php
    networks:
      - laravel-network

  php:
    build:
      context: ../php  # Caminho para a pasta PHP (relativo à pasta docker-compose)
    expose:
      - 9000
    volumes:
      - ../app:/var/www/html  # Monta a pasta app como /var/www/html (relativo à pasta docker-compose)
    depends_on:
      - db
    networks:
      - laravel-network

  db:
    image: mariadb:11.7.2
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: laravel
      MYSQL_USER: laravel
      MYSQL_PASSWORD: laravel
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - laravel-network

  phpmyadmin:
    image: phpmyadmin:latest
    ports:
      - "8080:80"
    environment:
      PMA_HOST: db
      MYSQL_ROOT_PASSWORD: root
    depends_on:
      - db
    networks:
      - laravel-network

volumes:
  db_data:

networks:
  laravel-network:
    driver: bridge

Dockerfile PHP

FROM php:8.4.5-fpm

# Definir diretório de trabalho
WORKDIR /var/www/html

# Instalar dependências do sistema
RUN apt-get update && apt-get install -y 
    build-essential 
    libpng-dev 
    libjpeg62-turbo-dev 
    libfreetype6-dev 
    locales 
    zip 
    unzip 
    git 
    curl 
    libzip-dev 
    libonig-dev 
    libxml2-dev 
    && apt-get clean && rm -rf /var/lib/apt/lists/*

# Instalar extensões PHP necessárias para o Laravel
RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl soap
RUN docker-php-ext-configure gd --with-freetype --with-jpeg
RUN docker-php-ext-install gd

# Instalar o Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Criar usuário para a aplicação Laravel
RUN groupadd -g 1000 www && useradd -u 1000 -ms /bin/bash -g www www

# Copiar o código da aplicação
COPY --chown=www:www . /var/www/html

# Alterar usuário
USER www

# Expor a porta 9000 para o PHP-FPM
EXPOSE 9000

CMD ["php-fpm"]

Dockerfile Nginx

FROM nginx:1.27.3

# Copiar a configuração do Nginx
COPY default.conf /etc/nginx/conf.d/default.conf

Opencart how can i remove query in seo link

<?php
namespace OpencartCatalogControllerStartup;
/**
 * Class SeoUrl
 *
 * @package OpencartCatalogControllerStartup
 */
class SeoUrl extends OpencartSystemEngineController {
    /**
     * @return void
     */
    public function index(): void {
        if ($this->config->get('config_seo_url')) {
            $this->url->addRewrite($this);
    
            $this->load->model('design/seo_url');
    
            if (isset($this->request->get['_route_'])) {
                $parts = explode('/', $this->request->get['_route_']);
    
                // remove any empty arrays from trailing
                if (oc_strlen(end($parts)) == 0) {
                    array_pop($parts);
                }
    
                foreach ($parts as $part) {
                    $seo_url_info = $this->model_design_seo_url->getSeoUrlByKeyword($part);
    
                    if ($seo_url_info) {
                        $this->request->get[$seo_url_info['key']] = html_entity_decode($seo_url_info['value'], ENT_QUOTES, 'UTF-8');
                    }
                }
            }
        }
    }
    

    /**
     * @param string $link
     *
     * @return string
     */
    public function rewrite(string $link): string {
        $url_info = parse_url(str_replace('&amp;', '&', $link));
    
        $url = $url_info['scheme'] . '://' . $url_info['host'];
    
        if (isset($url_info['port'])) {
            $url .= ':' . $url_info['port'];
        }
    
        parse_str($url_info['query'], $query);
    
        $this->load->model('design/seo_url');
    
        $paths = [];
    
        // Dil parametresini sakla
        $language = '';
        if (isset($query['language'])) {
            $language = $query['language'];
            unset($query['language']);
        }
    
        // Eğer route varsa ilk olarak onu işleyelim
        if (isset($query['route'])) {
            $route = $query['route'];
    
            $result = $this->model_design_seo_url->getSeoUrlByKeyValue('route', $route);
    
            if ($result) {
                $paths[] = $result;
                unset($query['route']);
            }
        }
    
        // Diğer parametreleri işle (product_id, search vs.)
        foreach ($query as $key => $value) {
            $result = $this->model_design_seo_url->getSeoUrlByKeyValue((string)$key, (string)$value);
    
            if ($result) {
                $paths[] = $result;
                unset($query[$key]);
            }
        }
    
        // Sıralama
        usort($paths, fn($a, $b) => $a['sort_order'] <=> $b['sort_order']);
    
        $url .= str_replace('/index.php', '', $url_info['path']);
    
        foreach ($paths as $result) {
            $url .= '/' . $result['keyword'];
        }
    
        // Dil parametresini ekle
        if ($language) {
            $query['language'] = $language;
        }
    
        // Kalan query'leri ekle
        if ($query) {
            $url .= '?' . http_build_query($query);
        }
    
        return $url;
    }
}
##
# READ THIS COMPLETELY IF YOU CHOOSE TO USE THIS FILE!
#
# 1.To use URL Alias you need to be running apache with mod_rewrite enabled.
# 2. In your opencart directory rename .htaccess.txt (this file) to .htaccess
#
# For any support issues please visit: https://www.opencart.com
#
# The line 'Options +FollowSymLinks' may cause problems with some server configurations.
# It is required for the use of Apache mod_rewrite, but it may have already been set by
# your server administrator in a way that disallows changing it in this .htaccess file.
# If you encounter problems (e.g. site is not loading), comment out this line by adding a # in front
# FLOC is a feature suggested by Google, if this header shall not be set, disable the line
# having 'interest-cohort' by adding a # in front
##

## No directory listings
<IfModule mod_autoindex.c>
  IndexIgnore *
</IfModule>

## No-Referrer-Header
<IfModule mod_headers.c>
  Header set Referrer-Policy "no-referrer"
</IfModule>

## Suppress mime type detection in browsers for unknown types and prevent FLOC
<IfModule mod_headers.c>
  Header always set X-Content-Type-Options "nosniff"
  Header always set Permissions-Policy "interest-cohort=()"
</IfModule>

## Can be commented out if causes errors, see notes above.
Options +FollowSymlinks

## Prevent Directory listing
Options -Indexes

## Prevent Direct Access to files
<FilesMatch "(?i)((.tpl|.twig|.ini|.log|(?<!robots).txt))">
 Require all denied
## For apache 2.2 and older, replace "Require all denied" with these two lines :
# Order deny,allow
# Deny from all
</FilesMatch>

## SEO URL Settings
RewriteEngine On
## If your opencart installation does not run on the main web folder make sure you folder it does run in ie. / becomes /shop/
RewriteBase /upload/
## Rewrite Rules
RewriteRule ^system/storage/(.*) index.php?route=error/not_found [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !.*.(ico|gif|jpg|jpeg|png|webp|js|css|svg)
RewriteRule ^(.*)$ index.php?_route_=$1 [L,QSA]

## Optional error documents
#ErrorDocument 400 /index.php?route=error/not_found
#ErrorDocument 401 /index.php?route=error/permission
#ErrorDocument 403 /index.php?route=error/not_found
#ErrorDocument 404 /index.php?route=error/not_found
#ErrorDocument 500 /index.php?route=error/not_found
#ErrorDocument 503 /index.php?route=error/not_found

## Additional Settings that may need to be enabled for some servers
## Uncomment the commands by removing the # sign in front of it.
## If you get an "Internal Server Error 500" after enabling any of the following settings, restore the # as this means your host doesn't allow that.

# 1. If your cart only allows you to add one item at a time, it is possible register_globals is on. This may work to disable it:
# php_flag register_globals off

# 2. If your cart has magic quotes enabled, This may work to disable it:
# php_flag magic_quotes_gpc Off

# 3. Set max upload file size. Most hosts will limit this and not allow it to be overridden but you can try
# php_value upload_max_filesize 999M

# 4. set max post size. uncomment this line if you have a lot of product options or are getting errors where forms are not saving all fields
# php_value post_max_size 999M

# 5. set max time script can take. uncomment this line if you have a lot of product options or are getting errors where forms are not saving all fields
# php_value max_execution_time 200

# 6. set max time for input to be recieved. Uncomment this line if you have a lot of product options or are getting errors where forms are not saving all fields
# php_value max_input_time 200

# 7. disable open_basedir limitations
# php_admin_value open_basedir none

when i activate seo urls on admin panel. http://localhost/upload/koltuk-takimlari?route=product%2Fcategory always links coming this type. but i want to remove this part from url ?route=product%2Fcategory . I tried to ask gpt and claude and cursor but it didnt work . please help me

I tried to ask chatgpt but it didnt work

after form submission 404 error coming in wordpress

Hi I have created a form function code inside a theme functions.php file
my file is https://example.com/counsellor-registration/
which is showing html layout of form when i open this link .
problem is that after submitting form 404 error coming on same page

my code is

function custom_counsellor_registration_form() {
ob_start();
$form_action = esc_url(trailingslashit(get_permalink()));
error_log('Counsellor Form Action URL: ' . $form_action);

if (isset($_POST['counsellor_registration_submit'])) {
    error_log('Counsellor Form Submitted. POST Data: ' . print_r($_POST, true));
    $name = sanitize_text_field($_POST['name']);
    $designation = sanitize_text_field($_POST['designation']);
    $qualification = sanitize_text_field($_POST['qualification']);
    $time_slots = isset($_POST['time_slots']) ? array_map('sanitize_text_field', $_POST['time_slots']) : array();
    $specification = sanitize_textarea_field($_POST['specification']);
    $username = sanitize_text_field($_POST['username']);
    $email = sanitize_email($_POST['email']);
    $password = $_POST['password'];
    $agreement = isset($_POST['agreement']) ? 1 : 0;

    $errors = [];
    if (empty($username) || empty($email) || empty($password)) {
        $errors[] = "Username, email, and password are required.";
    }
    if (!is_email($email)) {
        $errors[] = "Please enter a valid email address.";
    }
    if (strlen($password) < 6) {
        $errors[] = "Password must be at least 6 characters long.";
    }

    if (empty($errors) && $agreement) {
        $user_id = wp_create_user($username, $password, $email);
        if (!is_wp_error($user_id)) {
            wp_update_user(array('ID' => $user_id, 'role' => 'counsellor'));
            update_user_meta($user_id, 'name', $name);
            update_user_meta($user_id, 'designation', $designation);
            update_user_meta($user_id, 'qualification', $qualification);
            update_user_meta($user_id, 'time_slots', $time_slots);
            update_user_meta($user_id, 'specification', $specification);
            wp_redirect(wp_login_url() . '?registration=success');
            exit;
        } else {
            error_log('Counsellor Registration Error: ' . $user_id->get_error_message());
            $errors[] = $user_id->get_error_message();
        }
    }

    if (!empty($errors)) {
        echo '<div class="message" style="color:red;">';
        foreach ($errors as $error) {
            echo '<p>' . esc_html($error) . '</p>';
        }
        echo '</div>';
    } else if (!$agreement) {
        echo '<p class="message" style="color:red;">Please agree to the terms to proceed.</p>';
    }
}
?>
<div class="registration-form">
    <h2>Counsellor Registration</h2>
   <form action="" enctype="multipart/form-data" method="POST">
        <p>
            <label for="name">Name:</label><br>
            
          
            <input type="text" name="name" id="name" value="<?php echo isset($_POST['name']) ? esc_attr($_POST['name']) : ''; ?>" required>
        </p>
        <p>
            <label for="designation">Designation:</label><br>
            <input type="text" name="designation" id="designation" value="<?php echo isset($_POST['designation']) ? esc_attr($_POST['designation']) : ''; ?>" required>
        </p>
        <p>
            <label for="qualification">Qualification:</label><br>
            <input type="text" name="qualification" id="qualification" value="<?php echo isset($_POST['qualification']) ? esc_attr($_POST['qualification']) : ''; ?>" required>
        </p>
        <p>
            <label>Time slot comfortable for you:</label><br>
            <div class="time-slot">
                <input type="checkbox" name="time_slots[]" value="9 AM - 12 PM" <?php echo isset($_POST['time_slots']) && in_array('9 AM - 12 PM', $_POST['time_slots']) ? 'checked' : ''; ?>> 9 AM - 12 PM<br>
                <input type="checkbox" name="time_slots[]" value="12 PM - 3 PM" <?php echo isset($_POST['time_slots']) && in_array('12 PM - 3 PM', $_POST['time_slots']) ? 'checked' : ''; ?>> 12 PM - 3 PM<br>
                <input type="checkbox" name="time_slots[]" value="3 PM - 6 PM" <?php echo isset($_POST['time_slots']) && in_array('3 PM - 6 PM', $_POST['time_slots']) ? 'checked' : ''; ?>> 3 PM - 6 PM<br>
                <input type="checkbox" name="time_slots[]" value="6 PM - 9 PM" <?php echo isset($_POST['time_slots']) && in_array('6 PM - 9 PM', $_POST['time_slots']) ? 'checked' : ''; ?>> 6 PM - 9 PM<br>
            </div>
        </p>
        <p>
            <label for="specification">Any specification:</label><br>
            <textarea name="specification" id="specification"><?php echo isset($_POST['specification']) ? esc_textarea($_POST['specification']) : ''; ?></textarea>
        </p>
        <p>
            <label for="username">Username:</label><br>
            <input type="text" name="username" id="username" value="<?php echo isset($_POST['username']) ? esc_attr($_POST['username']) : ''; ?>" required>
        </p>
        <p>
            <label for="email">Email ID:</label><br>
            <input type="email" name="email" id="email" value="<?php echo isset($_POST['email']) ? esc_attr($_POST['email']) : ''; ?>" required>
        </p>
        <p>
            <label for="password">Password:</label><br>
            <input type="password" name="password" id="password" required>
        </p>
        <p>
            <input type="checkbox" name="agreement" id="agreement" required <?php echo isset($_POST['agreement']) ? 'checked' : ''; ?>>
            <label for="agreement">I agree all the details given above are true to the best of my knowledge</label>
        </p>
        <p>
            <input type="submit" name="counsellor_registration_submit" value="Register">
        </p>
    </form>
</div>
<?php
return ob_get_clean();
}

    add_shortcode('custom_counsellor_registration', 'custom_counsellor_registration_form');

I have also tried with <form method="post" action="<?php echo esc_url(trailingslashit(get_permalink())); ?>">

when I submit form my headers shows

scheme
    https
host
    example.com
filename
    /counsellor-registration/
Status
200

my request goes

------geckoformboundarya1c41156493fa0c19c973b6717e255d9
Content-Disposition: form-data; name="name"

testing name
------geckoformboundarya1c41156493fa0c19c973b6717e255d9
Content-Disposition: form-data; name="designation"

MD
------geckoformboundarya1c41156493fa0c19c973b6717e255d9
Content-Disposition: form-data; name="qualification"

MBBS
------geckoformboundarya1c41156493fa0c19c973b6717e255d9
Content-Disposition: form-data; name="time_slots[]"

12 PM - 3 PM
------geckoformboundarya1c41156493fa0c19c973b6717e255d9
Content-Disposition: form-data; name="specification"

klklkl
------geckoformboundarya1c41156493fa0c19c973b6717e255d9
Content-Disposition: form-data; name="username"

counc01
------geckoformboundarya1c41156493fa0c19c973b6717e255d9
Content-Disposition: form-data; name="email"

[email protected]
------geckoformboundarya1c41156493fa0c19c973b6717e255d9
Content-Disposition: form-data; name="password"

123456
------geckoformboundarya1c41156493fa0c19c973b6717e255d9
Content-Disposition: form-data; name="agreement"

on
------geckoformboundarya1c41156493fa0c19c973b6717e255d9
Content-Disposition: form-data; name="counsellor_registration_submit"

Register
------geckoformboundarya1c41156493fa0c19c973b6717e255d9--

Unable to update image name in MySQL database

I am trying to update an image in MySQL database but each time I do try to update, other fields (i.e. location) of the is updated but the image name becomes blank.
Below is the code for updating:

if(isset($_POST['edt_Pic']))
{
    
    $id         = mysqli_real_escape_string($con, $_POST["id"]);
    $file       = mysqli_real_escape_string($con, $_POST['file']);
    $fullname   = mysqli_real_escape_string($con, $_POST['fullname']);
    $filename   = $_FILES['file']['name'];
    $file_temp  = $_FILES['file']['tmp_name'];
    $file_size  = $_FILES['file']['size'];
    
    if($file_size > 1048576)
            {
                echo "<script type='text/javascript'>alert('Attached photo exceeds 1Mb. Kindly reduce the size.');
                        </script>";
                echo "<script>window.location.href='users.php'</script>";
            }
            elseif(!empty($_FILES["file"]["tmp_name"]))
               {
                $exp    = explode(".", $file_name);
                $ext    = end($exp);
                $name   = $_FILES['file']['name'];
                
                move_uploaded_file($_FILES["file"]["tmp_name"],"./users/" . $name);
                
                $location   =   "./users/" . $name;
                
            $sql  = "UPDATE     users
                     SET        file = ?, location = ?, fullname = ?
                     WHERE      id = ?";
            
            $stmt = mysqli_prepare($con, $sql);
              
              mysqli_stmt_bind_param($stmt, "sssi", $file, $location, $fullname, $id);
            
                if(mysqli_stmt_execute($stmt))
                    {
                        echo "<script type='text/javascript'>alert('Image for " . $fullname . " has updated successfully.');
                              </script>";
                        echo "<script>window.location.href='users.php'</script>";
                    } 
                        else                    
                    {
                    echo "<script type='text/javascript'>alert('Oops! Something went wrong. Please try again.');
                            </script>";
                    echo "<script>window.location.href='users.php'</script>";
                }
        }
                 
        mysqli_stmt_close($stmt);
}
mysqli_close($con);

I have tried to add the old file name input field but to no luck.

How to add the another disk folder and files in PHP in XAMPP [closed]

I am connecting the MS Access database with PHP.

My system us a server for XAMPP but the MS Access database is located in another system.

When I use the DSN system for the connection it works well but when I use the DSN-less system doesn’t work and it shows the following error:

32-bit to 64-bit error on DSN system

$conn = odbc_connect('SAP','','');
if($conn)
{ 
echo ""; 
}
else
{ echo "Failed";  }

That why I go for DSN-less system but it does not work outside the root folder.

My DSN system code

$db_username = ''; //username
$db_password = ''; //password


//path to database file
$database_path = realpath('temp.mdb');
print $database_path;
print "<br>";
$database = new PDO("odbc:DRIVER={Microsoft Access Driver (*.mdb, *.accdb)}; DBQ=$database_path; Uid=$db_username; Pwd=$db_password;");


$sql  = "SELECT * FROM Product ORDER BY PCode";
$result = $database->query($sql);
while ($row = $result->fetch()) {
    echo $row["PName"]."<br>";
}

Access drivers code instead of DSN-less system

DSN less Access driver code

In the code above the MS Access database works if it is located in server roor (e.g., C:/XAMPP/HTDOCS/)

I want to access the database in another drive or another computer.

php inheritance abstract class property [closed]

I have a question about inheritance in php 8.3.
I have an abstract class with a property, variable or what ever it must be called.
I then try to set this property/variable from a function in the abstract class. Then I get an error saying “Undefined variable”
I think that all conventions about OOP has been kept, what am I missing here?

<?php
abstract class grandparent{
    public function somefunction(){
    }
}

abstract class myparent extends grandparent{
    public $prop;
    protected function setfunction($myprop){
        $this->$prop = $myprop;
    }
}

class child extends myparent{
    public function myset() {
        $this->setfunction(42);
        $myvar = $this->prop;
    }
}

$myInstance = new child();
$myInstance->myset();

Automatically change user role after completed orders in WooCommerce

I’m using code that gives the user a new role after three orders.

The default user role is “Customer” and I have created an additional role “Regular Customer”.

/* Create a new role */
add_action('init', 'luckydoll_add_custom_user_role');
function luckydoll_add_custom_user_role() {
    add_role('regular_customer', __('Regular Customer', 'woocommerce'), array(
        'read' => true,
        'create_posts' => false,
    ));
}

/* Change user role after three orders */
function total_completed_orders( $the_user_id ) {
    global $wpdb;
    
    $count = $wpdb->get_var(
        // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
        "SELECT COUNT(*)
        FROM $wpdb->posts as posts
        LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
        WHERE   meta.meta_key = '_customer_user'
        AND     posts.post_type = 'shop_order'
        AND     posts.post_status = 'wc-completed'
        AND     meta_value = '" . esc_sql( $the_user_id ) . "'"
        // phpcs:enable
    );

    return $count;
}

add_action( 'woocommerce_order_status_completed', 'action_woocommerce_order_status_completed', 10, 1 );
function action_woocommerce_order_status_completed( $order_id ) {
    
    // User role in which the customer role must be changed
    $premium_user_role = 'regular_customer';
    
    // Spending min cash in one order
    $min_in_one_order = 400;
    
    // Change role after x completed orders
    $change_role_after_x_completed_orders = 3;
    
    $flag = false;
    
    // Get an instance of the WC_Order object
    $order = wc_get_order( $order_id );
    
    // Is a order
    if( is_a( $order, 'WC_Order' ) ) {
        // Get user ID or $order->get_customer_id();
        $user_id = $order->get_user_id();
        
        // Retrieve user meta field for a user. 
        $is_premium = get_user_meta( $user_id, '_customer_is_premium_member', true );
        
        // Is NOT a premium member
        if ( $is_premium != 1 ) {
            // Count total completed orders
            $total_completed_orders = total_completed_orders( $user_id );
            
            // Total completed orders greater than or equal to change role after x completed orders
            if ( $total_completed_orders >= $change_role_after_x_completed_orders ) {
                $flag = true;
            } else {
                // Get current order total
                $order_total = $order->get_total();
                
                // Order total greater than or equal to minimum in one order
                if ( $order_total >= $min_in_one_order ) {
                    $flag = true;
                }
            }
            
            // True, at least 1 condition has been met
            if ( $flag ) {
                // Get the user object
                $user = get_userdata( $user_id );

                // Get all the user roles as an array.
                $user_roles = $user->roles;
                
                // User role contains 'customer'
                if ( in_array( 'customer', $user_roles ) ) {
                    // Remove customer role
                    $user->remove_role( 'customer' );
                    
                    // Add premium role
                    $user->add_role( $premium_user_role );
                    
                    // Update user meta field based on user ID, set true
                    update_user_meta( $user_id, '_customer_is_premium_member', 1 );
                }
            }
        }
    }
}

When a registered user places three orders, their role automatically changes.

But if a guest makes an order and the manager sets his order to the “Done” status, a critical error appears. enter image description here

line 347: $user_roles = $user->roles;
line 350: if ( in_array( 'customer', $user_roles ) ) {

I can disable guest checkout. On the other hand, I can’t force guests to register on the site if they don’t want to.

How can this error be fixed? Is it possible to exclude guests from this custom code?

I get this error when I activate my WooCommerce Plugin:

thrown in /home/tenthspor/public_html/wp-content/plugins/woocommerce/packages/action-scheduler/classes/data-stores/ActionScheduler_DBLogger.php on line 29

PHP Warning: include(/home/tenthspor/public_html/wp-content/plugins/woocommerce/includes/admin/views/html-notice-update.php): Failed to open stream: No such file or directory in /home/tenthspor/public_html/wp-content/plugins/woocommerce/includes/admin/class-wc-admin-notices.php on line 400

PHP Warning: include(/home/tenthspor/public_html/wp-content/plugins/woocommerce/includes/admin/views/html-notice-update.php): Failed to open stream: No such file or directory in /home/tenthspor/public_html/wp-content/plugins/woocommerce/includes/admin/class-wc-admin-notices.php on line 400

PHP Warning: include(): Failed opening ‘/home/tenthspor/public_html/wp-content/plugins/woocommerce/includes/admin/views/html-notice-update.php’ for inclusion (include_path=’.:/opt/alt/php81/usr/share/pear:/opt/alt/php81/usr/share/php:/usr/share/pear:/usr/share/php’) in /home/tenthspor/public_html/wp-content/plugins/woocommerce/includes/admin/class-wc-admin-notices.php on line 400

PHP Warning: require(/home/tenthspor/public_html/wp-content/plugins/woocommerce/src/Internal/WCCom/ConnectionHelper.php): Failed to open stream: No such file or directory in /home/tenthspor/public_html/wp-content/plugins/woocommerce/vendor/jetpack-autoloader/class-php-autoloader.php on line 102

PHP Warning: require(/home/tenthspor/public_html/wp-content/plugins/woocommerce/src/Internal/WCCom/ConnectionHelper.php): Failed to open stream: No such file or directory in /home/tenthspor/public_html/wp-content/plugins/woocommerce/vendor/jetpack-autoloader/class-php-autoloader.php on line 102

PHP Fatal error: Uncaught Error: Failed opening required ‘/home/tenthspor/public_html/wp-content/plugins/woocommerce/src/Internal/WCCom/ConnectionHelper.php’ (include_path=’.:/opt/alt/php81/usr/share/pear:/opt/alt/php81/usr/share/php:/usr/share/pear:/usr/share/php’) in /home/tenthspor/public_html/wp-content/plugins/woocommerce/vendor/jetpack-autoloader/class-php-autoloader.php:102
Stack trace:

SEO freindly URLs [closed]

I have a PHP site that using the folllowing URL structure

example.com/search/category.php?=general

example.com/search/location.php?=london

I’d like to make them more SEO and aesthetically freindly by changing them to

example.com/search/general

example.com/search/bikes-for-sale-in-london

What’s the easiest way of doing this?

Thanks

Save order of custom entities in selection field

Let’s say I have two custom entities:

  • Dish
  • Ingredient

The entities have a many-to-many relation with extra field: ingredient_position:

#[ORMEntity]
class Dish
{
    #[ORMOneToMany(
        mappedBy: 'dish',
        targetEntity: DishIngredient::class,
        cascade: ['all'],
    )]
    private Collection $dishIngredients;
}

#[ORMEntity]
class Ingredient
{
    #[ORMOneToMany(
        mappedBy: 'ingredient',
        targetEntity: DishIngredient::class,
        cascade: ['all'],
    )]
    private Collection $dishIngredients;
}

#[ORMEntity]
class DishIngredient
{
    public function __construct(
        #[
            ORMManyToOne(
                targetEntity: Dish::class,
            ),
            ORMJoinColumn(nullable: false),
        ]
        private Dish $dish,
        #[
            ORMManyToOne(
                targetEntity: Ingredient::class,
            ),
            ORMJoinColumn(nullable: false),
        ]
        private Ingredient $ingredient,
        
        #[ORMColumn(type: Types::INTEGER)]
        private int $ingredientPosition = 0,
    ) {}
}

I’d like to be able to add existing Ingredients when adding/editing Dish but the ingredients have to be stored in the order I set in the admin form.

I tried to set up a ingredient_selection field in sulu_admin and it works, when I select ingredients and store them in the database, but when I load the Dish in the admin form, the ingredients don’t show up – Sulu tries to load ingredients from the ingredients’ endpoint: /admin/api/ingredients?locale=en&ids=9,10&page=1&flat=true: in that case the ids are the IDs of the DishIngredient entity, but I’m not able to load the ingredients.

(errno: 150 “Foreign key constraint is incorrectly formed “)”)

I am trying to create scheduleUser migration but this error is popping out although I am using the same standards I’ve been taught. I created another schema it gave me the same error. I made sure the relationships is written in a correct way still having the same error. I am using Laravel v.12.

This is the scheduleUser migration:

<?php

use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('scheduelusers', function (Blueprint $table) {
            
            $table->id();
            // $table->unsignedBigInteger('studentId')-> primary()->nullable() -> from(100000);
            $table -> string('firstName');
            $table -> string ('middleName');
            $table -> string ('lastName');
            $table -> string ('email')-> unique();
            $table -> string ('password');
            $table -> string ('phone')-> unique();
            $table -> foreignId('role_id')->constrained();
            
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('scheduelusers');
    }
};

This is the function I am using in scheduleusers migration for the relationship:

    public function role()
    {
        return $this->belongsTo(Role::class);
    }
    
}

This is the role migration:

<?php

use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('roles', function (Blueprint $table) {
            $table->id();
            $table -> string('role');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('roles');
    }
};

This is the function in role model for the relationship:

    public function scheduleusers()
    {
        return $this->hasMany(ScheduleUser::class);
    }
}

Laravel N+1 when accessing a pivot relationship and the related model (unit)

I got n+1 query while working with my models and pivot

Recipe.php:

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function ingredients(): BelongsToMany
    {
        return $this->belongsToMany(Ingredient::class)
            ->using(IngredientRecipe::class)
            ->withTimestamps()
            ->withPivot(['quantity', 'unit_id']);
    }

IngredientRecipe.php (Pivot):

    public function unit(): BelongsTo
    {
        return $this->belongsTo(Unit::class);
    }

Ingredient.php:

    public function recipes(): BelongsToMany
    {
        return $this->belongsToMany(Recipe::class);
    }

Unit.php:

    public function ingredient_recipes(): HasMany
    {
        return $this->hasMany(IngredientRecipe::class);
    }

What am I trying to do:

In my user-profile page I want to show a list of recipes for owner (user). Every recipe has ingredients() which are in pivot table with additionall columns quantity and unit_id

Code:

In my ProfileController.php I am using this code:

    public function show_profile(User $user)
    {
        $userRecipes = $user->recipes()->with('ingredients', 'guideSteps')->get();

        return view('user.user-profile', compact('user', 'userRecipes'));
    }

Problem:

Laravel doesn’t know that pivot->unit_id is related to the Unit model, so every I am accessing pivot->unit, it makes a separate query to the units table.

In debugbar I am getting 15 duplicated queries:

select * from users where users.id = 1 limit 1

select * from units where units.id = 3 limit 1

select * from units where units.id = 3 limit 1

… 12 more

And a problem is in this place:


   @foreach($userRecipes as $recipe)
       <x-recipe-card :recipe="$recipe"/>
   @endforeach

---------------inside component recipe-card:------------------------

        @foreach($recipe->ingredients as $ingredient)
            <div>
                <span>{{ $ingredient->name }}</span>
                <div></div>
                <span>{{ $ingredient->pivot->quantity . ' '. $ingredient->pivot->unit->name}}</span>
            </div>
        @endforeach

Troubleshooting Laravel Website Issues After Hosting on Shared Server

I have developed a Laravel website and uploaded it to the live server. Since a Laravel website cannot be hosted directly on shared hosting, I created an ASSET_URL in the .env file and moved the index.php file, which was inside the public folder, to the main directory of the website. I also changed the default session time of 120 in the .env file to SESSION_LIFETIME=600 and also have the setting SESSION_SECURE_COOKIE =true. Now, the website is working fine. However, when I keep the website open in a browser for a couple of days, I face issues like some buttons not working, some links not working, and the page reloading when I click a button. However, when I change the browser or open it in incognito mode, the website works perfectly. I don’t want to clear the cache all the time because the end user may not be aware of browser cache, etc. How to resolve this