PHP одновременный доступ к файлам / flock () проблема - PullRequest
0 голосов
/ 07 февраля 2012

У меня проблемы с реализацией скрипта, который должен анализировать строку json из файла, либо перезаписать объект с тем же идентификатором, либо добавить его в массив json и записать обратно в файл.Сценарий вызывается в цикле for, поэтому я попытался использовать flock для предотвращения перезаписи файла до того, как можно будет проанализировать строку json, но результаты выглядят действительно странно, и я не знаю, что происходит неправильно.Вот сценарий:

$method = $_SERVER['REQUEST_METHOD'];

$file = fopen($userid . '.json', 'c+');
flock($file, LOCK_EX);

$jsonStr = (filesize($userid . '.json') == 0 ) ? '{"success": true}' : fread($file, filesize($userid . '.json'));
$jsonObj = json_decode($jsonStr);

if($method === 'POST') {
$dataStr = file_get_contents('php://input');
$dataObj = json_decode($dataStr);

$replacements = array();
if(isset($jsonObj->images)) {
    foreach($jsonObj->images as $idx=>$image) {
            if($image->id == $dataObj->id) {
                $replacements += array($idx => $dataObj);
            }
    }
    if(count($replacements)==0) {
        array_push($replacements, $dataObj);
    }
    $jsonObj->images = array_replace($jsonObj->images, $replacements);
} else {
    //$jsonObj = new stdClass();
    $jsonObj->images = new stdClass(); 
    $jsonObj->images = array($dataObj);
}


fwrite($file, json_encode($jsonObj));
file_put_contents('log.json', json_encode($dataObj), FILE_APPEND);

echo '{"success":true, "images":' . $dataStr . '}';
} else if($method === 'GET') {
echo $jsonStr;
}

fclose($file);

В результате я получаю три файла, один из которых просто называется ".json", а другой правильно userid .json и log.json.Журнал выглядит лучше всего, поскольку все 26 объектов отображаются правильно, но без проверки на выход из объектов ранее.".Json" просто пуст и выглядит очень странно:

{"success":true,"images":[{"id":"f9f4b6ee-8b7b-414e-98f4-47ed5ee3c594","top":1200,"left":4050,"clicks":0,"affinity":[]}]}
{"success":true,"images":[{"id":"034c7661-9466-4651-b860-7e049e1543ac","top":900,"left":600,"clicks":0,"affinity":[]}]}
{"images":[{"id":"eebc35ec-6c0e-416a-9516-061df821083d","top":1800,"left":3300,"clicks":0,"affinity":[]}]}
{"images":[{"id":"e09da5b9-2e65-4a12-94cd-4745b354a256","top":1200,"left":1200,"clicks":0,"affinity":[]}]}
{"images":[{"id":"b023a259-4554-48a5-acd8-cb4215e6a391","top":1350,"left":1500,"clicks":0,"affinity":[]}]}
{"images":[{"id":"6521d8c3-461c-4fcd-b69d-69f14ae37418","top":600,"left":3750,"clicks":0,"affinity":[]}]}
{"images":[{"id":"4c082c1a-d4ae-4c1c-bfc4-ed36980f5db2","top":3150,"left":600,"clicks":0,"affinity":[]}]}
{"images":[{"id":"22dbdea2-4936-4353-825e-9af6e6f2ca93","top":3000,"left":2100,"clicks":0,"affinity":[]}]}
{"images":[{"id":"a7ba32d4-912e-489d-8f9b-e412bc1629c1","top":2850,"left":3750,"clicks":0,"affinity":[]}]}
{"images":[{"id":"b258148d-1779-4f17-ae5e-1160aa0a34b9","top":750,"left":4050,"clicks":0,"affinity":[]}]}
{"images":[{"id":"21c1c9d1-a7a6-48d2-a4ba-174c0fe248a3","top":1650,"left":750,"clicks":0,"affinity":[]}]}
{"images":[{"id":"bfed2f56-7876-4eb2-a217-e0f71f4455ee","top":3300,"left":1500,"clicks":0,"affinity":[]}]}
{"images":[{"id":"7f13b674-5d07-444f-bf6d-463758c96788","top":1650,"left":1950,"clicks":0,"affinity":[]}]}
{"images":[{"id":"fb8711f2-ba10-44d7-9038-02cae6438506","top":1800,"left":450,"clicks":0,"affinity":[]}]}
{"images":[{"id":"ac83e869-e4fb-4eee-8d2e-4d26762101d9","top":750,"left":1800,"clicks":0,"affinity":[]}]}
{"images":[{"id":"069a7595-2271-4430-b324-974115df7b80","top":2550,"left":1800,"clicks":0,"affinity":[]}]}
{"images":[{"id":"ea9ab2fc-e179-4f56-9ce7-8af456911b33","top":1950,"left":750,"clicks":0,"affinity":[]}]}
{"images":[{"id":"9b997ae3-0c66-4f78-937a-2fde2470d7d7","top":300,"left":300,"clicks":0,"affinity":[]}]}
{"images":[{"id":"f860dea4-3b27-4401-999b-72ce45022110","top":1200,"left":1950,"clicks":0,"affinity":[]}]}
{"images":[{"id":"2633c107-8a51-4e9c-bc2c-f87c30f7359d","top":750,"left":2100,"clicks":0,"affinity":[]}]}
{"images":[{"id":"bebcb2bb-c2f0-4e4d-b202-b05090eacf49","top":3600,"left":3600,"clicks":0,"affinity":[]}]}
{"images":[{"id":"460f961e-f1dd-4329-95be-d30770a37b83","top":2400,"left":1200,"clicks":0,"affinity":[]}]}
{"images":[{"id":"ee9b254f-fe6a-4ece-a662-e934625e992a","top":3600,"left":600,"clicks":0,"affinity":[]}]}
{"images":[{"id":"4e047ea9-345e-4cf9-a066-d0b431820c61","top":2100,"left":1350,"clicks":0,"affinity":[]}]}
{"images":[{"id":"8bbb5327-6d39-40e1-919e-d7b70e13fc2b","top":2700,"left":1200,"clicks":0,"affinity":[]}]}
{"images":[{"id":"0c50c0ec-e18b-4917-9787-bad245eed798","top":1200,"left":2550,"clicks":0,"affinity":[]}]}

Я также получаю исключение:

<b>Strict Standards</b>:  Creating default object from empty value in <b>C:\xampp\htdocs\gallery\store.php</b> on line <b>38</b><br />

Я думаю, я не правильно понял процедуру, и яЯ рад за любую помощь.

РЕДАКТИРОВАТЬ: Результат, который я хочу, выглядит следующим образом:

{"success":true,"images":[{"id":"f9f4b6ee-8b7b-414e-98f4-47ed5ee3c594","top":1200,"left":4050,"clicks":0,"affinity":[]},
{"id":"034c7661-9466-4651-b860-7e049e1543ac","top":900,"left":600,"clicks":0,"affinity":[]},{"id":"eebc35ec-6c0e-416a-9516-061df821083d","top":1800,"left":3300,"clicks":0,"affinity":[]},
{"id":"e09da5b9-2e65-4a12-94cd-4745b354a256","top":1200,"left":1200,"clicks":0,"affinity":[]},
{"id":"b023a259-4554-48a5-acd8-cb4215e6a391","top":1350,"left":1500,"clicks":0,"affinity":[]},
{"id":"6521d8c3-461c-4fcd-b69d-69f14ae37418","top":600,"left":3750,"clicks":0,"affinity":[]},
{"id":"4c082c1a-d4ae-4c1c-bfc4-ed36980f5db2","top":3150,"left":600,"clicks":0,"affinity":[]},
{"id":"22dbdea2-4936-4353-825e-9af6e6f2ca93","top":3000,"left":2100,"clicks":0,"affinity":[]},
{"id":"a7ba32d4-912e-489d-8f9b-e412bc1629c1","top":2850,"left":3750,"clicks":0,"affinity":[]},
{"id":"b258148d-1779-4f17-ae5e-1160aa0a34b9","top":750,"left":4050,"clicks":0,"affinity":[]},
{"id":"21c1c9d1-a7a6-48d2-a4ba-174c0fe248a3","top":1650,"left":750,"clicks":0,"affinity":[]},
{"id":"bfed2f56-7876-4eb2-a217-e0f71f4455ee","top":3300,"left":1500,"clicks":0,"affinity":[]},
{"id":"7f13b674-5d07-444f-bf6d-463758c96788","top":1650,"left":1950,"clicks":0,"affinity":[]},
{"id":"fb8711f2-ba10-44d7-9038-02cae6438506","top":1800,"left":450,"clicks":0,"affinity":[]},
{"id":"ac83e869-e4fb-4eee-8d2e-4d26762101d9","top":750,"left":1800,"clicks":0,"affinity":[]},
{"id":"069a7595-2271-4430-b324-974115df7b80","top":2550,"left":1800,"clicks":0,"affinity":[]},
{"id":"ea9ab2fc-e179-4f56-9ce7-8af456911b33","top":1950,"left":750,"clicks":0,"affinity":[]},
{"id":"9b997ae3-0c66-4f78-937a-2fde2470d7d7","top":300,"left":300,"clicks":0,"affinity":[]},
{"id":"f860dea4-3b27-4401-999b-72ce45022110","top":1200,"left":1950,"clicks":0,"affinity":[]},
{"id":"2633c107-8a51-4e9c-bc2c-f87c30f7359d","top":750,"left":2100,"clicks":0,"affinity":[]},
{"id":"bebcb2bb-c2f0-4e4d-b202-b05090eacf49","top":3600,"left":3600,"clicks":0,"affinity":[]},
{"id":"460f961e-f1dd-4329-95be-d30770a37b83","top":2400,"left":1200,"clicks":0,"affinity":[]},
{"id":"ee9b254f-fe6a-4ece-a662-e934625e992a","top":3600,"left":600,"clicks":0,"affinity":[]},
{"id":"4e047ea9-345e-4cf9-a066-d0b431820c61","top":2100,"left":1350,"clicks":0,"affinity":[]},
{"id":"8bbb5327-6d39-40e1-919e-d7b70e13fc2b","top":2700,"left":1200,"clicks":0,"affinity":[]},
{"id":"0c50c0ec-e18b-4917-9787-bad245eed798","top":1200,"left":2550,"clicks":0,"affinity":[]}]}

Ура, Даниэль

1 Ответ

0 голосов
/ 07 февраля 2012

Наконец-то у меня это работает, и для всех, у кого есть проблемы с одновременным доступом к файлу, вот мое решение:

  1. Проверьте, существует ли файл, если нет, создайте его и настройтеструктура данных (для предотвращения строгой стандартной ошибки)

    $filename = $userid . '.json';
    if(!file_exists($filename)) {
        $file = fopen($filename, 'w');
        if(flock($file, LOCK_EX)) {
            fwrite($file, '{"success": true, "images": []}');
            flock($file, LOCK_UN);
            fclose($file);
        }
    }
    
  2. Откройте файл, используя c + в качестве второго параметра (w + установит размер файла в 0).Проверьте, можете ли вы получить эксклюзивный замок.Прочитайте файл и перемотайте его, чтобы позже перезаписать.

    else {
        $file = fopen($userid . '.json', 'c+');
        if(flock($file, LOCK_EX)) {
            $jsonStr = fread($file, filesize($userid . '.json'));
            $jsonObj = json_decode($jsonStr);
            rewind($file);
    
  3. Управляйте объектом так, как вам нужно, и запишите его обратно в виде закодированной строки json, используя fwrite

            if($method === 'POST') {
                $dataStr = file_get_contents('php://input');
                if(isset($dataStr) &&$dataStr != '') {
                    $dataObj = json_decode($dataStr);
                    $replace = -1;
                    foreach($jsonObj->images as $idx=>$image) {
                        if($image->id == $dataObj->id) {
                            $replace = $idx;
                        }
                    }
                    if($replace != -1) {
                        $img = $jsonObj->images;
                        $img[$replace] = $dataObj;
                        $jsonObj->images = $img;
                    } else {
                        array_push($jsonObj->images, $dataObj);
                    }
                    fwrite($file, json_encode($jsonObj));
                }
                echo '{"success":true, "images":' . $dataStr . '}';
            } else if($method === 'GET') {
                echo $jsonStr;
            }
    
  4. Снять блокировку и закрыть файл.

            flock($file, LOCK_UN);
            fclose($file);
        }
    }
    
...