2

Hi I have question about DB raw in Laravel. Actually now I have a variable named $currencies with the structure like this.

<?php

$currencies = [
    'CNY' => 1000,
    'USD' => 10000
]

And I need to use the value of that array for sorting my products table. With the products table looks like this:

| id  |  product_name  | original_currency  | price |
|  1  | lorem ipsum d  | CNY                | 20    |
|  2  | new product n  | USD                | 10    |

So far my code looks like this:


$products = DB::raw(SELECT product_name, 
                           price, 
                           price * $currencies[original_currency] AS converted_price 
                    FROM products);

But I got the error Undefined Index: original_currency

I just need to access the correct value to set the converted_price. So the expected result will looks like this:

| id  |  product_name  | original_currency  | price |  converted_price  |
|  1  | lorem ipsum d  | CNY                | 20    |  20000            |
|  2  | new product n  | USD                | 10    |  1000000          |
2

1 Answer 1

2

Issues:

  • Pass query as a string, missing single or double quotes around the query.
  • You can't directly use PHP array inside queries, because queries are being sent to MySQL server and that doesn't have access to your PHP variables.

Solutions:

Approach 1: Fetch simple data from MySQL, modify data in PHP

    $products = DB::raw('SELECT products.product_id, products.original_currency, products.price FROM products);

    foreach($products as $key => $value) {
        $value['converted_price'] = $value['price'] * $currencies[$value['original_currency']];
    }

Approach 2: Use Temp table in MySQL:

    SELECT 
        products.product_id,
        products.price,
        products.price * weight_table.weight AS converted_price
    FROM products
    INNER JOIN (
        SELECT 'CNY' AS currency, 100 AS weight
        UNION
        SELECT 'USD' AS currency, 1000 AS weight
    ) AS weight_table 
        ON products.original_currency = weight_table.currency;

If you have dynamic currency array in PHP, use the following code to generate inner temp table.

$currencies = [
    'CNY' => 100,
    'USD' => 1000
];

function getTempTable($arrCurrency) {
    $arrQuery = [];
    foreach($arrCurrency as $key => $value) {
        $arrQuery[] = "SELECT '" . $key . "' AS currency, " . $value . " AS weight";
    }

    return implode(PHP_EOL. " UNION " . PHP_EOL, $arrQuery); 
}

$strQuery = 'SELECT 
    products.product_id,
    products.price,
    products.price * weight_table.weight AS converted_price
FROM products
INNER JOIN ( ' . getTempTable($currencies) . ') AS weight_table
    ON products.original_currency = weight_table.currency';

$products = DB::raw($strQuery);
Sign up to request clarification or add additional context in comments.

1 Comment

The solution looks fine, but this could potentially be simplified using a macro on the Illuminate\Database\Query\Builder class.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.