παπι Δημοσ. 3 Δεκεμβρίου 2017 Δημοσ. 3 Δεκεμβρίου 2017 Εκει που λεω να εμβαθύνω τςι γνωσεις μου, σκανε απο το πουθενα τα wtf.. Λοιπον, εχουμε 3 πινακες, offers, products, offers_products. Ενα offer, εχει πολλα products τα οποια ειναι mapped (pivot table λεγεται αυτο¨?? ) στο offer_products. <?php namespace App; use Illuminate\Database\Eloquent\Model; use App\Products; use App\OfferProducts; class Offers extends Model { // public function getProducts() { $offerProducts = OfferProducts::where('offers_id', $this->id)->get(); $ret = array(); foreach($offerProducts as $offerProduct) { $ret[] = Products::find($offerProduct->products_id); } return $ret; } public function getPrice() { $prods = $this->getProducts(); $c = count($prods); $price = 0; foreach($prods as $prod) { $price += $prod->sellprice; } return $price; } public function getDiscountPrice() { $initPrice = $this->getPrice(); return $initPrice - ($initPrice * ((double)$this->discount/100.0)); } public function addProduct($id) { $prod = new OfferProducts; $prod->offers_id = $this->id; $prod->products_id = $id; $prod->save(); return $prod; } public function products() { return $this->hasManyThrough( 'App\Products','OfferProducts', 'products_id','id'); } } Με το getProducts που ειναι μεθοδος "αφου δουλευει μωρε...." εχω το αποτελσα που θελω. Ενω με το a la eloquent μεθοδο δεν δουλευει ασχετα που ειναι η σωστη μεθοδολογια aka join join join. Εδω το αποτελεσμ Psy Shell v0.8.15 (PHP 7.1.8 — cli) by Justin Hileman >>> use App\Offers; >>> $offer = Offer::first(); PHP Fatal error: Class 'Offer' not found in eval()'d code on line 1 >>> $offer = Offers::first(); => App\Offers {#769 id: 1, created_at: "2017-12-02 21:45:35", updated_at: "2017-12-02 21:45:35", info: "1+1 20 ekptwsh", discount: 20.0, name: "1+1", } >>> $offer->getProducts(); => [ App\Products {#772 id: 1, created_at: "2017-12-02 21:45:34", updated_at: "2017-12-02 21:45:34", name: "prod name", shortname: "prod short name", description: "prod desc", img_url: "img/img_5930.png", buyprice: "6", sellprice: "10", }, App\Products {#753 id: 1, created_at: "2017-12-02 21:45:34", updated_at: "2017-12-02 21:45:34", name: "prod name", shortname: "prod short name", description: "prod desc", img_url: "img/img_5930.png", buyprice: "6", sellprice: "10", }, ] >>> offer->products; PHP Parse error: Syntax error, unexpected T_OBJECT_OPERATOR on line 1 >>> $offer->products; [!] Aliasing 'OfferProducts' to 'App\OfferProducts' for this Tinker session. => Illuminate\Database\Eloquent\Collection {#765 all: [ App\Products {#763 id: 1, created_at: "2017-12-02 21:45:34", updated_at: "2017-12-02 21:45:34", name: "prod name", shortname: "prod short name", description: "prod desc", img_url: "img/img_5930.png", buyprice: "6", sellprice: "10", products_id: 1, }, ], } >>>
TheDarkKnight Δημοσ. 3 Δεκεμβρίου 2017 Δημοσ. 3 Δεκεμβρίου 2017 https://laravel.com/docs/5.5/eloquent-relationships#has-many-through Εδώ δείχνει ότι δύο διαφορετικοί πίνακες έχουν από ένα εξωτερικό κλειδί ενώ στην περίπτωση σου ένας έχει δύο. Αντί για product_id δοκίμασε offer_id μπας και δούλεψει σύμφωνα με το παράδειγμα.
WebDevGr Δημοσ. 3 Δεκεμβρίου 2017 Δημοσ. 3 Δεκεμβρίου 2017 Επειδή είμαι από κινητό, ρίξε μια ματιά στο παρακάτω ίσως σε βοηθήσει. https://hackernoon.com/eloquent-relationships-cheat-sheet-5155498c209
alou Δημοσ. 3 Δεκεμβρίου 2017 Δημοσ. 3 Δεκεμβρίου 2017 (επεξεργασμένο) Παπί δεν διάβασα όλες τις λεπτομέρειες αλλά η λογική μάλλον θα έπρεπε να είναι πως το model σου είναι το offer και να παίρνεις Offer::where('id', '=', $id)->with('products') που σημαίνει ότι έχεις φτιάξει και τα αντίστοιχα relations στο κάθε model Δεν καταλαβαίνω γιατι η σχέση σου είναι hasManyThrough (που σημαίνει ότι υπάρχει ένα ενδιάμεσο model) και όχι belongsToMany που είναι μάλλον το προφανές στην περίπτωση που περιγράφεις. namespace App; use Illuminate\Database\Eloquent\Model; use App\Products; use App\OfferProducts; class Offers extends Model { public function products() { return $this->belongsToMany('Path\to\Product'); } } /// product Model namespace App; use Illuminate\Database\Eloquent\Model; use App\Products; use App\OfferProducts; class Product extends Model { public function offer() { return $this->belongsToMany('\Path\To\Offer'); } } και μερικά παραδείγματα, χύμα χωρίς δοκιμή όμως /// Call it like: $offer = Offer::find(1)->with('products')->first(); //το first στο τέλος επιστρέφει single object, οχι collection: //echo $offer->id, foreach($offer->products as $product) ... //more complex product query Offer::find(1)->with(['products' => function($query){ $query->where('price', '>', 100); }])->get(); //more relations in the same query Offer::find(1)->with(['products','customer_groups'])->get(); //deeper relations Offer::find(1)->with('products.category')->get(); //category is a relation in product model Αν υπάρχουν τα naming conventions στους πίνακες δεν χρειάζεσαι κάτι παραπάνω, διαφορετικά τα προσδιορίζεις Επεξ/σία 3 Δεκεμβρίου 2017 από alou
παπι Δημοσ. 3 Δεκεμβρίου 2017 Μέλος Δημοσ. 3 Δεκεμβρίου 2017 Ένα offer δεν έχει products. Εννοώ το product δεν έχει fk_offer. Υπάρχει ο τρίτος πίνακας offerproducts που έχει μόνο δύο fk, αυτό του offer και αυτό του products. Άρα για να πάρω τα products, θα πρέπει να κάνω join τον ,offerproducts. Φυσικά παίζει να είναι λάθος το σκεπτικό μου και να γίνεται αλλιώς αυτή η σχέση. Δηλαδή το offer να έχει products χωρίς τα products σα table να έχουν fk προς offer.
alou Δημοσ. 3 Δεκεμβρίου 2017 Δημοσ. 3 Δεκεμβρίου 2017 Όταν έχεις many 2 many relation, έχεις pivot table για να τα συσχετίσεις όπως έχεις ήδη κάνει. Ορίζεις και το αντίστοιχο relation στο model και πας παρακάτω. product id-name-slug-whatever offer id-name-percent offer_product product_id-offer_id Αυτή η σχέση είναι many 2 many και θα εφαρμοζόταν με τον τρόπου που έγραψα προηγουμένως και υποθέτει ότι και τα 2 μέρη μπορούν να συσχετιστούν με 1 ή περισσότερα από το άλλο μέρος, άρα ένα προιον υπάρχει σε 1 η περισσότερες προσφορές, 1 προσφορά έχει 1 ή περισσότερα προιοντα. Αν ένα προιον ΔΕΝ μπορεί να ανήκει σε πολλές προσφορές, θα έπρεπε να έχει σχέση belongsTo προς το offer, να έχει ένα πεδίο offer_id στον πίνακα που θα το συσχετίζει και το offer να έχει μια σχέση hasMany προς τα products. Υπάρχουν και διάφορες άλλες παραλλαγές όμως για να μην μπλέκεις, το καλύτερο που μπορείς να κάνεις τώρα νομίζω είναι να χρησιμοποιήσεις τις σχέσεις όπως σου τις έγραψα παραπάνω στο product και στο offer
παπι Δημοσ. 3 Δεκεμβρίου 2017 Μέλος Δημοσ. 3 Δεκεμβρίου 2017 Ένα προϊόν μπορεί να είναι και σε άλλες προσφορές. Μάλλον επειδή είμαι άσχετος με βάσεις, δεν είδα ότι έχω ουσιαστικά many2many και όχι one to many
alou Δημοσ. 4 Δεκεμβρίου 2017 Δημοσ. 4 Δεκεμβρίου 2017 Edit: Διαβάζοντας ξανά τα μηνύματα, προφανώς θεωρείς ότι το offer_product table θα πρέπει να είναι ξεχωριστό model ώστε να το χρησιμοποιήσεις για να τα συνδέσεις, κάτι που δεν ισχύει. Ο πίνακας offer_product χρησιμοποιείται από το ORM για να κάνει τα join στα offers και products tables, όταν η σχέση είναι many 2 many. Δεν ασχολείσαι απευθείας μαζί του στα queries αν δεν υπάρχει κάποιος πολύ ιδιαίτερος λόγος. ------ OK οπότε το pivot καλώς υπάρχει, αυτό είχα φανταστεί και γω και το μόνο που χρειάζεσαι είναι να αλλάξεις το relation του offer public function products() { return $this->belongsToMany('App\Products','product_id'); } Στο product, αντίστοιχα, θα δηλώσεις το relation προς το offer public function offers() { return $this->belongsToMany('App\Offer','offer_id'); } αν είναι έτσι τα ονόματα των πεδίων στο pivot (offer_id, product_id) ή τα τροποποιείς ανάλογα. Όταν θες να πάρεις ένα offer μαζί με τα προιοντα που το αφορούν $offer = Offer::where('id', '=', $id)->with('products')->first(); όπου τα προιοντα είναι στο $offer->products Ουσιαστικά αυτό είναι 2 queries, με παρόμοια λογική σαν αυτό που έκανες στην getProducts αλλά πιο ευανάγνωστο και στις περισσότερες περιπτώσεις πιο εύχρηστο. Και ένα τελευταίο: όταν καλείς κάτι με id ή γενικά είναι σίγουρο ότι ψάχνεις ένα αποτέλεσμα, το ζητάς με ->first() στο τέλος όχι με get ώστε να μη χρειαστεί foreach - παίρνεις ένα object σαν αποτέλεσμα, όχι collection. Edit again: Αν υποθέσουμε ότι για κάποιο λόγο θες να χρησιμοποιήσεις αυτού του είδους το query: public function getProducts() { $offerProducts = OfferProducts::where('offers_id', $this->id)->get(); $ret = array(); foreach($offerProducts as $offerProduct) { $ret[] = Products::find($offerProduct->products_id); } return $ret; } σημαίνει πρακτικά ότι θέλεις τα product ids που αφορούν την συγκεκριμένη προσφορά για να τα πάρεις από τον πίνακα products, οπότε θα μπορούσες να το κάνεις έτσι χωρίς τα ατείλειωτα queries μέσα στο foreach public function getProducts() { $productIds = OfferProducts::where('offers_id', $this->id)->lists('product_id');//επιστρέφει array με product ids return Products::whereIn('id', $productIds); } 1
παπι Δημοσ. 4 Δεκεμβρίου 2017 Μέλος Δημοσ. 4 Δεκεμβρίου 2017 Ναι ειναι οκ με belongsToMany. Btw, γιατι να μην βαλω model στο pivot table? Πως θα κανω εισαγωγη ενος προϊόντος μεσα σε ενα οφερ; Δηλαδή για να βαλω ενα προϊόν, δεν θα έπρεπε να εισαγω στο pivot τα δυο fk?
alou Δημοσ. 4 Δεκεμβρίου 2017 Δημοσ. 4 Δεκεμβρίου 2017 Όχι, τα αναλαμβάνει το ORM αυτά, με sugar syntax. πχ βγάλε όλες τις προσφορές από ένα προιον (δηλαδή σβήσε ότι έχει το συγκεκριμένο product_id από το pivot) $product->offers()->detach(); πάρε ένα array με τα offer ids που συνδέονται με το προιον και γέμισε το pivot $product->offer()->attach($offerIds); ή sugar on top of sugar, με μία κίνηση $product->offers()->sync($offerIds); 1
παπι Δημοσ. 5 Δεκεμβρίου 2017 Μέλος Δημοσ. 5 Δεκεμβρίου 2017 (επεξεργασμένο) Πωπω, επαθα ζαχαρο <?php namespace App; use Illuminate\Database\Eloquent\Model; use App\Product; class Offer extends Model { // public function products() { return $this->belongsToMany('App\Product'); } public function addProduct(Product $product) { $this->products()->attach($product->id); } public function getPrice() { return $this->products()->sum('sellprice'); } public function getDiscountPrice() { $initPrice = $this->getPrice(); return $initPrice - ($initPrice * ((double)$this->discount/100.0)); } } Επεξ/σία 5 Δεκεμβρίου 2017 από παπι
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα