How to group same values in a parent array? - php

I want to create story for my ios app, I am trying to get useful json response for it. I want to show same user stories in a group inside of that user`s array.
Current JSON RESULT;
{
"current_page": 1,
"data": [
{
"id": 3,
"name": "Muhammed Ali Yüce",
"username": "ali",
"avatar": "1544128196.png",
"stories": {
"id": 3,
"user_id": 3,
"image": "1550228567.jpg",
"created_at": "2019-02-15 11:02:47",
"updated_at": "2019-02-15 11:02:47"
}
},
{
"id": 2,
"name": "Ömer Faruk YÜCE",
"username": "omer",
"avatar": "1544128227.png",
"stories": {
"id": 2,
"user_id": 2,
"image": "1550228407.jpg",
"created_at": "2019-02-15 11:00:08",
"updated_at": "2019-02-15 11:00:08"
}
},
{
"id": 2,
"name": "Ömer Faruk YÜCE",
"username": "omer",
"avatar": "1544128227.png",
"stories": {
"id": 1,
"user_id": 2,
"image": "1550072626.jpg",
"created_at": "2019-02-13 15:43:47",
"updated_at": "2019-02-13 15:43:47"
}
}
],
"first_page_url": "/?page=1",
"from": 1,
"last_page": 1,
"last_page_url": "/?page=1",
"next_page_url": null,
"path": "/",
"per_page": 10,
"prev_page_url": null,
"to": 3,
"total": 3
}
I did tried groupBy func for it but it was not what I excepted.
I want to get result like this;
{
"id": 3,
"name": "Muhammed Ali Yüce",
"username": "ali",
"avatar": "1544128196.png",
"stories": [
{
"id": 2,
"user_id": 3,
"image": "1550228567.jpg",
"created_at": "2019-02-15 11:02:47",
"updated_at": "2019-02-15 11:02:47"
},
{
"id": 3,
"user_id": 3,
"image": "1550228567.jpg",
"created_at": "2019-02-15 11:02:47",
"updated_at": "2019-02-15 11:02:47"
}
]
StoryController.php
<?php
namespace App\Http\Controllers;
use App\Story;
use App\User;
use Illuminate\Http\Request;
use Image;
use Illuminate\Support\Facades\DB;
use Illuminate\Pagination\LengthAwarePaginator;
class StoryController extends Controller
{
public function index(Request $request){
$userId = $request->id;
$followsArr = [$userId];
$follows = DB::table('follows')->whereNotIn('ismuted', [1])->where('follower', $userId)->get();
foreach ($follows as $follow) {
$friend = $follow->following;
$followsArr[] = $friend;
}
$itemCollection = collect($followsArr);
$stories = [];
Story::whereIn('user_id', $itemCollection)
->orderBy('created_at', 'DESC')
->get()->each(function ($story) use (&$stories){
$user = User::where('id', $story->user_id)->first();
$stories[] =
['id' => $user->id]
+ ['name' => $user->name]
+ ['username' => $user->username]
+ ['avatar' => $user->avatar]
+ ['stories' => $story->toArray()];
});
// Get current page form url e.x. &page=1
$currentPage = LengthAwarePaginator::resolveCurrentPage();
// Create a new Laravel collection from the array data
$itemCollection = collect($stories);
// Define how many items we want to be visible in each page
$perPage = 10;
// Slice the collection to get the items to display in current page
$currentPageItems = $itemCollection->slice(($currentPage * $perPage) - $perPage, $perPage)->all();
// Create our paginator and pass it to the view
$paginatedItems= new LengthAwarePaginator($currentPageItems , count($itemCollection), $perPage);
return response()->json($paginatedItems);
}
I hope you will understand what I mean, Thanks in advance :)

Assume you have User.php and Story.php Models
In User.php
public function stories()
{
return $this->hasMany(Story::class);
}
You can load story along with user. something like that
$user = User::where('id', $story->user_id)->with('stories')->first(); //Eager Load
or
$user = User::where('id', $story->user_id)->first();
$user->load('stories'); //Lazy Eager Load
Please read more about Laravel Eloquent: Relationships

Related

Select * from a pivot table in laravel

I have a many to many relation with table users,items and the pivot table user_item and i need to call the query : Select * from user_item where user_id=$user->id in laravel and return the results in json format. I try with
$user=User::find(session('user_id'))->items()->get();
return response ()->json($user);
But it doesn't work. How can I do that?
class User extends Authenticatable {
public function items (){
return $this->belongsToMany ("App\Models\Item", "user_item", "user", "item");
}
}
class Item extends Models {
public function users (){
return $this->belongsToMany ("App\Models\User", "user_item", "item", "user");
}
}
You can define columns in your pivote table using withpivot method
public function items (){
return $this->belongsToMany ("App\Models\Item", "user_item",
"user", "item")->withPivot(['column1', 'column2','another_column']);
}
to get relation instead of using get(), you should use like below:
$user=User::find(session('user_id'))->items;
return response ()->json($user);
above will give below json result:
[{
"id": 4,
"name": "PC",
"pivot": {
"column1": 1,
"column2": 4,
"another_column": "2016-03-03"
}
},
{
"id": 5,
"name": "Phone",
"pivot": {
"column1": 1,
"column2": 4,
"another_column": "2016-03-03"
}
}]
you can also include pivot in use user model using with():
$user=User::with('items')->find(session('user_id'));
return response ()->json($user);
give json result something like:
{
"id": 1,
"name": "User Name",
"email": "email#user.com",
"created_at": null,
"updated_at": null,
"items": [{
"id": 4,
"name": "PC",
"pivot": {
"column1": 1,
"column2": 4,
"another_column": "2016-03-03"
}
},
{
"id": 5,
"name": "Phone",
"pivot": {
"column1": 1,
"column2": 4,
"another_column": "2016-03-03"
}
}]
}]

Laravel : using where inside (with Model)

I have this Controller :
public function user_predects()
{
$matches=Match::with('Predect')->get();
return ($matches);
}
and it is get json data like this :
[
{
"id": 1,
"m_date": "2021-02-06 22:00:00",
"home": "Turkey",
"away": "Italy",
"h_goals": 0,
"a_goals": 0,
"predect": [
{
"id": 3,
"user_id": 10,
"match_id": 1,
"h_predect": 1,
"a_predect": 1,
"player_id": 1,
"point": 0,
"created_at": null,
"updated_at": null
},
{
"id": 4,
"user_id": 9,
"match_id": 1,
"h_predect": 2,
"a_predect": 1,
"player_id": 1,
"point": 0,
"created_at": null,
"updated_at": null
Now I want to view same json data but just for one user ,I used this but don't works :
public function user_predects($username)
{
$user = User::where('username',$username)->get()
$matches=Match::with('Predect')->where('Predect.user_id',$user[0]->id)->get();
return ($matches);
}
How can I view matches model with predect model for one user?
Try this one:
public function user_predects($username)
{
$user = User::where('username',$username)->first()
$matches = Match::with(['Predect' => function($query) use ($user) {
return $query->where('Predect.user_id', $user->id);
}])->get();
return ($matches);
}
You can also read about constraining Eager Loading from the official documentation: Constraining Eager Loads

Getting Duplicate Data on Response On Laravel Eloquent

I am new in laravel in php. So it might be very silly mistake. I have song table and song categories table. I am trying to fetch all category with their respective songs. I have implemented larvel eloquent one to many relationship between song category and song.
Here is my code of fetching data:
public function getSongCategoriesWithSongs(){
$json_array = array();
$song_categories = SongCategory::all();
foreach ($song_categories as $item) {
# code...
$json = [];
$json['category'] = $item;
$json['songs'] = $item->songs;
array_push($json_array,$json);
}
return $json_array;
}
Here is response:
[{
"category": {
"id": 1,
"title": "Rock",
"created_at": "2020-12-20T02:58:32.000000Z",
"updated_at": "2020-12-20T02:58:32.000000Z",
"songs": [{
"id": 1,
"title": "Mere Mehboob",
"thumbnail": "https:\/\/static.toiimg.com\/photo\/msid-71407401\/71407401.jpg?108311",
"song_category_id": 1,
"stream_link": "https:\/\/2u039f-a.akamaihd.net\/downloads\/ringtones\/files\/mp3\/mere-mehboob-qayamat-hogi-52150.mp3",
"created_at": "2020-12-20T13:26:30.000000Z",
"updated_at": "2020-12-20T13:26:30.000000Z"
}, {
"id": 2,
"title": " Taaron Ke Shehar",
"thumbnail": "https:\/\/static.toiimg.com\/photo\/msid-71407401\/71407401.jpg?108311",
"song_category_id": 1,
"stream_link": "https:\/\/newmp3ringtones.net\/assets\/sass\/Ringtones\/TaaronKeSheharRingtoneByNehaKakkarJubinNautiyal2145436126.mp3",
"created_at": null,
"updated_at": null
}, {
"id": 3,
"title": "Bewafa Tera Masoom Chehra",
"thumbnail": "https:\/\/static.toiimg.com\/photo\/msid-71407401\/71407401.jpg?108311",
"song_category_id": 1,
"stream_link": "https:\/\/newmp3ringtones.net\/assets\/sass\/Ringtones\/BewafaTeraMasoomChehraRingtoneByJubinNautiyal352778308.mp3",
"created_at": null,
"updated_at": null
}]
}
}, {
"songs": [{
"id": 1,
"title": "Mere Mehboob",
"thumbnail": "https:\/\/static.toiimg.com\/photo\/msid-71407401\/71407401.jpg?108311",
"song_category_id": 1,
"stream_link": "https:\/\/2u039f-a.akamaihd.net\/downloads\/ringtones\/files\/mp3\/mere-mehboob-qayamat-hogi-52150.mp3",
"created_at": "2020-12-20T13:26:30.000000Z",
"updated_at": "2020-12-20T13:26:30.000000Z"
}, {
"id": 2,
"title": " Taaron Ke Shehar",
"thumbnail": "https:\/\/static.toiimg.com\/photo\/msid-71407401\/71407401.jpg?108311",
"song_category_id": 1,
"stream_link": "https:\/\/newmp3ringtones.net\/assets\/sass\/Ringtones\/TaaronKeSheharRingtoneByNehaKakkarJubinNautiyal2145436126.mp3",
"created_at": null,
"updated_at": null
}, {
"id": 3,
"title": "Bewafa Tera Masoom Chehra",
"thumbnail": "https:\/\/static.toiimg.com\/photo\/msid-71407401\/71407401.jpg?108311",
"song_category_id": 1,
"stream_link": "https:\/\/newmp3ringtones.net\/assets\/sass\/Ringtones\/BewafaTeraMasoomChehraRingtoneByJubinNautiyal352778308.mp3",
"created_at": null,
"updated_at": null
}]
}, {
"category": {
"id": 2,
"title": "Soft",
"created_at": null,
"updated_at": null,
"songs": []
}
}, {
"songs": []
}]
As you can see songs get repeated.
UPDATE
Solved using eager loading
public function getSongCategoriesWithSongs(){
return SongCategory::with('songs')->get();
}
But don't know why the foreach method not working.
Try this code
public function getSongCategoriesWithSongs(){
$json_array = array();
$song_categories = SongCategory::all();
foreach ($song_categories as $item) {
$json_array[] = ['category' => $item, 'songs' => $item->songs] ;
}
return $json_array;
}
The problem is that you assign the same relation twice.
Each SongCategory already has a collection of songs inside.
So in your foreach block, you assign a category with $json['category'] => $item which will load all related songs and pass them to the final JSON object. And you duplicate this by passing the next item $json['songs'] = $item->songs to the same array. Default Laravel behavior will be to fetch all related objects and transform them into JSON.
I would suggest you to use Laravel resources to return JSON objects with exact shapes: API Resources.
You can fix your code block without eager loading by removing $json['songs'] = $item->songs assignment.
Eager loading works because you passed all your objects only once.

Laravel pass parameter to its distant relationship (translate children)

I have categories with id, parent_id, slug , pivot table category_language which columns are id,category_id,language_id,value
As you can see I can translate parent category, but can't send desired $lang_id to children translations, so each children having all translations
here is what I get:
{
"id": 1,
"parent_id": 0,
"slug": "personal-computers",
"created_at": "2019-12-27 15:05:31",
"updated_at": "2019-12-27 15:05:31",
"children": [
{
"id": 3,
"parent_id": 1,
"slug": "accessories-for-pc",
"created_at": "2019-12-27 15:05:32",
"updated_at": "2019-12-27 15:05:32",
"translations": [
{
"id": 1,
"code": "en",
"name": "English",
"pivot": {
"category_id": 3,
"language_id": 1,
"value": "Acc for PC",
"id": 7
}
},
{
"id": 2,
"code": "ru",
"name": "Русский",
"pivot": {
"category_id": 3,
"language_id": 2,
"value": "Аксессуары для ноутбуков и ПК",
"id": 8
}
},
{
"id": 3,
"code": "ro",
"name": "Romana",
"pivot": {
"category_id": 3,
"language_id": 3,
"value": "aksessuari-dlya-noutbukov-i-pk-ro",
"id": 9
}
}
]
}
],
"translations": [
{
"id": 1,
"code": "en",
"name": "English",
"pivot": {
"category_id": 1,
"language_id": 1,
"value": "PC",
"id": 1
}
}
]
}
Controller:
return Category::with('children')
->with(array('translations'=>function($query) use ($lang_id){
$query->where('language_id',$lang_id);
}))
->where('parent_id',0)->first();
Model
class Category extends Model
{ ..
public function translations()
{
return $this->belongsToMany('App\Models\Translation','category_language', 'category_id' ,'language_id' )->withPivot('value','id');
}
public function children()
{
return $this->hasMany( 'App\Models\Category' , 'parent_id' , 'id' )->with('translations');
}
}
you can add condition in children method
public function children()
{
return $this->hasMany( 'App\Models\Category' , 'parent_id' , 'id' )->with('translations')->where('language_id', 1);
}
Dry7 answer was close to the one I've implemented later, so I upvoted him.
Finally in model I've added: ...->where('language_id',helper_SetCorrectLangIdForQuery());
and function helper_SetCorrectLangIdForQuery is using global helper of Laravel request()->lang . If lang=enz, than it takes default language from another helper.

Add data into laravel object

so i have this kind of class from my user controller
public function index()
{
$table_data = User::with('CU','pus')->select('id','id_cu','id_pus','name','username','gambar','status','created_at')->filterPaginateOrder();
return response()
->json([
'model' => $table_data
]);
}
it is using trait called filterPaginateOrder and the end result that i receive are:
{
"model": {
"current_page": 1,
"data": [
{
"id": 8,
"id_cu": 0,
"id_pus": 1,
"name": "test1",
"username": "test17",
"gambar": "",
"status": 1,
"created_at": "2018-02-27 06:37:10",
"c_u": null,
"pus": {
"id": 1,
"name": "Puskopdit BKCU Kalimantan"
}
},
{
"id": 1,
"id_cu": 0,
"id_pus": 1,
"name": "tony",
"username": "t0n1zz",
"gambar": null,
"status": 1,
"created_at": "2017-01-01 11:11:11",
"c_u": null,
"pus": {
"id": 1,
"name": "Puskopdit BKCU Kalimantan"
}
}
],
"from": 1,
"last_page": 1,
"next_page_url": null,
"path": "https://bkcuvue.dev/api/v1/user",
"per_page": "2",
"prev_page_url": null,
"to": 2,
"total": 2
}
}
so what if i want to add some data into it? inside data array for each array i want to add "role":"master" how do i do that?
i tried $table_data->push('role','master') and $table_data->put('role','master') from reading about collection (those query in laravel return collection right?) but none of those code working...
There are two ways to go about it.
Add it via a foreach
$table_data = User::with('CU','pus')->select('id','id_cu','id_pus','name','username','gambar','status','created_at')->filterPaginateOrder();
foreach($table_data->data as $data) {
$data->role = 'master';
}
Or add it into the SELECT:
$table_data = User::with('CU','pus')->select('id','id_cu','id_pus','name','username','gambar','status','created_at', DB::raw('"master" as role'))->filterPaginateOrder();
Or you can override collection data of paginator object.
$table_data = User::with('CU','pus')->select('id','id_cu','id_pus','name','username','gambar','status','created_at')->filterPaginateOrder();
$table_data->getCollection()->each(function($user) {
$user->role = 'master';
});
return response()->json([
'model' => $table_data
]);

Categories