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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.