Laravel - Can't use a manyToMany method after join - php

I've a strange behavior of Laravel when I'm trying to use a belongsToMany method, only after a join.
I've these classes: Meeting, Order, Organizer, User and Product
and these pivot tables: meeting_organizer, order_product, organizer_user
And this is order class
class Order extends \Eloquent {
public function meeting(){
return $this->belongsTo('Meeting');
}
public function state(){
return $this->belongsTo('OrderState', 'order_state_id');
}
public function products(){
return $this->belongsToMany('Product')->withPivot('qty');
}
public function sellers(){
$meeting = $this->meeting()->first();
if($meeting) return $meeting->sellers()->get();
else return array();
}
public function organizers(){
$meeting = $this->meeting()->first();
if($meeting) return $meeting->organizers()->get();
else return array();
}
When I use
$data['records'] = Order::all();
and then this loop:
foreach( $data['records'] as $r ){
if($r->meeting){
$r->meeting_date = $r->meeting->date;
$r->meeting_name = $r->meeting->name;
}
$r->status = $r->state->name;
$r->delivery_date = date_format(date_create($r->delivery_date), 'm-d');
$r->seller = '';
foreach( $r->sellers() as $s) $r->seller .= $s->name.', ';
$r->organizer = '';
foreach( $r->organizers() as $o) $r->organizer .= $o->name.', ';
$r->product = '';
foreach( $r->products as $p) $r->product .= $p->pivot->qty ." x ". $p->name.'<br />';
}
works well.
But if I use this join
$data['records'] = Order
::join('meeting_organizer', 'orders.meeting_id', '=', 'meeting_organizer.id')
->join('organizer_user', 'meeting_organizer.organizer_id', '=', 'organizer_user.organizer_id')
->where('organizer_user.user_id', '=', Auth::user()->id)->get();
the loop doesn't return any products.
So, I don't get any error, only an empty result.
If I try to print on screen inside my loop $r->id the result is wrong and the same number for all records, but all of other properties are correct.

Related

Codeigniter 4 pagination on function in model

I'm currently stuck with the built-in pagination of CI4.
I try to paginate the results of a function in my model, which does not work:
My model:
<?php
namespace App\Models;
use CodeIgniter\Model;
class CategoriesModel extends Model
{
protected $table = 'categories';
protected $allowedFields = [];
protected $beforeInsert = ['beforeInsert'];
protected $beforeUpdate = ['beforeUpdate'];
//Kategorie(n) laden
public function getCategories($categoryID = null)
{
$db = \Config\Database::connect();
if (!$categoryID) {
$builder = $db->table('categories');
$query = $builder->get();
$results = $query->getResultArray();
} else {
$builder = $db->table('categories');
$query = $builder->where('categoryID', $categoryID);
$query = $builder->get();
$results = $query->getRow();
}
return $results;
}
}
In my controller, i try to paginate the results of the "getCategories"-function from the model:
<?php
namespace App\Controllers;
use App\Models\CategoriesModel;
use App\Models\PodcastsModel;
class Categories extends BaseController
{
public function index($page = 1)
{
$this->request->setLocale(session()->get('locale'));
//Helper laden
helper(['form', 'template', 'userrights']);
$data['template'] = getTemplate();
$model = new CategoriesModel;
$data['categories'] = $model->getCategories()->paginate(5, 'test', $page, 2);
$data['pager'] = $model->pager;
//Recht "13" (Benutzergruppen) prüfen
if ($data['userrights'][13] == 0) {
return redirect()->to('/admin');
}
//Views aufbauen
echo view($data['template'] . '/templates/header', $data);
echo view($data['template'] . '/backend/navigation');
echo view($data['template'] . '/templates/sidebar');
echo view($data['template'] . '/backend/categories');
echo view($data['template'] . '/templates/footer');
}
}
So the line
$data['categories'] = $model->getCategories()->paginate(5, 'test', $page, 2);
will cause the following error:
Error
Call to a member function paginate() on array
When i use
$data['categories'] = $model->paginate(5, 'test', $page, 2);
it works just fine. But it paginates ALL results from the categories table, as declared in the model.
But as i want to paginate the results from the function, depending on variables i pass to the model,
Is there a way to use the pagination class for model-functions?
You're not using the paginate library correctly. It must be used at the end of your query builder instead of a get() for example.
Your model could return the paginate object.
public function getCategories($nb_paginate, $categoryID = null)
{
$db = \Config\Database::connect();
if (!$categoryID) {
$results = $this->paginate($nb_paginate);
} else {
$results = $this->where('categoryID', $categoryID)->paginate($nb_paginate);
}
return $results;
}
And then catch it with your controller
$data['categories'] = $model->getCategories(5);
$data['pager'] = $model->pager;
You might want to give a look at the doc aswell : https://codeigniter.com/user_guide/libraries/pagination.html
No idea if this is "valid code" (i'm new to this formal CI4 models namespaces etc). But this works fine for me. Just make sure to filter your "search" in production properly for security
Controller:
$filter['search'] = $this->request->getGet('search');
$this->template->data['customers'] = $customer_model->get_customers_index($filter)->paginate(50);
$this->template->data['pager'] = $customer_model->pager;
Model:
function get_customers_index($filter)
{
if (isset($filter['search']) and $filter['search'])
{
$this->like('id_number', $filter['search']);
}
return $this;
}

Complex query and getting results by slug instead of ID in laravel

I have complex query and relation which I'm not fully understand. I'm kind of new in Laravel. Anyway, I'm looking for a way to load this with slugs instead of ID's.
This is the function in the controller
public function index( $category_id)
{
$Category = new Category;
$allCategories = $Category->getCategories();
$category = Category::find($category_id);
if($category->parent_id == 0) {
$ids = Category::select('id')->where('parent_id', $category_id)->where('parent_id','!=',0)->get();
$array = array();
foreach ($ids as $id) {
$array[] = (int) $id->id;
}
$items = Item::whereIn('category_id',$array)->where('published', 1)->paginate(5);
} else {
$items = Item::where('category_id' ,$category_id)->where('published', 1)->paginate(5);
}
return view('list', compact('allCategories','items'));
}
Those are relations in the Model
public function item()
{
return $this->hasMany('App\Item','category_id');
}
public function children()
{
return $this->hasMany('App\Category', 'parent_id');
}
public function getCategories()
{
$categoires = Category::where('parent_id',0)->get();
$categoires = $this->addRelation($categoires);
return $categoires;
}
public function selectChild( $id )
{
$categoires = Category::where('parent_id',$id)->where('published', 1)->paginate(40);
$categoires = $this->addRelation($categoires);
return $categoires;
}
public function addRelation( $categoires )
{
$categoires->map(function( $item, $key)
{
$sub = $this->selectChild($item->id);
$item->itemCount = $this->getItemCount($item->id , $item->parent_id );
return $item = array_add($item, 'subCategory', $sub);
});
return $categoires;
}
public function getItemCount( $category_id )
{
return Item::where('category_id', $category_id)->count();
}
This is what I have in my routes
Route::get('list/{category}', 'ListController#index')->name('list');
currently is loading urls like http://example.com/list/1 where 1 is the ID. I'm wonder if with current setup is possible to make it like, http://example.com/slug
I'm aware how slugs are working. I just can't understand how to use them in queries instead of ID's
You can use explicit Route Model Binding to grab your Category by slug before processing it.
In your RouteServiceProvider you need to bind the model:
Route::bind('category', function ($value) {
//Change slug to your column name
return App\Category::where('slug', $value)->firstOrFail();
});
Then, you can typehint the categories.
For example in your index method:
public function index(Category $category)
{
$Category = new Category;
$allCategories = $Category->getCategories();
//This line is obsolete now:
//$category = Category::find($category_id);
//...
}
Try to change your index function parameter from $category_id to $category_slug
Remove this line $Category = new Category;
And change this $category = Category::find($category_id);
To this: $category = Category::where('slug', $category_slug)->first();
*Assuming that you have a unique slug in category table

searching in belongsToMany relationship in laravel 5

Actually i want to search those question which user want to search after select any subject or course.
if a remove either whereHas from subject or course its works but with both its not working.
Please give a better solution for searching in belongsToMany realtionship.
i have a question table with Question model class
class Question extends Model{
public function courses(){
return $this->belongsToMany('App\Models\Course','course_questions');
}
public function subjects(){
return $this->belongsToMany('App\Models\Subject','subject_questions');
}
}
and in my searchController
public function index(Request $request){
$questions = Question::with(['user','courses','branches','subjects','years','universities','question_type'])
->where("status","=",1)
->where(function($query) use($request){
$q = $request->q;
if(isset($q) && !is_null($q)){
$query->where("question","LIKE","%$q%");
}
})
->whereHas('subjects',function($query) use($request){
$subjects = $request->subject;
if(isset($subjects)){
$_subjects = explode(" ",$subjects);
$query->whereIn("slug",$_subjects)
->orWhereIn("subject_name",$_subjects);
}
})
->whereHas('courses',function($query) use($request){
$course = $request->course;
if(isset($course)){
$_course = explode(" ",$course);
$query->whereIn("slug",$_course)
->orWhereIn("course",$_course);
}
})
->paginate();
if($request->ajax()){
$returnHTML = view('questions.question_list')->with('questions', $questions)->render();
return response()->json(array('success' => true, 'pageContent'=>$returnHTML));
}
You should build your query probably this way - you should verify conditions before adding any constraints to your query:
$query = Question::with(['user','courses','branches','subjects','years','universities','question_type'])
->where("status","=",1);
$q = $request->q;
if(isset($q) && !is_null($q)) {
$query = $query->where("question","LIKE","%$q%");
}
$subjects = $request->subject;
if (isset($subjects)) {
$query = $query->whereHas('subjects',function($query) use($subjects){
$_subjects = explode(" ",$subjects);
$query->whereIn("slug",$_subjects)
->orWhereIn("subject_name",$_subjects);
});
}
$course = $request->course;
if (isset($course)) {
$query = $query->whereHas('courses',function($query) use($course ){
$_course = explode(" ",$course);
$query->whereIn("slug",$_course)
->orWhereIn("course",$_course);
});
}
$questions = $query->paginate();
$products = Product::query()->
WhereHas('categories', function ($q) use ($keyword) {
$q->where('products.name', $keyword)
->orWhere('categories.name', $keyword);
})->get();
This is how I have used in my project

laravel eloquent : Increments visits column by one for every visits

I have model for my post in my site.My post model has a column that stores visits.when user visit my post should increments by 1.
I exactly knows how to do this, but my problem is when I increment it by one in my model, it's increments by 2!!!!!
I wrote this code in my controller:
$new_post_inst = Post::where('id','=',$id)->first();
$new_post_inst->increment('visit');
This is my controller:
public function get_id($id) {
// cat
$cat = Category::join('catrelations', 'catrelations.idcat', '=', 'categories.id')->orderBy('categories.id', 'ASC')->get();
// menu
$nav = Nav::orderBy('index', 'DESC')->get();
$post = Post::find($id);
$setting = Settings::find(1);
$comments = Comment::where('post_id', '=', $id)->orderBy('id', 'asc')->get();
$get_reply = array();
$get_reply_id = array();
//$counter = 0;
//var_dump($comments);
foreach ($comments as $comment) {
$reply = Reply::where('parentId', '=', $comment->id)->get();
if (!$reply->isEmpty()) {
//$arr_reply[$comment->id] = $reply;
//echo $comment->id.' has reply!!!!!<br>';
//$reply_parent_id = $comment->id;
$counter = 0;
foreach ($reply as $replying) {
$get_reply[$comment->id][$counter] = Comment::where('id', '=', $replying->comment_id)->get();
//$comment_reply_id = $replying->comment_id;
//$reply_arr = array();
//$reply_arr[$comment->id] = $comment_reply_id;
//echo 'The reply is: '.$comment_reply_id.'<br>';
foreach ($get_reply[$comment->id][$counter] as $key => $value) {
//($value->text);
$get_reply_id[] = $value->id;
}
$counter++;
}
//$counter++;
}
}
$post_owner_info = User::select('id', 'first_name', 'last_name', 'image', 'desc')->find($post->user_id);
$arr = array();
$arr['comments'] = $comments;
$arr['post'] = $post;
//$arr['reply'] = $reply;
//var_dump($get_reply);
//var_dump($get_reply_id);
$new_post_inst = Post::where('id','=',$id)->first();
$new_post_inst->increment('visit');
return View::make('blogsingle', compact('arr'))->with('setting', $setting)->with('post', $post)->with('nav', $nav)->with('get_reply', $get_reply)->with('get_reply_id', $get_reply_id)->with('cat', $cat)->with('post_owner_info', $post_owner_info);
}
And this is my Post model:
class Post extends Eloquent
{
public function User()
{
return $this->belongsTo('User');
}
public function Categories()
{
return $this->belongstomany('Category');
}
public function comments()
{
return $this->hasMany('Comment');
}
}
you can try like this
$new_post_inst = Post::where('id','=',$id)->first();
$new_post_inst->increment('visit',1);
Try this:
$new_post_inst = Post::where('id','=',$id)->first();
$new_post_inst->visit+=1;
$new_post_inst->save();
OR this:
$new_post_inst = Post::where('id','=',$id)->first();
$new_post_inst->update(array('visit' => $new_post_inst->visit+1));
I searched around for a little bit and this could be the favicon icon that is making a second request. How did you declare the favicon? Or maybe you could remove it to try and see if it is indeed the favicon?

laravel4 select all data from other table by relation(one to many)

i have two tables users its model (User) ... and servs it model (servs) .... the relation is one to many .... when i try to select all sevices with belong to one user .... it select first service only and ignore others ... this is code i used it
public function getserv(){
return View::make('infos.serv');
}
public function postserv(){
$user = User::find(Auth::user()->id);
$user_id = $user->id;
$serv = servs::where('user_id','=',$user_id);
if($serv->count()){
$serv = $serv->get();
//return $serv->user_id;
foreach ($serv as $servs) {
return $servs->serv_id;
}
}
}
Instead of returning the data at the first loop, you should better do something like this:
$result = array();
foreach ($serv as $servs) {
$result[] = $servs->serv_id;
}
return $result;
Try this.
public function postserv(){
$user = User::find(Auth::user()->id);
$user_id = $user->id;
$serv = servs::where('user_id','=',$user_id)->get()->first;
if($serv)
return $serv->serv_id;
else
return null;
}
You only see the first one because when you return something the function ends and the rest of $serv doesn't get processed.
I recommend you first set up Eloquent relations properly
class User extends Eloquent {
public function servs(){
return $this->hasMany('servs');
}
}
After that you can retrieve all servs for a user like this:
$user = Auth::user();
$servs = $user->servs;
foreach ($servs as $serv) {
echo $serv->serv_id;
}

Categories