Updating table with multiple rows - mysql

How can I update multiple rows at the same time by their report_id? My Inventory table looks like this:
| id | report_id | product_id | shelf_quantity | display_quantity |
|----|-----------|------------|----------------|------------------|
| 1 | 2 | 12 | 1 | 5 |
| 2 | 2 | 13 | 2 | 6 |
| 3 | 2 | 14 | 3 | 23 |
My attempt to solve the problem:
My controller:
function update($id, Request $request) {
$report = Report::find($id);
$inputs = $request->input('display');
$report->user_id = $user_id;
$report->save();
//Updating inventory table
$inventory = Inventory::where('report_id', $report->id)->get();
foreach($inputs as $key => $value) {
$inventory->display = $request->input('display')[$key] ?: 0;
$inventory->storage = $request->input('storage')[$key] ?: 0;
$inventory->save();
}
My web route:
Route::put('/reports/{id}', 'ReportController#update');
The problem here is that it is only saving the last value that I input.
Additional information
I'm also using the same code in storing new rows and it's working fine. Please see code below:
public function store(Request $request) {
//Adding inventory table
$new_inventories = new Inventory();
foreach($inputs as $key => $value) {
$data[] = [
'user_id' => $user_id,
'report_id' => $new_report->id,
'display' => $request->input('display')[$key] ?: 0,
'storage' => $request->input('storage')[$key] ?: 0,
'product_id' => $request->product_id[$key],
'created_at' => $now,
'updated_at' => $now,
// 'remark' => $request->remark[$key] ?? null,
];
}
Inventory::insert($data);
//End of inventory table
}
Any form of help would be appreciated. Thank you!
EDIT:
My form looks like this:
<form action="/reports/{{$report->id}}" method="post">
#csrf
{{method_field('PUT')}}
#foreach($products as $product)
<input type="number" name="product_id[]" value="{{ $product->id}}" hidden>
<input type="number" name="storage[]">
<input type="number" name="display[]">
#endforeach
</form>

You cannot update multiple rows in one shot. In this case the best way is to get one by one the items in inventory and update them. So you loop through $request->input('product_id'), get the Inventory model for that product_id and $report->id, update and save.
for($i=0; $i<count($request->input('product_id');$i++) {
$inventory = Inventory::where('report_id', $report->id)->where('product_id', $request->input('product_id')[$i])->first();
$inventory->display = $inventory->display = $request->input('display')[$i];
$inventory->storage = $inventory->storage = $request->input('storage')[$i];
$inventory->save();
}

Related

Laravel: get data from related tables (json array column)

I have 2 related tables
teams:
| id | name | game_id | user_id |
|----|----------|---------------|---------|
| 1 | EA Games | ["1","2"] | 1 |
| 2 | Nintendo | ["1"] | 2 |
| 3 | HoG | ["3","4","5"] | 1 |
games:
| id | name |
|----|----------|
| 1 | Cod MW |
| 2 | FIFA |
Controller:
public function showManage()
{
$teams = Teams::where('user_id', Auth::user()->id)->where('enabled', '!=', 0)->get();
return view('teams.manage.index', ['teams' => $teams]);
}
View:
#foreach ($teams as $item)
<div class="col-md-2 text-center">
<div class="team-item">
<div class="team-image">
<img src="/images/teams/logo/{{$item->logo}}" alt="{{$item->name}}">
</div>
<div class="team-text">
{{$item->name}}
</div>
<ul>
<li> Game Name 1 </li>
<li> Game Name 2 </li>
<li> Game Name 3 </li>
</ul>
</div>
</div>
#endforeach
Team Model:
<?php
namespace App;
use App\User;
use App\Games;
use Illuminate\Database\Eloquent\Model;
class Teams extends Model
{
protected $table = 'teams';
public function captain()
{
return $this->hasOne(User::class, 'id', 'user_id');
}
public function game()
{
return $this->hasMany(Games::class, 'id', 'game_id');
}
}
Each user can have many teams with different game_ids and i wan't to show game name for each team for my user
How can i join to my game table?
Sorry for my bad English
Having a json field make it impossible to do it with a database statement.
Note that JSON columns cannot have a default value, be used as a primary key, be referenced as a foreign key or have an index. You can create secondary indexes on generated virtual columns, but it’s possibly easier to retain an indexed value in a separate field.
With the current structure, your only solution is to loop the results and do another query for the games.
Changing the structure will be a better solution where you have another table game_team with ids of teams and games as composite key. Then it will be as easy as running this (with the right belongsToMany relation)
$teams = Auth::user()->teams()->with('games')->where('enabled', '!=', 0)->get();
I can fix it with foreach and for loops
Controller:
public function showManage()
{
$teams = Teams::where('user_id', Auth::user()->id)->where('enabled', '!=', 0)->get();
$array = array();
foreach ($teams as $v) {
$data = $v->game_id;
$array[$v->id] = array(
'games' => array(
)
);
$games = Games::whereIn('id', $data)->get();
foreach ($games as $k) {
array_push($array[$v->id]['games'], $k->name);
}
}
return view('teams.manage.index', ['teams' => $teams, 'data' => $array]);
}
View:
#foreach ($teams as $item)
<div class="col-md-2 text-center">
<div class="team-item">
<div class="team-image">
<img src="/images/teams/logo/{{$item->logo}}" alt="{{$item->name}}">
</div>
<div class="team-text">
{{$item->name}}
</div>
<ul>
#foreach ($data[$item->id] as $v)
#for ($i = 0; $i < count($v); $i++)
<li> {{$v[$i]}} </li>
#endfor
#endforeach
</ul>
</div>
</div>
#endforeach

Sql request to get an ordered menu

Right now, I build my menu doing many request and loop with symfony.
I would like to be able to retrieve the same thing in a single sql request
MenuItem (Id,parent_id,level,weight)
parent_id is a reference to an other MenuItem
If I have these records
1,null,1,50
2,null,1,20
3,1,2,100
4,1,2,0
5,2,2,40
6,5,3,900
7,5,3,500
I want the results to be
2
5
7
6
1
4
3
The weigtht attribute is used to order the menu items inside their own level.
That means id 2 come before id 1 because weight 20 < weight 50 but id 2 still comes before id 4 because level 1 < level 2
I'm not even sure this is possible.
EDIT: Right now, I have to do something very ugly
$menu = $this->factory->createItem('root');
$menu->setLabel("Menu");
$item_repository = $this->getDoctrine()->getRepository(MenuItem::class);
//profondeur max defini à 5
//On récupère les items du niveau 1 trié par poids (profondeur)
$items_lv1 = $item_repository->findBy(array('menu' => $id_main_menu,'active' => 1, 'niveau' => 1),array('poids' => 'ASC'));
//On récupère les items du niveau 2 trié par parent et poids (profondeur)
$items_lv2 = $item_repository->findBy(array('menu' => $id_main_menu,'active' => 1,'niveau' => 2),array('parent' => 'ASC','poids' => 'ASC'));
$items_lv3 = $item_repository->findBy(array('menu' => $id_main_menu,'active' => 1,'niveau' => 3),array('parent' => 'ASC','poids' => 'ASC'));
$items_lv4 = $item_repository->findBy(array('menu' => $id_main_menu,'active' => 1,'niveau' => 4),array('parent' => 'ASC','poids' => 'ASC'));
$items_lv5 = $item_repository->findBy(array('menu' => $id_main_menu,'active' => 1,'niveau' => 5),array('parent' => 'ASC','poids' => 'ASC'));
$cptLv1 = 1;
foreach ($items_lv1 as $item_lv1){
$lv1 = $menu->addChild($cptLv1,
['uri' => $item_lv1->getUrl(),'label' => $item_lv1->getLabel(),
'attributes' => array('title' => $item_lv1->getTitle(),
'id_css' => $item_lv1->getIdCss(), 'class_css' => $item_lv1->getClassCss(), 'target' => $item_lv1->getTarget())]);
$cptLv2 = 1;
foreach ($items_lv2 as $item_lv2){
if($item_lv2->getParent()->getUrl() == $item_lv1->getUrl()){
$lv2 = $lv1->addChild($cptLv1.$cptLv2,
['uri' => $item_lv2->getUrl(),'label' => $item_lv2->getLabel(),
'attributes' => array('title' => $item_lv2->getTitle(),
'id_css' => $item_lv2->getIdCss(), 'class_css' => $item_lv2->getClassCss(), 'target' => $item_lv2->getTarget())]);
$cptLv3 = 1;
foreach ($items_lv3 as $item_lv3){
if($item_lv3->getParent()->getUrl() == $item_lv2->getUrl()) {
$lv3 = $lv2->addChild($cptLv1.$cptLv2.$cptLv3,
['uri' => $item_lv3->getUrl(), 'label' => $item_lv3->getLabel(),
'attributes' => array('title' => $item_lv3->getTitle(),
'id_css' => $item_lv3->getIdCss(), 'class_css' => $item_lv3->getClassCss(), 'target' => $item_lv3->getTarget())]);
$cptLv4 = 1;
foreach ($items_lv4 as $item_lv4){
if($item_lv4->getParent()->getUrl() == $item_lv3->getUrl()) {
$lv4 = $lv3->addChild($cptLv1.$cptLv2.$cptLv3.$cptLv4,
['uri' => $item_lv4->getUrl(), 'label' => $item_lv4->getLabel(),
'attributes' => array('title' => $item_lv4->getTitle(),
'id_css' => $item_lv4->getIdCss(), 'class_css' => $item_lv4->getClassCss(), 'target' => $item_lv4->getTarget())]);
$cptLv5 = 1;
foreach ($items_lv5 as $item_lv5){
if($item_lv5->getParent()->getUrl() == $item_lv4->getUrl()) {
$lv4->addChild($cptLv1.$cptLv2.$cptLv3.$cptLv4.$cptLv5,
['uri' => $item_lv5->getUrl(), 'label' => $item_lv5->getLabel(),
'attributes' => array('title' => $item_lv5->getTitle(),
'id_css' => $item_lv5->getIdCss(), 'class_css' => $item_lv5->getClassCss(), 'target' => $item_lv5->getTarget())]);
}
$cptLv4 += 1;
}
}
$cptLv4 += 1;
}
}
$cptLv3 += 1;
}
}
$cptLv2 +=1;
}
$cptLv1+=1;
}
Consider the following:
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,parent_id INT NULL
,level INT NOT NULL
,weight INT NOT NULL
);
INSERT INTO my_table VALUES
(1,null,1,50),
(2,null,1,20),
(3,1,2,100),
(4,1,2,0);
SELECT *,COALESCE(y.level,x.level) my_level,COALESCE(y.weight,x.weight) my_weight FROM my_table x LEFT JOIN my_table y ON y.id = x.parent_id;
+----+-----------+-------+--------+------+-----------+-------+--------+----------+-----------+
| id | parent_id | level | weight | id | parent_id | level | weight | my_level | my_weight |
+----+-----------+-------+--------+------+-----------+-------+--------+----------+-----------+
| 1 | NULL | 1 | 50 | NULL | NULL | NULL | NULL | 1 | 50 |
| 2 | NULL | 1 | 20 | NULL | NULL | NULL | NULL | 1 | 20 |
| 3 | 1 | 2 | 100 | 1 | NULL | 1 | 50 | 1 | 50 |
| 4 | 1 | 2 | 0 | 1 | NULL | 1 | 50 | 1 | 50 |
+----+-----------+-------+--------+------+-----------+-------+--------+----------+-----------+
Extract from that whatever you like.
you do not have to use level and weight ... just use the weight ("order" would be better).
do not worry if id 2 is before or after id 4, because id4 is in id2 (parent level).
an element with parent_id = null is a id with level 0.
think like this :
select Id,parent_id,level ,weight from mytable order by level,weight
Here is a piece of code that allows you, after your select, to have a recursive table that you can browse to display the menus.
It takes into account that an element can be related to "null" (root), and that there can be non-consecutive "weights" ...
the $ result variable is constructed as if you had made a select with a sort on level + weight
<style>
ul {
list-style-type: none;
margin: 0;
padding: 0;
background-color: #D0D0D0;
}
li {
margin-left:2em;
border-left:solid 2px green;
text-align:left;
padding-left:1em;
}
</style>
<?php
/*
* warn ! this array looks like a result after a select, ordered by level+weight
*/
$result=array(
array( 'id'=>2, 'parent_id'=>null, 'level'=>1, 'weight'=>20 ),
array( 'id'=>1, 'parent_id'=>null, 'level'=>1, 'weight'=>50 ),
array( 'id'=>4, 'parent_id'=>1, 'level'=>2, 'weight'=>0 ),
array( 'id'=>3, 'parent_id'=>1, 'level'=>2, 'weight'=>100 ),
array( 'id'=>5, 'parent_id'=>2, 'level'=>2, 'weight'=>40 ),
array( 'id'=>7, 'parent_id'=>5, 'level'=>3, 'weight'=>500 ),
array( 'id'=>6, 'parent_id'=>5, 'level'=>3, 'weight'=>900 )
);
// store recursive array of menus
$menus=array();
// store link of an id in the recursive array of menus
$keysIds=array();
// start with a empty menu
$menus[0]=array('element'=>'ROOT','subMenus'=>array());
$keysIds[0]=&$menus[0];
// build a menus array
foreach ($result as $element) {
$idParent=$element['parent_id'];
$id=$element['id'];
// check for idParent=0 !!
if ($idParent==null) {
$idParent=0;
}
// check if parent exists
// don't forget, result is sorted by level+weight,
// so the idParent is always in array
if (!isset($keysIds[$idParent])) {
echo "<H2>PARENT = $idParent , not exists while INSERTING Id {$id} </H2>";
continue;
}
// JSON index sorting prevention
$max=sizeof($keysIds[$idParent]['subMenus']);
// create a entry
$keysIds[$idParent]['subMenus'][$max]=array('element'=>$element,'subMenus'=>array());
// for next entries, keep this id accessible quickly..it can be a parent.
$keysIds[$id]=&$keysIds[$idParent]['subMenus'][$max];
}
// show the HTML LISTE
htmlMenus($menus,0);
// Recursive iteration on $menus
function htmlMenus($root,$listeLevel) {
echo str_repeat(" ", $listeLevel*2); // beautifull source...
echo "<ul>\n";
foreach ($root as $datas) {
echo str_repeat(" ", $listeLevel*2+2);
echo "<li>\n ";
if ($datas['element']!='ROOT') {
echo str_repeat(" ", $listeLevel*2+2);
echo "ID : {$datas['element']['id']} weight:{$datas['element']['weight']}\n";
}
htmlMenus($datas['subMenus'],$listeLevel+1);
echo str_repeat(" ", $listeLevel*2+2);
echo '</li>';
}
echo str_repeat(" ", $listeLevel*2);
echo "</ul>\n";
}

Laravel 4.2 Multiple Query in date range

I'm trying to get data for each date in range from 3 tables: Main table which is connected with 2 other tables using hasMany method.
Data stored as in example:
Main Table:
id | article title | url | created_at | updated_at |
----------------------------------------------------------------
14 | Some Title | www.example.com | TIMESTAMP | TIMESTAMP |
Views table (there is written count of views for each hour):
id | article_id | views | created_at | updated_at |
---------------------------------------------------
1 | 14 | 317 | TIMESTAMP | TIMESTAMP | (01:00:00)
2 | 14 | 186 | TIMESTAMP | TIMESTAMP | (02:00:00)
Clicks Table (there is written every click on this article):
id | article_id | ip_adress | created_at | updated_at |
---------------------------------------------------------
1 | 14 | 192.168.1.1 | TIMESTAMP | TIMESTAMP |
For example:
I need to get Articles from 01-02-2016 to 01-03-2016.
For every article I need to sum views and clicks for each day.
So in result i need to get something like this:
ID: 14, Title: Some Title, Views: 503, Clicks: 27
First, I wrote this code, but it makes lots of requests to database:
$dates = new DatePeriod($start, new DateInterval('P1D'), $stop);
foreach ($dates as $i => $date) {
$articles = Articles::with(['views' => function ($query) use ($date) {
$query->where('created_at', $date);
}, 'clicks' => function ($query) use ($date) {
$query->where('created_at', $date);
}])->get();
foreach ($articles as $article) {
foreach ($views->countOfViews as $i) {
// Code
}
foreach ($clicks->countOfClicks as $i) {
// Code
}
// Code
}
}
Then I found solution, to get exact same result as I'm getting in first example, but making only three requests:
$dates = new DatePeriod($start, new DateInterval('P1D'), $stop);
$articles = Articles::with(['views' => function ($query) use ($start, $stop) {
$query->whereBetween('created_at', array($start, $stop));
}, 'clicks' => function ($query) use ($start, $stop) {
$query->whereBetween('created_at', array($start, $stop));
}])->get();
foreach ($dates as $date) {
foreach ($articles as $article) {
foreach ($views->countOfViews as $i) if ($date->format('Y-m-d') === $i->created_at->toDateString()) {
// Code
}
foreach ($clicks->countOfClicks as $i) if ($date->format('Y-m-d') === $i->created_at->toDateString()) {
// Code
}
// Code
}
}
It solves problem with too many queries, but it takes to much time. Is it possible to do same thing faster?
Final Code:
$dates = new DatePeriod($start, new DateInterval('P1D'), $stop);
$articles = Articles::with(['views' => function ($query) use ($start, $stop) {
$query->whereBetween('created_at', array($start, $stop))
->groupBy('campaign_id', DB::raw('DATE(created_at)'))
->selectRaw('*, sum(views) as views');
}, 'clicks' => function ($query) use ($start, $stop) {
$query->whereBetween('created_at', array($start, $stop))
->groupBy('campaign_id', DB::raw('DATE(created_at)'))
->selectRaw('*, sum(clicks) as clicks');
}])->get();
foreach ($dates as $date) {
foreach ($articles as $article) {
foreach ($views->countOfViews as $i) if ($date->format('Y-m-d') === $i->created_at->toDateString()) {
// Code
}
foreach ($clicks->countOfClicks as $i) if ($date->format('Y-m-d') === $i->created_at->toDateString()) {
// Code
}
// Code
}
}

laravel REST api post method

im making an api in laravel but when i send from a post request it display nothing it work only when i send the values in the url what im i doing wrong here is my code !
$user = new userInscription;
$user->nom = Request::get('name');
$user->pseudo = Request::get('pseudo');
$user->userId = Request::get('userId');
$user->hasFiat = Request::get('hasFiat');
$user->optin = Request::get('optin');
$user->mail = Request::get('mail');
$pseudo = Input::get('pseudo');
$userId = Input::get('userId');
$hasFiat = Input::get('hasFiat');
if($pseudo == '' || $hasFiat == '' )
{
return Response::json( array(
'status' => 'ko',
'message' => 'missing mandatory parameters')
);
}
else if($userId == '')
{
if( $user->save() )
{
$id = DB::table('user')
->where('pseudo','LIKE',$pseudo)
->pluck('userId');
return Response::json(array(
'status' => 'ok',
'message' => 'success',
'userId' => $id
));
}
else
{
return Response::json(array(
'message' => 'error while saving this user !!',
));
}
}
Laravel REST-ful (Resourceful) controlllers has pre-configured routes (can be re-configured):
According to : http://laravel.com/docs/controllers#resource-controllers
+-----------+---------------------------+---------+------------------+
| Verb | Path | Action | Route Name |
+-----------+---------------------------+---------+------------------+
| GET | /resource | index | resource.index |
| GET | /resource/create | create | resource.create |
| POST | /resource | store | resource.store |
| GET | /resource/{resource} | show | resource.show |
| GET | /resource/{resource}/edit | edit | resource.edit |
| PUT/PATCH | /resource/{resource} | update | resource.update |
| DELETE | /resource/{resource} | destroy | resource.destroy |
+-----------+---------------------------+---------+------------------+
Referencing the table each of the Verb must correspond to the action method in the controller.
For example if your Resourceful Route is registered as:
Route::resource('user', 'userInscriptionController');
Then to POST to user resource, you need to have userInscriptionController#store action (i.e. method called store() in your userInscriptionController.
To avoid manually creating each of these actions, you can use Laravel's artisan controller:make
php artisan controller:make userInscriptionController
which will generate all these actions for you, then you just need to fill in your logic to complete the resource.
From your comment, you are using
Route::resource('user', 'userInscriptionController');
which will generate following routes
Verb | Path | Action | Route Name
------------------------------------------------------------------------
GET | /resource | index | resource.index
GET | /resource/create | create | resource.create
POST | /resource | store | resource.store
GET | /resource/{resource} | show | resource.show
GET | /resource/{resource}/edit | edit | resource.edit
PUT/PATCH | /resource/{resource} | update | resource.update
DELETE | /resource/{resource} | destroy | resource.destroy
And as you can see, the only action allowing post is store. So you should use this one or add post route for an other method like this :
Route::post('your_url', array('as' => 'your_route_name', 'uses' => 'YourController#yourMethod'));
I hope it's clear now
if request is GET then:
if (Request::isMethod('get'))
{
$user = new userInscription;
$user->nom = Request::get('name');
$user->pseudo = Request::get('pseudo');
$user->userId = Request::get('userId');
$user->hasFiat = Request::get('hasFiat');
$user->optin = Request::get('optin');
$user->mail = Request::get('mail');
$pseudo = Input::get('pseudo');
$userId = Input::get('userId');
$hasFiat = Input::get('hasFiat');
if($pseudo == '' || $hasFiat == '' )
{
return Response::json( array(
'status' => 'ko',
'message' => 'missing mandatory parameters')
);
}
else if($userId == '')
{
if( $user->save() )
{
$id = DB::table('user')
->where('pseudo','LIKE',$pseudo)
->pluck('userId');
return Response::json(array(
'status' => 'ok',
'message' => 'success',
'userId' => $id
));
}
else
{
return Response::json(array(
'message' => 'error while saving this user !!',
));
}
}
}
===================
if request is POST then:
if (Request::isMethod('post'))
{
$user = new userInscription;
$user->nom = Request::post('name');
$user->pseudo = Request::post('pseudo');
$user->userId = Request::post('userId');
$user->hasFiat = Request::post('hasFiat');
$user->optin = Request::post('optin');
$user->mail = Request::post('mail');
$pseudo = Input::post('pseudo');
$userId = Input::post('userId');
$hasFiat = Input::post('hasFiat');
if($pseudo == '' || $hasFiat == '' )
{
return Response::json( array(
'status' => 'ko',
'message' => 'missing mandatory parameters')
);
}
else if($userId == '')
{
if( $user->save() )
{
$id = DB::table('user')
->where('pseudo','LIKE',$pseudo)
->pluck('userId');
return Response::json(array(
'status' => 'ok',
'message' => 'success',
'userId' => $id
));
}
else
{
return Response::json(array(
'message' => 'error while saving this user !!',
));
}
}
}

Create multidimensional array from one mysql table

I am trying to generate nested json data like in this example from one mysql table.
var data = {
"62" : {
"section" : "bodyImage",
"img" : "imageurl/image62.png",
"label" : "blue",
"price" : "100"
},
"63" : {
"section" : "bodyImage",
"img" : "imageurl/image63.png",
"label" : "red",
"price" : "120"
}
}
62 and 63 are from the row data_id in the following table:
+-----------+------------+-------------------------+-------+---------+
| data_id | section | img | label | price |
+-----------+------------+-------------------------+-------+----------
| 62 | bodyImage | imagpath/image62.png | blue | 100 |
| 63 | bodyImage | imagpath/image62.png | red | 120 |
+-----------+------------+-------------------------+-------+---------
+
This is the php file with the query:
$result = mysql_query("SELECT data_id, section, img, label, price FROM table WHERE active != 'no'");
$data = array();
while($row=#mysql_fetch_object($result)) {
$data[] = array (
'section' => $row['sub_section'],
'img' => $row['big_image'],
'label' => $row['label_client_en'],
'price' => $row['price']
);
}
echo json_encode( $data );
I cannot get it working. Please help me with the right syntax for the multi-dimensional array.
You cannot json_encode "sub arrays" directly on the main array
You must do json_encode for each array in your while:
$data[] = json_encode(array (
'section' => $row['sub_section'],
'img' => $row['big_image'],
'label' => $row['label_client_en'],
'price' => $row['price']
));
And then you must also encode the main array as you already do.