Warunek z tekstu (json)

0

Hej!

Mam zrobione drzewo z wartościami w json, w którym są pola z wartościami i warunek do walidacji danych.
Przykład:

{
  "Current": {
    value: 12,
    valid: "value < 20 && value > 9"
  },
  "Voltage": {
    value: 9.2,
    valid: "value >= 12 && value < 24"
  },
  "Fuses": {
    value: true,
    valid: "value == true"
  }
}

Część wartości value wpisywanych jest poprzez formularz w postaci strony internetowej a część przez programy, które mierzą fizycznie wartości.
Potrzebuję teraz zrobić skrypt w php, który sprawdzi mi czy wszystkie wartości spełniają warunek:

  $content = file_get_contents("data/test1.json");
  $json = json_decode($content, true);
  $valid = true;
  foreach($json as $key => $val){
    $value = $val['value'];
    $condition = $val['valid'];
    if(!/* condition */){
      $valid = false;
      break;
    }
  }
  echo $valid ? "OKEJ" : "NOT OKEJ";

I co by tu zrobić w miejscu /* condition */ ?

W formularzu jest walidacja na bieżąco(javascript), która ma tylko informować, a wygląda tak:

function test_valid(value, valid){
  // nazwa zmiennej value odpowiada tekstowemu zapisowi w valid
  return eval(valid);
}

Nie jestem z tego sposobu dumny, ponieważ można w pole valid wpisać głupoty i głupoty też się staną.
Aktualnie nie mam lepszego rozwiązania i też chętnie przyjmę propozycje :)

Dziękuję!

0

Jeśli warunki zawsze są takie proste (tj. bez nawiasów itd.), najprościej będzie wczytywać token po tokenie/wyraz po wyrazie i sprawdzać, z czym aktualnie ma się do czynienia.
Jeśli natomiast istnieją bardziej skomplikowane konstrukcje, nie obejdzie się bez jakiegoś parsera oraz interpretera.

Podejściem z innej strony mogłoby być na przykład zamienianie każdej zmiennej JSowej na PHPową w tym ciągu znaków (np. z test na $test) oraz wywoływanie na tym eval, tyle że, cóż, nie rób tego.

2

Myśle, że do Twojego problemu doskonale nada się to (nie ma problemow z bezpieczenstwem):

http://symfony.com/doc/current/components/expression_language.html

Proste użycie:

<?php declare(strict_types = 1);

include_once '../../../autoload.php';

use Symfony\Component\ExpressionLanguage\ExpressionLanguage;

$array = [
    [
        'value' => 12,
        'rules' => 'value < 20 && value > 9'
    ],
    [
        'value' => 9.2,
        'rules' => 'value >= 12 && value < 24'
    ],
    [
        'value' => true,
        'rules' => 'value == true'
    ],
];

$language = new ExpressionLanguage();

foreach($array as $element){
    $value = $element['value'];
    $condition = $element['rules'];

    var_dump($language->evaluate($condition, ['value' => $value]));
}

Da wyniki:

index.php:28:boolean true
index.php:28:boolean false
index.php:28:boolean true

1 użytkowników online, w tym zalogowanych: 0, gości: 1