I have a homepage where there is a menu with some categories and below there are the latest 10 posts.
A post can have many categories and one category can belong to many posts so there are 2 models and a pivot table "category_post" with 2 columns: id and name.
So in the homepage, there is a menu with some categories and below the posts:
<ul class="Categories__Menu">
#foreach($categories->take(6) as $category)
<li class="ative">
{{$category->name}}
</li>
#endforeach
</ul>
<div class="row" id="posts">
#foreach($posts as $post)
<div class="col-12 col-sm-6 col-lg-4 col-xl-3 mb-4">
<div class="card">
<img class="card-img-top" src="{{$post->image}}" alt="Card image cap">
<h5 class="card-title">{{$post->name}}</h5>
<div class="card-footer d-flex justify-content-between align-items-center">
More
</div>
</div>
</div>
#endforeach
</div>
I want that when each category is clicked to show only the posts of that category in the homepage, but in the same homepage, not in a specific category page. So maybe the best approach is using AJAX.
But Im getting an error accessing "http://proj.test/posts/where/category/5"
ReflectionException (-1)
Class PostController does not exist
Or when I click in a category in the menu it appears in the console:
GET http://proj.test/posts/where/category/5 500 (Internal Server Error)
Do you know where is the issue?
The code:
In the FrontController I already pass the categories and posts to the homepage view:
FrontController:
class FrontController extends Controller
public function index(){
return view('home')
->with('categories', Category::orderBy('created_at', 'desc')->get())
->with('posts', Post::orderBy('created_at','desc')->take(10)->get());
}
}
Post and Category models:
class Post extends Model
{
public function categories(){
return $this->belongsToMany('App\Category');
}
}
class Category extends Model
{
public function posts(){
return $this->belongsToMany('App\Post');
}
}
PostController:
public function WhereHasCategory(Request $request)
{
$posts = Post::whereHas('categories', function ($categories) use (&$request) {
$categories->where('id',$request->id);
})->get();
return response()->json($posts);
}
Route to the homepage:
Route::get('/', [
'uses' => 'FrontController#index',
'as' =>'index'
]);
Route to the ajax part:
Route::get('posts/where/category/{id}','\PostController#WhereHasCategory')->name('category.posts');
Ajax:
$(function() {
$("a[name='category']").on('click', function(){
var category_id = $(this).attr("id");
$.ajax({
url: '{{ route('category.posts',null) }}/' + category_id,
type: 'GET',
success:function(result){
$('#posts').empty();
$.each(result,function(index, postObj){
$('#posts').append("<p>"+postObj.title+"</p>");
});
console.log(result);
},
error: function(error) {
console.log(error.status)
}
});
});
});
You've defined the class wrong in the ajax route.
Route::get(
'posts/where/category/{id}',
'\PostController#WhereHasCategory'
)->name('category.posts');
You've put the controller as \PostController when I imagine it's App\Http\Controllers\PostController. When you prefix the class with \ it tells it that it's in the global scope, with no namespace. Remove the \.
Related
I am trying to get the posts that belong to each category, i had this working before but i can't seem to find what i have done wrong here.
I have a Post Table and a Categories Table
ROUTE
Route::get('articles/category/{id}', ['as' => 'post.category', 'uses' => 'ArticlesController#getPostCategory']);
CONTROLLER
public function getPostCategory($id)
{
$postCategories = PostCategory::with('posts')
->where('post_category_id', '=', $id)
->first();
$categories = PostCategory::all();
// return view
return view('categories.categoriesposts')->with('postCategories', $postCategories)->with('categories', $categories);
}
VIEW
#foreach($postCategories->posts as $post)
<div class="well">
<div class="media">
<a class="pull-left" href="#">
<img class="media-object" src="http://placekitten.com/150/150">
</a>
<div class="media-body">
<h4 class="media-heading">{{ substr($post->title, 0, 50) }}</h4>
<p class="text-right">By Francisco</p>
<p>{{ substr($post->body, 0, 90) }}</p>
<ul class="list-inline list-unstyled">
</ul>
</div>
</div>
</div>
#endforeach
POST MODAL
public function postCategory()
{
return $this->belongsTo('App\PostCategory');
}
POSTCATEGORY MODAL
class PostCategory extends Model
{
// connect Categories to Posts tables
protected $table = 'post_categories';
// Category belongs to more than 1 post
public function posts()
{
return $this->hasMany('App\Post', 'post_category_id');
}
}
I can't see what i am doing wrong every time I go to a category it shows
Trying to get property of non-object
Any help will be much appreciated thanks
replace your lines:
$postCategories = PostCategory::with('posts')
->where('post_category_id', '=', $id)
->first();
with:
$postCategories = PostCategory::find($id)->posts;
Change your line in your PostCategoryModel to:
return $this->hasMany('App\Post', 'post_category_id','post_category_id');
In the homepage there is a menu with some categories and below there are the latest 10 posts.
A post can have many categories and one category can belong to many posts so there are 2 models and a pivot table "category_post" with 2 columns: id and name.
So in the homepage, there is a menu with some categories and the posts:
<ul class="Categories__Menu">
#foreach($categories->take(6) as $category)
<li class="ative">
{{$category->name}}
</li>
#endforeach
</ul>
<div class="row" id="posts">
#foreach($posts as $post)
<div class="col-12 col-sm-6 col-lg-4 col-xl-3 mb-4">
<div class="card">
<img class="card-img-top" src="{{$post->image}}" alt="Card image cap">
<h5 class="card-title">{{$post->name}}</h5>
<div class="card-footer d-flex justify-content-between align-items-center">
More
</div>
</div>
</div>
#endforeach
</div>
I want that when each category is clicked to show only the posts of that category in the homepage, but in the same homepage, not in a specific category page. So maybe the best approach is using AJAX.
Im not understanding what is necessary in the controllers and routes and the jquery is also dont working properly. Do you know how what is necessary to list the posts when a category is clicked with AJAX?
In the Frontcontroller I already pass the categories and posts to the homepage view:
class FrontController extends Controller
public function index(){
return view('home')
->with('categories', Category::orderBy('created_at', 'desc')->get())
->with('posts', Post::orderBy('created_at','desc')->take(10)->get());
}
}
route to the homepage:
Route::get('/', [
'uses' => 'FrontController#index',
'as' =>'index'
]);
Post and Category models:
class Post extends Model
{
public function categories(){
return $this->belongsToMany('App\Category');
}
}
class Category extends Model
{
public function posts(){
return $this->belongsToMany('App\Post');
}
}
In this homepage I have at bottom the ajax below
#section('scripts')
<script>
$(function() {
$("a[name='category']").on('click', function(){
var category_id =$(this).attr("id");
alert("test");
$.get('/ajax-category?category_id=' + category_id, function (data) {
$('#posts').empty();
$.each(data,function(index, postObj){
$('#posts').append('');
});
});
});
});
</script>
#stop
Pivot table "category_post" structure
public function up()
{
Schema::create('category_post', function (Blueprint $table) {
$table->increments('id');
$table->integer('post_id');
$table->integer('category_id');
$table->timestamps();
});
}
Just in your API route add a new route for your SQL queries, something like this following route :
Route::get('posts/where/category/{id}','\Posts#WhereHasCategory')->name('category.posts');
Then in your WhereHasCategory function return related posts :
API Controller (WhereHasCategory) :
public function WhereHasCategory(Request $request)
{
$posts = Post::whereHas('categories', function ($categories) use (&$request) {
$categories->where('id',$request->id);
})->get();
return response()->json($posts);
}
Post Model (Many To Many Relationships) :
public function Categories () {
return $this->belongsToMany(Category::class,'post_category','post_id','category_id');
}
You will get those posts that have $request->id category
For your Ajax part, you have to make an ajax request to the above route, You will get the posts which you want, so once you're done change the content of your home page (If you are using VueJS or similar Javascript framework it's really easy) ... That is all, I think!
Try this for your ajax request :
<a name="category" id="2018" href="#">
Category
</a>
<div id="posts">
<p>Title : Posts Are Here !</p>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<script>
$(function() {
$("a[name='category']").on('click', function(){
var category_id = $(this).attr("id");
$.ajax({
url:"https://jsonplaceholder.typicode.com/posts",
type: 'GET',
success:function(result){
$('#posts').empty();
$.each(result,function(index, postObj){
$('#posts').append("<li>"+postObj.title+"</li><p>"+postObj.body+"</p>");
});
},
error: function(error) {
console.log(error.status)
}
});
});
});
</script>
Always keep your Javascript queries at the end of the page.
I think your ajax not working because your page is refreshing when you click the category link, try to add hashtag in the href property.
exsampel:
<ul class="Categories__Menu">
#foreach($categories->take(6) as $category)
<li class="ative">
{{$category->name}}
</li>
#endforeach
</ul>
or change <a> with <span>.
sorry for my English. I hope it would help.
I have two methods show and index I have a list of items on the index method that when a user clicks it takes her to another page containing some data that belongs to that id. Instead of doing it such way, I want to use jquery to make the data load on the same page. I have the following on my index.blade.php view. How do I achieve this in laravel?
#foreach ($categories as $category)
<div class="body">
<h4><a style="text-decoration: none; " href="{{ URL::route('category.show', $category->id) }}">{{$category->name}}</a></h4>
</div>
#endforeach
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use illuminate\HttpResponse;
use App\Http\Requests\todolistRequest;
use App\Http\Requests\CreateCategoryRequest;
use App\Http\Requests;
use App\Companylist;
use App\Category;
use Illuminate\Support\Facades\DB;
class CategoryController extends Controller
{
public function create(){
return view('category.create');
}
public function index(){
$categories=Category::all();
return view('category.index',compact('categories'));
}
public function store(CreateCategoryRequest $request){
$category = new Category($request->all());
$category->save();
return \Redirect::route('category.create')->with('message', 'Your list has been created!');
}
public function show($id)
{
$category = Category::findOrFail($id)->companylist()->get();
$cat=Category::findOrFail($id);
// this my route
Route::resource('category','CategoryController');
return view('category.show')->with('category', $category)->with('cat',$cat);
}
//
}
Use bootstrap modals or pop ups.
Design your category.show view according to your needs.
Call ajax and append your returned view response to that modal body and show it so it will be exactly same view you wanted.
example code is for replace and ajax is like
This is replace modal
<!-- Show Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Show data</h4>
</div>
<div class="modal-body replace">
</div>
</div>
This will be your ajax method
$('.showModalButton').on('click',function(e){
var id = $(this).data('id'); // get id of resource you want to show
$('.replace').empty(); //
$.ajax({
url: 'your route/'+id,
type: "GET",
success:function(data) {
$('.replace').html(data);
},
error:function(jQXHR, textStatus, errorThrown) {
console.log(jQXHR);
console.log(textStatus);
console.log(errorThrown);
}
}); //end Ajax call
});
This will be your show method in controller
public function show($id)
{
$category = Category::findOrFail($id)->companylist()->get();
$cat=Category::findOrFail($id);
// this my route
Route::resource('category','CategoryController');
return view('category.show')->with('category',$category)->with('cat',$cat);
}
Design category.show however you want to show your data.
I'm new to laravel and trying to understand correctly how to show in my view my picture of my relations.
For example I have a table for Category, Post, User, and Image, and I need some help with this.
For my DB it's OK with Image table like tutorial polymorphic relation on laravel docs.(same like doc)
In my models image I have my polymorphic relation and it's all OK
class Image extends \Eloquent {
protected $guarded = ['id' , 'created_at'];
public function imageable(){
return $this->morphTo();;
}
}
I need to associate a image on my different category
class Category extends \Eloquent {
protected $guarded = ['id' , 'created_at'];
public function posts(){
return $this->hasMany('Post');
}
public function images(){
return $this->morphMany('Image','imageable');
}
public function parent(){
return $this->belongsTo('Category','parent_id');
}
public function children(){
return $this->hasMany('Category','parent_id');
}
public function getImportantPost(){
return $this->hasOne('Post')->latest();
}
public function latestPost(){
return $this->hasOne('Post')->latest();
}
}
After that in my homecontroller for my home page I have a request for 1 particular post to show with a specific category
//show headliner post specific category
$headliner = Category::with(['posts' => function($query){
$query->orderBy('published_at', 'DESC')->take(1)->get();
}])->where('id' , '=' , '5')->get();
In my home index view I have a foreach $headliner like this
<div class="widget-area-4">
<div class="widget kopa-article-list-widget">
<ul class="clearfix">
#foreach($headliner as $headline)
<li>
<article class="entry-item clearfix">
<div class="entry-thumb">
<img src="{{$headline}}" alt="" />
<span class="category-title">{{$headline->name}}</span>
</div>
<!-- entry-thumb -->
<div class="entry-content">
<header>
<h5 class="entry-title">{{$headline->latestPost->name}}</h5>
<span class="entry-date"><i class="fa fa-calendar"></i> {{$headline->latestPost->published_at}}</span>
<span class="entry-categories">Auteur: </span>
<span class="entry-comments">{{$headline->latestPost->counts_comments}}<span></span></span>
</header>
<p>{{str_limit($headline->latestPost->content, 600 ,' ...' )}}</p>
<a class="more-link" href="#">Voir plus</a>
</div>
<!-- entry-content -->
</article>
<!-- entry-item -->
</li>
#endforeach
</ul>
</div>
<!-- kopa-article-list-widget -->
</div>
But I don't know how to show my image in my foreach because I have my post associated to category so it's OK but when I try to
{{$headline->images->path}}
(path is my entries in my DB) I have a error.
Thanks for your help.
As you've used morphMany() to define images relation for a category, loading this relation will give you a collection of Image objects. Therefore in your view $headline->images refers to this collection, not a single image. Collection does not have a path attribute, hence the error.
You'll need to iterate through your images collection in the view and then render each image separately, e.g.:
#foreach($headline->images as $image)
<img src="{{ $image->path }}" />
#endforeach
There is a simple page where i display search results by keywords.
But now i want to search on those results by some criteria.
How can i do it
SearchController
class SearchController extends \BaseController {
public function search() {
$keyword = Input::get('header-search-query');
if (empty($keyword)) {
$product = Product::paginate(10);
$this - > setModel($product);
return View::make('product.listbykeyword') - > with('products', $product);
}
return View::make('product.listbykeyword') - > with('products', Product::like('title', $keyword) - > paginate(10));
}
public function advance() {
//what should i put here
}
}
View
#foreach($products as $product)
<div class="media">
<div class="media-left" style="width:16%;">
<a href="{{ URL::to('image/'.$product->productImage()->first()['image']) }}">
{{ HTML::image('image/'.$product->productImage()->first()['image'],'no-image',array('class'=>'media-object','height'=>'100','width'=>'100'))}}
</a>
</div>
<div class="media-body">
<h4 class="media-heading">{{ HTML::link('/product/'.$product->id,$product->title) }}</h4>
<p>{{substr($product->description,0,85)}}</p>
<p>Price : {{$product->price}} TK</p>
<p class="time">{{$product->created_at->diffForHumans()}}
<b>Near</b> {{$product->location}}
</p>
</div>
</div>
<hr></hr>
#endforeach
As it was true that you can't able to use Datatables in your case as it is a public search i would recommend you to use ajax call on the keychange event.
Step 1 :
Detect the keychange from your textbox
<input id='myTextbox1' type='text'/>
$('#myTextbox1').on('input', function() {
alert('Text1 changed!');
});
Here is the fiddle
Step 2 :
Call the ajax page to your controller
$.ajax({
type: "POST",
url : "yourcontroller",
data : dataString,
success : function(data){
$("#result").html(data);
}
});
Place a div named as result in your page.
So, First time you will get the result from your default controller you use to search and then next time whenever you type the text in your myTextbox1 it will call the controller yourcontroller and in your controller you should get the datastring and return the matching output to the view.
Hope this helps you.