Problem z dodawaniem produktów to bazy danych

0

Cześć. Mam problem związany z zapisywaniem danych w laravelu. Dane pobieram z api i pętlą zapisuje je w bazie danych. Problem w tym, że danych jest bardzo dużo... po wykonaniu pętli baza danych powinna mieć ok. 300000 rekordów. Gdy zapisuje po kolei tzn. najpierw kategorie, potem produkty a dopiero potem parametry do wszystko jest w porządku. Natomiast jak zrobie to w pętli tak jak w kodzie poniżej to wyskakuje błąd:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (baza.category_product, CONSTRAINT category_product_category_id_foreign FOREIGN KEY (category_id) REFERENCES categories (id) ON DELETE CASCADE) (SQL: insert into category_product (category_id, product_id) values (0, 13356))

Kod (wywoływana funkcja to getAllProductsToDB()):

namespace App\Http\Controllers;
use App\Product;
use App\Param;
use App\Category;
use Illuminate\Http\Request;
class ProductController extends Controller
{
    public function petla2($petla)
    {
        $client = new RestClient(config('app.apikey'));
        $category = Category::firstOrCreate(
            [
                'id' => $petla->getId()
            ],
            [
                'name' => $petla->getName(),
                'category_id' => $petla->getParentId()
            ]
        );

        if($petla->getArticleIdList())
        {
            $products = $client->getProducts($petla->getArticleIdList());
            foreach($products as $product)
            {
                $newProduct = Product::firstOrCreate(
                    [
                        'id' => $product->getId()
                    ],
                    [
                        'name' => $product->getName(),
                        'description' => $product->getDescription(),
                        'price' => $product->getPrice(),
                        'stockAvailability' => $product->getStockAvailability()
                    ]
                );

                $newProduct->categories()->save($category);

                if(!$product->getParams()->isEmpty())
                {
                    foreach($product->getParams() as $param)
                    {
                        $newParam = Param::firstOrCreate(
                            [
                                'id' => $param->getId()
                            ],
                            [
                                'name' => $param->getName()
                            ]
                        );
                        
                        $newProduct->params()->save($newParam,['value' => $param->getValue()]);
                    }
                }
            }
        }
        if(!$petla->getSubCategories()->isEmpty())
        {
            foreach($petla->getSubCategories() as $subCategory)
            {
                self::petla2($subCategory);
            }
        }
    }
    public function getAllProductsToDB()
    {
        $client = new RestClient(config('app.apikey'));
        $tree = $client->getCategoryTree();

        $mainCategory = Category::firstOrCreate(
            ['id' => $tree->getId()],
            ['name' => $tree->getName()]  
          );
        foreach($tree->getSubCategories() as $category)
        {
            self::petla2($category);
        }
    }
}
0

Nie masz w systemie kategorii o id 0, dlatego nie da się dodać rekordu. Poczytaj o kluczach obcych w MySQL.

0
TomRZ napisał(a):

Nie masz w systemie kategorii o id 0, dlatego nie da się dodać rekordu. Poczytaj o kluczach obcych w MySQL.

I nie ma prawa być takiej kategorii. Przy zapisywaniu kategorii nie pobieria id z tworzonego obiektu na początku kodu (Category::firstOrCreate) a tworzy kategorie w bazie.

0

a produkt może być w wielu kategoriach?

0

Tak, jest to relacja many to many. Gdy dam:

$category = Category::firstOrCreate(
            [
                'id' => $petla->getId()
            ],
            [
                'name' => $petla->getName(),
                'category_id' => $petla->getParentId()
            ]
        );
        $category->id = $petla->getId();
        $category->save();

to wszystko działa mimo tego, że bez tego id zapisuje się w bazie.

0

Wydaje Ci się że działa, zrób sobie eksperyment:

$category = Category::firstOrCreate(
            [
                'id' => 0
            ],
            [
                'name' => 'test',
            ]
        );

i zobacz czy w bazie będziesz miał kategorie z id = 0 czy jednak z AUTOINCREMENTA?

0

Rzecz w tym, że pole ID nie ma być INCREMENT. Pole ID podczas twoezenia obiektu zaciągane jest z API. Podczas tworzenia w bazie dodaje się poprawne ID lecz obiekt zwraca ID=0 - być może przez to, że to nie A_I.

0
DuzyMichal napisał(a):

Rzecz w tym, że pole ID nie ma być INCREMENT. Pole ID podczas twoezenia obiektu zaciągane jest z API. Podczas tworzenia w bazie dodaje się poprawne ID lecz obiekt zwraca ID=0 - być może przez to, że to nie A_I.

To może zrób tak:

  1. Normalne ID z autoincrement
  2. ID pobierane z API zapisuj pod inną nazwą np. api_id.
0

a jak masz zdefiniowany model Category?

0
javafxdev napisał(a):

a jak masz zdefiniowany model Category?

Gdzie? Wszystko jest w kodzie w pierwszym poście.

0

To co wkleiłeś to jest controller, a nie model category.

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