Relationships of models (Laravel 5.2) - mysql
My tables (Mysql DB):
// Stores Table
CREATE TABLE IF NOT EXISTS `app_beta`.`stores` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`))
// Items Table
CREATE TABLE IF NOT EXISTS `app_beta`.`items` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT UNSIGNED NOT NULL,
`title` TEXT NOT NULL,
`content` LONGTEXT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_items_user_id`
FOREIGN KEY (`user_id`)
REFERENCES `app_beta`.`users` (`id`))
// Products Table
CREATE TABLE IF NOT EXISTS `app_beta`.`products` (
`id` INT UNSIGNED NOT NULL,
`reviews` DECIMAL(7,1) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_products_id`
FOREIGN KEY (`id`)
REFERENCES `app_beta`.`items` (`id`))
// Product_Store Table
CREATE TABLE IF NOT EXISTS `app_beta`.`products_stores` (
`product_id` INT UNSIGNED NOT NULL,
`store_id` INT UNSIGNED NOT NULL,
`price` DECIMAL(7,2) NOT NULL,
`url` VARCHAR(255) NOT NULL,
CONSTRAINT `fk_products_store_product_id`
FOREIGN KEY (`product_id`)
REFERENCES `app_beta`.`products` (`id`),
CONSTRAINT `fk_products_stores_store_id`
FOREIGN KEY (`store_id`)
REFERENCES `app_beta`.`stores` (`id`))
// Offers Table
CREATE TABLE IF NOT EXISTS `app_beta`.`offers` (
`id` INT UNSIGNED NOT NULL,
`store_id` INT UNSIGNED NOT NULL,
`price` DECIMAL(7,2) NULL,
`url` VARCHAR(255) NOT NULL,
`start_date` DATE NOT NULL,
`end_date` DATE NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_offers_store_id`
FOREIGN KEY (`store_id`)
REFERENCES `app_beta`.`stores` (`id`),
CONSTRAINT `fk_offers_id`
FOREIGN KEY (`id`)
REFERENCES `app_beta`.`items` (`id`))
Add. Info:
My tables are migrated. Just to clarify... the products and offers inherit from the items table. If the item is not created I can not add products and offers.
The product can have the title, summary, content, category etc... same for the offer.
The product can be on 1-many stores
The offer can be only on 1-1 store.
If I'm wrong LET ME KNOW!
** Please, I want someone to help me creating the relationships between the Item model, product and offer. Can i use polymorphic relations? **
Models DONE:
class Store extends Model
{
public function offers()
{
return $this->hasMany('App\Offer');
}
public function products()
{
return $this->hasMany('App\Product');
}
}
class Product extends Model
{
public function stores()
{
return $this->belongsToMany('App\Store');
}
}
class Offer extends Model
{
public function store()
{
return $this->belongsTo('App\Offer');
}
}
using php artisan tinker, all works nice!
namespace App
$user = new User
$store = new Store
$item = new Item
$item->id = 1
$item->user_id = 1
$item->title = 'test'
$item->content 'test'
$item->save();
true
$item2 = new Item
$item2->id = 2
....
true
$product1 = new Product
$product1->id = 1 (FK item->id)
$product1->reviews = 5
$product1->save()
true
$offer1 = new Offer
$offer1->id = 2 (FK item->id)
$offer1->store_id = 1
...
true
I'll add later a function to attach product to one or many stores (products_stores table).
Thanks.
This is how I think you can have a good start...
First of all, your model and migration can handle all it.
There is for relationship:Laravel 5.2 Relationship
There is for migration:Laravel 5.2 Migration
So there you create your migration:
Schema::create('stores', function (Blueprint $table) {
$table->bigIncrements('id')->unsigned();
$table->string('name', 50);
$table->timestamps();
});
Schema::create('items', function (Blueprint $table) {
$table->bigIncrements('id')->unsigned();
$table->bigInteger('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->text('title');
$table->longText('content');
$table->timestamps();
});
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('store_id')->unsigned();
$table->foreign('store_id')->references('id')->on('stores');
$table->decimal('reviews', 7,1);
$table->timestamps();
});
Schema::create('offers', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('store_id')->unsigned();
$table->foreign('store_id')->references('id')->on('stores');
$table->bigInteger('item_id')->unsigned();
$table->foreign('item_id')->references('id')->on('items');
$table->decimal('price', 7,2);
$table->string('url', 255);
$table->dte('start_date');
$table->dte('end_date');
$table->timestamps();
});
So, once you did this, you can make your relationship onto your model. This way you don't need all the "between" tables. When you will use associate(), Laravel will create the link for you. This way you can do something like this: $offer->store()->name to get the name of the store of the current offer. Take a look:
Into Store's model
public function products()
{
return $this->hasMany(Product::class);
}
public function offers()
{
return $this->hasMany(Offer::class);
}
Into Offer's model
public function store()
{
return $this->belongsTo(Store::class);
}
This way, You create a one-to-many relation. Has I said, $offer->store() will retrieve the store of the offer. $store->offers()->get() will retrieve all offer of the store.
Hope it help.
EDIT
There is one only problem with what I said. The n + 1 problem. So like it explain there(search google "laravel n+1 problem" and pick the link to laracast) (can't put it as a link, not enough reputation) , when you call things like I said, the script will do 2 query. When you use a foreach() loop, it'll have as much loop +1 query. I suggest you to do things like that
$offers = Offer::with('store')->all();
This way you'ill have only 1 query and you will still able to do
$offer->store;
without doing another query.
When you use $model = Model::with('something')->all();, the query will fetch data from 2 table and return the result with an array into an array. Like this:
offers {
[0]:{a,b,c,d,e, store{a,b,c,d,e}}
[1]:{a,b,c,d,e, store{a,b,c,d,e}}
[2]:{a,b,c,d,e, store{a,b,c,d,e}}
[3]:{a,b,c,d,e, store{a,b,c,d,e}}
}
You can use the opposite:
$stores = Store::with('offers')->all();
So you can use:
$store->offers[i]->somthing;
Because the array will look like this:
stores {
[0]:{a,b,c,d,e, offers{
[0]:{a,b,c,d,e}
[1]:{a,b,c,d,e}
[2]:{a,b,c,d,e}
[3]:{a,b,c,d,e}
}}
[1]:{a,b,c,d,e, offers{
[0]:{a,b,c,d,e}
[1]:{a,b,c,d,e}
[2]:{a,b,c,d,e}
[3]:{a,b,c,d,e}
}}
[2]:{a,b,c,d,e, offers{
[0]:{a,b,c,d,e}
[1]:{a,b,c,d,e}
[2]:{a,b,c,d,e}
[3]:{a,b,c,d,e}
}}
}
Related
Creating a MySQL trigger to set a boolean value to true if a collection of booleans are true
I am creating an inventory management app in node.js that uses MySQL as a database. I have a weak entity “rental_item” that holds the items in a particualr rental. The issue is that the rental may not come back all at once so I need a way of marking the “rental_returned” boolean in the rental table true only when all of the “item_returned” entires are true. Here is my table structure: CREATE TABLE `rental` ( `rental_id` int NOT NULL AUTO_INCREMENT, `renter_id` int NOT NULL, `date_in` date NOT NULL, `date_out` date NOT NULL, `sig_path` varchar(50) NOT NULL, `doc_path` varchar(50) NOT NULL, `col_name` varchar(50) NOT NULL, `col_path` varchar(50) NOT NULL, `cost` decimal(15,2) NOT NULL, `rental_returned` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`rental_id`), UNIQUE KEY `doc_path` (`doc_path`), UNIQUE KEY `col_path` (`col_path`), UNIQUE KEY `sig_path` (`sig_path`), KEY `renter_key` (`renter_id`), CONSTRAINT `renter_key` FOREIGN KEY (`renter_id`) REFERENCES `renter` (`renter_id`) ) CREATE TABLE `rental_item` ( `rental_id` int NOT NULL, `i_ID` varchar(20) NOT NULL, `item_returned` tinyint(1) NOT NULL DEFAULT '0', KEY `rental_key` (`rental_id`), KEY `rental_item_key` (`i_ID`), CONSTRAINT `rental_item_key` FOREIGN KEY (`i_ID`) REFERENCES `item` (`i_ID`), CONSTRAINT `rental_key` FOREIGN KEY (`rental_id`) REFERENCES `rental` (`rental_id`) ON DELETE CASCADE ) I am currently doing this through the mysql2 node.js module and just checking for all the values of a given rental_id. I then found out about triggers and thought this way could be better. I fiddled round with things like this Trigger with table join, but couldn’t wrap my head around how to get the rental_id of the entry that was updated from rental_item, then check that all entires in rental_item with that id have item_returned = 1, and finally update the rental table to show that all the items/the complete rental has been returned. I understand that this sould be an update after trigger on rental_item but dont know how to handle the conditionals or loops needed.
Use NEW.rental_id to get the ID of the row that was updated. CREATE TRIGGER rental_returned AFTER UPDATE ON rental_item FOR EACH ROW UPDATE rental SET rental_returned = ( NOT EXISTS ( SELECT * FROM rental_item WHERE rental_id = NEW.rental_id AND item_returned = 0)) WHERE rental_id = NEW.rental_id
Didnt display results in database
I have a little problem with one database. I have already entered data in the individual tables in the database. The problem is that with this code, it displays the column names, but didnt return rows. I can't find the error. I think the problem is in JOIN itself. Any ideas for solving the problem? SELECT cars.brand, cars.model, cars.yearofproduction, cars.engine_type, parts.part_name, parts.price AS MONEY, parts.quantity FROM CATALOG JOIN parts ON parts.part_name = parts.id JOIN cars ON CATALOG.car_id = cars.id WHERE quantity >= '0' HAVING MONEY < ( SELECT AVG(price) FROM cars ); And here the tables. I've already insert values in the tables. CREATE TABLE CATALOG.parts ( id INT AUTO_INCREMENT PRIMARY KEY, part_name VARCHAR(255) NOT NULL, price DECIMAL NOT NULL, DESCRIPTION VARCHAR(255) DEFAULT NULL, quantity TINYINT DEFAULT 0 ); CREATE TABLE CATALOG.cars ( id INT AUTO_INCREMENT PRIMARY KEY, brand VARCHAR(255) NOT NULL, model VARCHAR(255) NOT NULL, yearofproduction YEAR NOT NULL, engine_type SET('Diesel', 'A95', 'Gas', 'Metan') ); CREATE TABLE CATALOG.catalog ( part_id INT NOT NULL, CONSTRAINT FOREIGN KEY(part_id) REFERENCES parts(id) ON DELETE RESTRICT ON UPDATE CASCADE, car_id INT NOT NULL, CONSTRAINT FOREIGN KEY(car_id) REFERENCES cars(id) ON DELETE RESTRICT ON UPDATE CASCADE, PRIMARY KEY(part_id, car_id) );
SQL failed to output parameters
So we have 2 tables: listings users Currently, i'm trying to retrieve all the information of the given users id where the fk_poster_id of the listings table is the foreign key with reference made to the users id by using the GET method.But when i try to execute the codes, i receive [] as the output. Is there a way to solve this? Here's my current sql codes DROP DATABASE snapsell; CREATE DATABASE IF NOT EXISTS `snapsell`; USE `snapsell`; DROP TABLE IF EXISTS `users`; DROP TABLE IF EXISTS `listings`; CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, UNIQUE (username), profile_pic_url VARCHAR(1000) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=INNODB; -- THESE ARE JUST EXAMPLES AND TEST KITS.TO BE REMOVED BEFORE PRESENTATION. INSERT INTO users (username, profile_pic_url) VALUES ("steve_jobs","https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/Steve_Jobs_Headshot_2010-CROP2.jpg/800px-Steve_Jobs_Headshot_2010-CROP2.jpg"), ("barack_obama","https://upload.wikimedia.org/wikipedia/commons/e/e9/Official_portrait_of_Barack_Obama.jpg"), ("kim_jung_un","https://upload.wikimedia.org/wikipedia/commons/d/d0/Kim_Jung-Un_-_Inter_Korean_Summit%28cropped%29_v1.jpg"), ("lee_kuan_yew","https://upload.wikimedia.org/wikipedia/commons/0/0f/Lee_Kuan_Yew.jpg"); CREATE TABLE listings ( id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, title VARCHAR(100) NOT NULL, description_i VARCHAR(1000) NOT NULL, price INT(6) NOT NULL, fk_poster_id INT NOT NULL, KEY fkPosterID (fk_poster_id), CONSTRAINT FOREIGN KEY (fk_poster_id) REFERENCES users(id) ON DELETE NO ACTION ON UPDATE NO ACTION, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=INNODB; -- THESE ARE JUST EXAMPLES AND TEST KITS.TO BE REMOVED BEFORE PRESENTATION. INSERT INTO listings (title, description_i, fk_poster_id, price) VALUES ("iPhone 6s USED","In good condition. Camera and screen not working.","2","250"), ("Samsung S7 NOT USED","In bad condition. Screen fully smashed. Can't even operate.","3","10000"); CREATE TABLE offers ( id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, fk_offeror_id INT NOT NULL, KEY fkOfferID (fk_offeror_id), CONSTRAINT FOREIGN KEY (fk_offeror_id) REFERENCES users(id) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=INNODB; SELECT * FROM users; SELECT * FROM listings; My current controller codes var express = require('express'); var app = express(); const userJs = require('../model/user') const listingJs = require('../model/listing') var bodyParser = require('body-parser'); var urlencodedParser = bodyParser.urlencoded({ extended: false }); app.use(bodyParser.json()); //parse appilcation/json data app.use(urlencodedParser); app.get("/users/:user_id/listings/",(req,res) => { var user_id = req.params.id; userJs.getListingsByUserID(user_id, (error,results) => { if (error) { res.status(500).send("Internal Server Error") } res.status(200).send(results); }); }) And my current user.js codes var db = require('./databaseConfig.js') const users = {getListingsByUserID: function (user_id, callback) { const getListingsByUserIDQuery = 'SELECT u.id,l.title,l.description_i,l.price,l.fk_poster_id,l.created_at FROM listings l INNER JOIN users u ON u.id = l.fk_poster_id WHERE u.id = ?;'; db.query(getListingsByUserIDQuery,[user_id],(error,results) => { if (error) { callback(error,null); return; }; callback(null,results); }) } module.exports = users;
Just try to use Promise instead of callback like this: const users = { function getListingsByUserID(user_id) { return new Promise((resolve, reject) => { db.query(getListingsByUserIDQuery,[user_id],(error,results) => { if (error) { return reject(error); } else { return resolve(results); } }); }); }); }; If you want result through callback method then try callback(null,results[0]);
create a trigger that adds a field to +5 and creates the total in another table
I'm new and I'm not so good with the triggers, I place the tables and figure out how to create this sum -- Table `databasestreaming`.`tipologiaabbonamento` CREATE TABLE IF NOT EXISTS `databasestreaming`.`tipologiaabbonamento` ( `idtipologiaabbonamento` INT NOT NULL AUTO_INCREMENT, `piano abbonamento` VARCHAR(45) NULL, `dispositivi` VARCHAR(45) NULL, `Risoluzione` VARCHAR(45) NULL, `Prezzo` INT NULL, PRIMARY KEY (`idtipologiaabbonamento`)) ENGINE = InnoDB; -- Table databasestreaming.abbonamento CREATE TABLE IF NOT EXISTS `databasestreaming`.`abbonamento` ( `idabbonamento` INT NOT NULL AUTO_INCREMENT, `data attivazione` DATE NULL, `data termine` DATE NULL, `Sport` ENUM("Si", "No") NULL, `cliente_idcliente` INT NOT NULL, `tipologiaabbonamento_idtipologiaabbonamento` INT NOT NULL, `Prezzo_finale` INT NULL, PRIMARY KEY (`idabbonamento`, `cliente_idcliente`, `tipologiaabbonamento_idtipologiaabbonamento`), INDEX `fk_abbonamento_cliente_idx` (`cliente_idcliente` ASC) , INDEX `fk_abbonamento_tipologiaabbonamento1_idx` (`tipologiaabbonamento_idtipologiaabbonamento` ASC) , CONSTRAINT `fk_abbonamento_cliente` FOREIGN KEY (`cliente_idcliente`) REFERENCES `databasestreaming`.`cliente` (`idcliente`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `fk_abbonamento_tipologiaabbonamento1` FOREIGN KEY (`tipologiaabbonamento_idtipologiaabbonamento`) REFERENCES `databasestreaming`.`tipologiaabbonamento` (`idtipologiaabbonamento`) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB; I would like that when the user selects from enum Si with Sport, the trigger will take the price from the type of subscription (three types of subscriptions that will choose the user) and add the type of subscription chosen to the eventual or not of the sport choice, if yes, then we add +5 if instead it chooses no, in the final price I would like it to simply report the price of the chosen subscription
Cakephp $scaffold doesn't display associated models
Help me please, I'm desperate! I have this schema: CREATE TABLE `baskets` ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `name` varchar(20) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; CREATE TABLE `apples` ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `basket_id` INT UNSIGNED ,`type` int, FOREIGN KEY (basket_id) references baskets(id) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; These are my models: class Apple extends AppModel { public $name = 'Apple'; public $recursive = 2; public $belongsTo = 'Basket'; } class Basket extends AppModel { public $name = 'Basket'; public $recursive = 2; public $hasMany = 'Apple'; } However, when I call the variable $scaffold on either one of them, and try to update or create a new apple; the little drop-down thingy where I would normally choose a basket is empty. What can I do???? I'm gonna get fired if I don't solve this by monday :(