Проверка базы данных и избежание дублирования перед вставкой данных с помощью laravel - PullRequest
0 голосов
/ 12 октября 2018

Я пытаюсь проверить базу данных перед вставкой данных, чтобы избежать дублирования.Я храню URL-адреса в массиве и вставляю их в столбец «link» таблицы.Итак, сначала я проверяю столбец, истере тот же URL или нет?Если нет, то вставьте данные с этим кодом.

Вот мои целые коды вставки базы данных;

foreach ($outlineUrls  as $outlineUrl) {
    $html = file_get_contents($outlineUrl);
    $DOMParser = new \DOMDocument();
    $DOMParser->loadHTML($html);


    $changeForMyDB = [
                            'remote_id' => '',
                            'region' => '関西',
                            'link' => json_encode($outlineUrl),
                            'name' => '',
                            'price' => '',
                            'extend' => '',
                            'address' => '',
                            'hows_old' => '',
                            'rooms' => '',
                            'old' => '',
                            'entery' => '',
                            'balcon_m2' => '',
                            'company_name' => '',
                            'script_from' => ''
                        ];

            $allPTags = $DOMParser->getElementsByTagName('p');
            foreach($allPTags as $ptag){
                if($ptag->getAttribute('class') == 'c-name'){
                        $changeForMyDB['name'] = trim($ptag->nodeValue);
                }
            }

            $changeForMyDB['address'] = trim($DOMParser->getElementsByTagName('dd')[0]->nodeValue);

            $allTables = $DOMParser->getElementsByTagName('table');
            foreach($allTables as $table){
                foreach($table->getElementsByTagName('tr') as $tr){
                    $property = trim($tr->getElementsByTagName('th')[0]->nodeValue);
                    $value = trim($tr->getElementsByTagName('td')[0]->nodeValue);

                    switch ($property) {
                        case '物件名':
                            $changeForMyDB['name'] = $value;
                            break;
                        case '販売価格':
                            $changeForMyDB['price'] = $value;
                            break;
                        case '専有面積':
                            $changeForMyDB['extend'] = $value;
                            break;
                        case '所在地':
                            $changeForMyDB['address'] = $value;
                            break;
                        case '総戸数':
                            $changeForMyDB['hows_old'] = $value;
                            break;
                        case '間取り':
                            $changeForMyDB['rooms'] = $value;
                            break;
                        case '竣工時期':
                            $changeForMyDB['old'] = $value;
                            break;
                        case '管理会社':
                            $changeForMyDB['company_name'] = $value;
                            break;
                        case '入居時期':
                            $changeForMyDB['entery'] = $value;
                            break;
                        case '入居時期':
                            $changeForMyDB['entery'] = $value;
                            break;
                        case 'バルコニー面積':
                            $changeForMyDB['balcon_m2'] = $value;
                            break;
                        default:
                            # code...
                            break;
                    }
                }
            }

if(Estates::where('link','=',$outlineUrl)->count() > 0)
{

   $this->error('There is link.');

} else {

        Estates::insertGetId($changeForMyDB);

        $this->line('Data saved.');

       }

Но проблема здесь.Это вставка данных без проверки!Есть идеи, в чем проблема?Спасибо за помощь.

1 Ответ

0 голосов
/ 12 октября 2018

Вы можете использовать метод updateOrCreate () для достижения цели только вставки, если запись не существует:

$estate = Estates::updateOrCreate(['link' =>  $outlineUrl], $changeForMyDB);

Это проверит, существует ли Estate::where('link', '=', $outlineUrl).Если ничего не найдено, будет создан новый Estate´ and add all data from $ changeForMyDB to it. If one exists, it will fetch it from the database, add all data from $ changeForMyDB`.Тогда будут сохраняться изменения.Подробнее об этом читайте здесь: https://laravel.com/docs/5.7/eloquent#other-creation-methods


Чтобы избежать проблем с параллельными запросами, вы также должны заключить свое обновление в транзакцию базы данных.Это гарантирует, что при проверке уникальности база данных будет в том же состоянии, что и при сохранении ваших данных.

DB::transaction(function () {
    $estate = Estates::updateOrCreate(['link' =>  $outlineUrl], $changeForMyDB);
});

Если вы не хотите обновлять существующие записи, используйте что-то вроде этого:

DB::transaction(function () {
    if (Estates::where('link','=',$outlineUrl)->count() === 0) {
        $estate = Estates::create($changeForMyDB);
    }
});

Помните, что Estates::create($data) и Estates::insert($data) не совпадают.Функция create($data) создаст модель, заполнит ее $data и вернет сохраненную модель.Он также запустит все события Eloquent, относящиеся к методу create.С другой стороны, метод insert($data) не будет создавать модель Eloquent и, следовательно, не будет запускать любые события Eloquent.Он будет напрямую вставлять данные в базу данных.Это проще и быстрее, но вы должны помнить об этом.


Если вы хотите проверить, существует ли уже запись, и сообщить об ошибке какого-либо типа, вы можете проверить это:

if (!$estate->wasRecentlyCreated()) {
    // report error here
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...