Slim Framework PHP

Salutare, revin cu o problema, de data asta in Slim Framework.

Am 2 tabele.

Products:
products
ProductsMeta
metas

El afiseaza asta momentan asa
json

As vrea sa afiseze ceva de genul ca sa pot folosi mai tarziu AJAX.

{

* productId: "1",

* productName: "PizzaElCozo"

* ingredients: "1";

* ingredients: "2";

* ingredients: "3";

},

Si sa adauge o linie pentru fiecare ingredient.

Acesta este codul:

<?php
header('Content-Type: application/json');

#Retrive pizzas list from db
$app->get('/api/pizzas', function(){
    require_once('databaseconnect.php');
    $queryPizzas = "select * from cms_products order by productName";
    $result = $mysqli->query($queryPizzas);

    #Tryout
    $Ingredients = "
    SELECT 
        * 
    FROM 
        cms_productsmeta as cpm, cms_products as cps
    WHERE  
        cps.productId = cpm.productId     
    ";
    $resultIngredients = $mysqli->query($Ingredients);

    while($row = $result->fetch_assoc()){
        $data[] = $row;
    }

    if (!isset($data)){
        echo "Nu exista nicio pizza in baza de date!";
    } else {

        echo json_encode($data);
    }
});

Al 2-lea select, ar fi cum l-am gandit sa afiseze. Multumesc!

Ok, o solutie rapida (desi te lovesti de N+1 Query Problem) ar fi ca dupa primul query sa-ti salvezi toate produsele intr-un array, iar apoi sa iterezi prin respectivul array si la fiecare iteratie sa faci un query pentru a prelua ingredientele.

1 Like

M-ai pierdut complet :slight_smile: O sa ma documentez!

use devforum;
SELECT products.productId, products.productName, GROUP_CONCAT(productsMeta.valueData SEPARATOR '|') as ingrediente

FROM

	products
	
LEFT JOIN 

	productsMeta ON products.productId = productsMeta.productdId

GROUP BY products.productName;

Foloseste explode pentru ingrediente.

Dar baza de date nu este create corect, ai duplicaturi atat la valueType cat si la valueMeta. Creeaza tabele separate si faci o tabela cu relatii.

vezi un join.

Pai de ce sa fie duplicate daca tipul este ingredient, si valoarea ingredientului pentru fiecare pizza este acelasi.

Daca am Pizza cu pui cu sos de rosii si sos de ceva voi avea
pentru pizza cu pui -> ingredient -> sos rosii
pentru pizza cu pui -> ingredient -> sos ceva

pentru pizza cu vita-> ingredient -> sos rosii
pentru pizza cu vita-> ingredient -> sos ceva

Vor avea acelasi ingrediente samd.

Multumesc, am sa incerc varianta de mai sus.

Multumesc frumos! Am reusit cu Group Concat.

$app->get('/api/all', function(){
    require_once('databaseconnect.php');
           
    $queryPizzas = "
    select 
        p.*, 
        GROUP_CONCAT(i.valueData SEPARATOR ', ') as Ingrediente
    from 
        cms_products as p, 
        cms_productsMeta as i 
    where 
        p.productId = i.productId
    GROUP BY 
        p.productId    
    "; 

    $result = $mysqli->query($queryPizzas);

    while($rowP = $result->fetch_assoc()){
        $data[] = $rowP;

    }

    if (!isset($data)){
        echo "Nu exista niciun utilizator in baza de date";
    } else {

        echo json_encode($data);
    }
});

Asa am reusit si functioneaza cum am nevoie! Seara buna tuturor!
Screenshot_2

Salut @KilobaiD,

In primul rand baza ta de date ar trebui sa arate asa:

tabel feluri pizza(produse):

CREATE TABLE `products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

tabel ingrediente pizza(atribute produs):

CREATE TABLE `attributes` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `type` varchar(255) NOT NULL,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

tabel de legatura intre produs si ingrediente:

CREATE TABLE `productattributes` (
  `productID` int(11) NOT NULL,
  `attributeID` int(11) NOT NULL,
  PRIMARY KEY(productID, attributeID),
  FOREIGN KEY(productID) REFERENCES products(id),
  FOREIGN KEY(attributeID) REFERENCES attributes(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Dupa cum observi, in tabelul cu produse(tipuri de pizza) ar trebui sa ai doar produsele in sine si informatia despre ele, in tabelul cu atribute(ingrediente) asemenea, doar acele atribute si detalile despre ele iar legatura intre cele doua intr-un alt tabel care sa contina exact doar aceasta relatie astfel eviti duplicarea de date.

Odata ce ai baza de date structurata astfel sau asemanator, in cod poti obtine datele pentru o pizza si ingredientele ei astfel:

SELECT p.id, p.name, GROUP_CONCAT(a.name SEPARATOR '|') as attributes
FROM products p
LEFT JOIN productattributes pa on p.id = pa.productID
LEFT JOIN attributes a on pa.attributeID = a.id
GROUP BY p.name;

Evident ca vei folosi explode pentru atribute(ingrediente) ca sa le transformi dintr-un string intr-un array/obiect/ce vrei tu

$attributes = explode("|", $resultAttributes);

iar mai departe am incredere ca te descurci.

3 Likes

Offtopic:

Am vazut ca in scriptul tau datele raspunse au format diferit: fie e un json cu date fie un string cu mesajul “Nu exista nicio pizza”.

Sfatul meu: scriptul ar trebui sa aiba un singur format. Alege unul care sa te ajute in toate cazurile. Exemplu

{
data:[],
meta:{
pagination:{total:320,perPage:100,curPage:1,totalPages:4},
message:"What ever you want to sent"
}
}

Te poti inspira din JSON-API format, daca nu chiar sa il adopti

1 Like

@oneistbesser perfect! Este exact ce cautam, am înțeles mai multe lucruri din acest reply! Inclusiv normalizarea bazei de date. M-am lămurit cu mai multe lucruri :slight_smile: mulțumesc mult de tot!

@Catalin_Banu am sa arunc un ochi, mulțumesc frumos!

Best forum ever!