I am trying to loop through two joined tables of data. One table is an image collection and another is the images. The images have a foreign key to collection.
My question is, how do I achieve the following in my view?
foreach ($collections as $collection) {
echo '<ul>';
foreach ($collection->image as $image) {
echo '<li><img src="'.$image->url.'" /></li>';
}
echo '</ul>';
}
I am currently using this in the controller:
class Collection extends CI_Controller {
public function index()
{
$this->load->model('Collection_model');
$data['collections'] = $this->Collection_model->get_latest_collections();
$this->load->view('collection_view.php', $data);
}
}
And have the following model:
class Collection_model extends CI_Model {
function get_latest_collections()
{
$this->db->select('*');
$this->db->from('photo');
$this->db->join('collection', 'photo.collection_id = collection.id');
$this->db->order_by("collection.date_created", "DESC");
$query = $this->db->get();
return $query->result();
}
}
The problem with the above is that when I loop through the collection results I am actually looping directly through all the images. I am having to put some logic into the view to check to see if the collection id has changed to put in the . This means that I can't use next() and prev() to get the next and previous collection as the loop is looping through the images and next() and prev() gives the next and previous image rather than the next and previous collection.
If i well understood your question, you want loop on your photos and organize them by collections.
There are several ways to achieve that, but this cannot be by a join query because the tables relation is one(collection) to many (photos).
Solution 1: You want show all your photos
//get all collections
$collections = $this->db
->order_by("date_created", "DESC")
->get('collection')
->result();
//get all photos
$photos = $this->db
->get('photo')
->result();
Solution 2: you want show some collections
//get some collections
$collections = $this->db
//->where('..', '..') //some filtering
->order_by("date_created", "DESC")
->get('collection')
->result();
//extract ids
$collection_ids = array();
foreach($collections as $collection)
{
$collection_ids[] = $collection->id;
}
//get photos who are in these collections
$photos = $this->db
->where_in('collection_id', $collection_ids)
->get('photo')
->result();
In your view
The two solutions above work with this code.
//loop on collections
foreach($collections as $collection)
{
//<ul>..
foreach($photos as $photo)
{
if($photo->collection_id == $collection->id)
{
//<li>..$photo->url..
}
}
//</ul>..
}
Or to have exactly what you expected in your first block of code
//loop on collections
foreach($collections as $collection)
{
$collection->images = array();
foreach($photos as $photo)
{
if($photo->collection_id == $collection->id)
{
$collection->images[] = $photo;
}
}
}
//so in your view (what you expected)
foreach($collections as $collection)
{
//<ul>..
foreach($collections->images as $image)
{
//<li>..$image->url..
}
//</ul>..
}
But this last code implies to loop twice.
Related
I am trying to create Laravel/Vue project with two models: Category and Article. Vue part haves tree-view, which will display categories and articles tree. Categories may belong to another categories, Article may belong only to Article.
How can i form json tree from these relations?
model Category
public function articles() {
return $this->hasMany(Article::class);
}
public function childs() {
return $this->hasMany(Category::class)->union($this->files()->toBase());
}
but it shows The used SELECT statements have a different number of columns, because there is defferent fields in results.
One solution i see here is to find every article and post and create array, then jsonify it. Maybe any better solutions?
UPDATE
Done it with this code (in api controller):
public function nodes() {
$rootCategories = Category::where('category_id', null)->get();
$out = $this->_nodes($rootCategories);
return response()->json($out);
}
private function _nodes($eCategories) {
$out = [];
foreach($eCategories as $cat) {
$out[$cat->id] = $cat->toArray();
$out[$cat->id]["type"] = "folder";
$out[$cat->id]["childs"] = [];
foreach ($cat->articles as $article) {
$out[$cat->id]["childs"][$article->id] = $article->toArray();
$out[$cat->id]["childs"][$article->id]["type"] = "article";
}
if ($cat->categories) {
$out[$cat->id]["childs"] = $out[$cat->id]["childs"] + $this->_nodesCategory($cat->categories);
}
}
return $out;
}
I have an array of category , and this categories have many books (belongToMany) how i can get all book
sorry about my English
category model
class category_b extends Model
{
protected $table = 'categoryb';
protected $attributes = array(
'lang'=> 'fa',
);
public function getBooks()
{
return $this->belongsToMany('App\book','categoryb_book');
}
}
my book model
class book extends Model
{
public function getCategory()
{
return $this->belongsToMany('App\category_b','categoryb_book');
}
}
my code
$Category = $user->subscriptions(category_b::class)->pluck('id');
$bookCategory= category_b::whereIn('id',$Category)->get();
$bookCategory = $bookCategory->getBooks;
As #Makdous indicated, different approaches exist, you may take the one that fits your need.
Notice that the loop approach may lead to duplicate books, so after the loop you will have to delete duplicate records.
To avoid that problem, one solution would be to query the Book model directly:
$categoryIds = $user->subscriptions(category_b::class)->pluck('id');
$books = book::whereHas('getCategory', function ($q) use ($categoryIds) {
return $q->whereIn('categoryb.id', $categoryIds);
})
->get();
EDIT:
You may go beyond that and improve the readability of your code by defining a local scope.
In your Book class:
class book extends Model
{
// .....
// .....
// Somewhere in your Book class ...
public function scopeOfCategories($query, $categoryIds = [])
{
return $query->whereHas('getCategory', function ($q) use
($categoryIds) {
return $q->whereIn('categoryb.id', $categoryIds);
});
}
}
Now you can replace the old code snippet with the following:
$categoryIds = $user->subscriptions(category_b::class)->pluck('id');
$books = book::ofCategories($categoryIds)->get();
You can use a foreach as mentioned in the docs to iterate through the books of you're fetched category.
foreach ($bookCategory as $book) {
//access book's attributes
}
Or likewise you can get the categories of a certain book.
$book = Book::find($id);
$categories = $book->getCategory();
foreach ($categories as $category) {
//access category's attributes
}
I am trying to retrieve the data on my wishlist table, for a particular user, so far it only retrieves the first data on the table, just returning one array instead of the three in the table with same user id
public function getWishlistByUserId($id){
$wishlists = Wishlist::where('userId', $id)->get();
foreach($wishlists as $wishlist){
$products = Product::where('id', $wishlist->productId)->get();
return $products;
}
}
It happens because the foreach loop returns a value during the first iteration. Place your return statement outside the loop. Also you could improve your performence by making use of relationships.
An example could be:
// Product.php
public function wishlists()
{
return $this->hasMany(Wishlist::class);
}
// Your method
public function getWishlistByUserId($id)
{
return Product::whereHas('wishlists', function ($query) use ($id) {
$query->where('userId', $id);
});
}
Ideally this is n+1 situation
So i will suggest to use laravel relationship like:
in your whishlist model
public function product(){
return $this->hasMany(Product::class,'productId','id');
}
get data with relationship
public function getWishlistByUserId($id){
$wishlists = Wishlist::with('product')->where('userId', $id)->get();
}
I was finally able to get it working this way, i just pushed the result into an array, and then returned it outside the loop, thanks everyone for your help
public function getWishlistByUserId($id){
$wishlists = Wishlist::where('userId', $id)->get();
$wishlist = [];
foreach($wishlists as $wish){
$product = Product::where('id', $wish->productId)->get();
array_push($wishlist, $product);
}
return $wishlist;
}
protected function show()
{
$users = User::all();
$letters = Letter::with('user');
$userLetter = $letters->where(['user_id' => 2])->count();
//Here function work right. Shows that we have 10 users
foreach ($users as $user) {
$userLetter = $letters->where(['user_id' => $user->id])->first();
if($userLetter){
//Here it shows that only the first user exists, returns null for the rest users.
}
}
}
We get an error when we sort the array with foreach.
No record is found in the database except the first.
For other entries, return null.
outside foreach no errors.
Just move your object inside the loop like below.
protected function show()
{
$users = User::all();
$userLetter = $letters->where(['user_id' => 2])->count();
//Here function work right. Shows that we have 10 users
foreach ($users as $user) {
$userLetter = Letter::with('user')->where(['user_id' => $user->id])->first();
if($userLetter){
}
}
}
You would probably be better off using a letter relationship on the User.
On the User model you could do something like :
public function letter()
{
return $this->hasOne(Letter::class, 'user_id');
}
Then you could in the controller:
protected function show()
{
$users = User::with('letter')->get();
foreach ($users as $user) {
if ($user->letter) {
// do things
}
}
}
I am developing an online ecommerce for the first time and currently, i am not able to iterate through my collection.
Every item for a shop is categorized into a product category. My relationship is below
Category
public function items()
{
return $this->belongsToMany('App\Item','category_item','category_id','item_id')
->withTimestamps();
}
Items
public function categories()
{
return $this->belongsToMany('App\Category','category_item','item_id','category_id')
->withTimestamps();
}
This code here is able to fetch the groups and their products. I try to loop through to get the names of the products like below but it only displays the name of the last product in the database.
Why is this happening?
ItemController
//get id of product categories and display all products in grid table
$items_in_table = Category::whereIn('id',$request->get('product_category'))->with('products')->get();
foreach($items_in_table as $item)
{
return $item->name;
}
update
$temp
foreach($items_in_table as $item)
{
temp = $item;
}
return $temp
response
{"id":2,"title":"freight","no_of_contacts":0,"user_id":1,"created_at":"2018-04-15 23:55:30","updated_at":"2018-04-15 23:55:30","items":[{"id":1,"name":"AirBag ","phone":"0247878234","group_id":null,"user_id":1,"created_at":"2018-04-16 00:14:20","updated_at":"2018-04-16 05:31:05","pivot":{"group_id":2,"customer_id":1,"created_at":"2018-04-16 05:33:08","updated_at":"2018-04-16 05:33:08"}}
enter image description here
let's define our relationships first
Category:
public function items()
{
return $this->belongsToMany('App\Item')
->withTimestamps();
}
Item:
public function categories()
{
return $this->belongsToMany('App\Category')
->withTimestamps();
}
then in your controller:
$items_in_table = Category::with('items')->get();
$names = [];
foreach($items_in_table as $category) {
foreach($category->items as $item) {
$names[] = $item->name;
}
}
dd($names);
Maybe you need to put it in an array and then rotate it
$items_in_table = Category::whereIn('id',$request->get('product_category'))->with('products')->get();
$name = [];
foreach($items_in_table as $item)
{
$name[] = $item->name;
}
return $name;
foreach will not manipulate the values of the array
Some possible solutions:
Use a reference, this will change the values in $items_in_table
foreach($items_in_table as &$item)
{
$item = $item->name;
}
Use map (since it is an Laravel-collection), this will also alter the array
$items_in_table->map(function ($item) {
return $item->name;
})
you can Access any relation like this way .
For View what is you are getting. you can also use dd($item->quoteReturnDetail)
return collect($models->items())->transform(function ($item, $index){
if( $item->quoteReturnDetail){ dd($item->quoteReturnDetail); } });