I'm trying to fetch current category details.
For example, if the route is example.com/articles/category-slug
In my ArticleCategory Model
public function article(){
return $this->hasMany(Article::class);
}
In Article Model
public function category(){
return $this->belongsTo(ArticleCategory::class, 'category_id');
}
Routes
Route::group(['prefix' => 'articles'], function(){
Route::get('/', 'Frontend\ArticleController#index')->name('articles.index');
Route::get('/{articlecategory}', 'Frontend\ArticleController#category');
Route::get('/{articlecategory}/{slug}', 'Frontend\ArticleController#show');
});
ArticleController
public function category(Request $request, ArticleCategory $articlecategory)
{
$category = $articlecategory->id;
$currentcategory = ArticleCategory::where('id', $category)->first();
return $currentcategory;
}
i have created two categories, 1. Updates 2. News
When i go to the url example.com/articles/updates i receive a error "Page Not Found"
When i change the {{ articlecategory }} to {{ category }} only in the routes file. It shows a blank page without the current category details. How to solve this?
Note: I used the same code earlier in Laravel 5.5 and it worked well. In Laravel 5.6 i see this error. I'm already using a cache killer on chrome and have also cleared cache and views in laravel as suggested by few links on google. However i still see the same error
I found out a way that worked.
I have changed route key value to slug and it worked. I thought that was done by the slugs package i was using. After adding the below code manually to the models it works as expected.
public function getRouteKeyName()
{
return 'slug';
}
If you would like model binding to use a database column other than id when retrieving a given model class, you may override the getRouteKeyName method on the Eloquent model:
for example :
class ArticleCategory extends Model
{
public $table='article_category';
public function article(){
return $this->hasMany(Article::class);
}
public function getRouteKeyName()
{
return 'category_slug';
}
}
and my article_category table :
| category_slug | name | id |
|:-------------:|:-------:|:--:|
| cat1 | Updates | 1 |
| cat2 | News | 2 |
your routes should be :
Route::group(['prefix' => 'articles'], function(){
Route::get('/', 'Frontend\ArticleController#index')->name('articles.index')->name('articles');
Route::get('/{category}', 'Frontend\ArticleController#category')->name('category');
Route::get('/{category}/{slug}', 'Frontend\ArticleController#show')->name('category_articals');
});
now you are passing a category_slug to your controller then
example: example.com/articles/news
in your controller :
public function category(Request $request,$category)
{
$category = ArticleCategory::where('slug',$category)->first();
if($category){
// category found , return category to page
return view('category',compact('category'));
}else{
// category not found , return 404 page
return view('error.404');
}
}
Related
I have a laravel app using Policies to assign roles and permissions, i cant seem to access the show page and im not sure what im doing wrong?
If i set return true it still shows a 403 error as well, so im unsure where im going wrong here. The index page is accessable but the show page is not?
UserPolicy
public function viewAny(User $user)
{
if ($user->isSuperAdmin() || $user->hasPermissionTo(44, 'web')) {
return true;
}
return false;
}
public function view(User $user, User $model)
{
if ($user->isSuperAdmin() || $user->hasPermissionTo(44, 'web')) {
return true;
}
return false;
}
UserController
public function __construct()
{
$this->authorizeResource(User::class, 'user');
}
public function index()
{
$page_title = 'Users';
$page_description = 'User Profiles';
$users = User::all();
return view('pages.users.users.index', compact('page_title', 'page_description', 'users'));
}
public function create()
{
//
}
public function store(Request $request)
{
//
}
public function show($id)
{
$user = User::findOrFail($id);
$user_roles = $user->getRoleNames()->toArray();
return view('pages.users.users.show', compact('user', 'user_roles'));
}
Base on Authorize Resource and Resource Controller documentation.
You should run php artisan make:policy UserPolicy --model=User. This allows the policy to navigate within the model.
When you use the authorizeResource() function you should implement your condition in the middleware like:
// For Index
Route::get('/users', [UserController::class, 'index'])->middleware('can:viewAny,user');
// For View
Route::get('/users/{user}', [UserController::class, 'view'])->middleware('can:view,user');
or you can also use one policy for both view and index on your controller.
I had an issue with authorizeResource function.
I stuck on failed auth policy error:
This action is unauthorized.
The problem was that I named controller resource/request param with different name than its model class name.
F. ex. my model class name is Acknowledge , but I named param as timelineAcknowledge
Laravel writes in its documentation that
The authorizeResource method accepts the model's class name as its first argument, and the name of the route / request parameter that will contain the model's ID as its second argument
So the second argument had to be request parameter name.
// Here request param name is timelineAcknowledge
public function show(Acknowledge $timelineAcknowledge)
{
return $timelineAcknowledge->toArray();
}
// So I used this naming here also
public function __construct()
{
$this->authorizeResource(Acknowledge::class, 'timelineAcknowledge');
}
Solution was to name request param to the same name as its model class name.
Fixed code example
// I changed param name to the same as its model name
public function show(Acknowledge $acknowledge)
{
return $acknowledge->toArray();
}
// Changed here also
public function __construct()
{
$this->authorizeResource(Acknowledge::class, 'acknowledge');
}
I looked over Laravel policy auth code and I saw that the code actually expects the name to be as the model class name, but I couldn't find it anywhere mentioned in Laravel docs.
Of course in most of the cases request param name is the same as model class name, but I had a different case.
Hope it might help for someone.
Laravel Version 5.7
PHP 7+
I created a resource controller -> CategoryController [having all the magic methods]
This is the routes/web.php
Route::group(['as'=>'admin.','middleware'=>['auth','admin'],'prefix'=>'admin'], function(){
Route::get('/dashboard','AdminController#dashboard')->name('dashboard');
// product resource controller methods
// check php artisan r:l
Route::resource('product', 'ProductController');
Route::resource('category', 'CategoryController');
Route::resource('profile', 'ProfileController');
Route::post('remove', 'CategoryController#remove')->name('category.remove');
});
Now as you can see, I have "http://127.0.0.1:8000/admin/category/1/edit" for one of my categories to edit with category id = 1, that is also stored in the database.
<?php
namespace App\Http\Controllers;
use App\Category;
use Illuminate\Http\Request;
class CategoryController extends Controller
{
public function index()
{
$categories = Category::paginate(3);
return view('admin.categories.index',compact('categories'));
}
public function edit(Category $category)
{
return "This is category edit page";
// dd($category);
// $categories = Category::where('id','!=', $category->id)->get();
// // dd($categories);
// return "This is category edit page";
// return view('admin.categories.create',['categories' => $categories, 'category'=>$category]);
}
When I try to go to this edit category page, it shows 404 page not found error.
Although, when I made an individual route for edit method with a closure function to return some text, it worked perfectly.
Route::get('category/{category}/edit', function($category){
return $category;
})->name('category.edit');
You didn't excluded full error you get, but try to change:
public function edit(Category $category)
{
return "This is category edit page";
}
into:
public function edit($category)
{
return "This is category edit page";
}
and see if it helps. If it helps, it means that there is no record matching id you passed or this record is soft deleted (or some additional conditions are not met) - Laravel uses Route model binding to match valid record.
try this
public function edit(Request $category)
{
return "This is category edit page";
}
Here are my tables
Posts
id | name | created_At
Comments
id | comment | post_id | created_at
Post Model
function comments(){
return $this->hasMany('App\Models\Comment','id','post_id');
}
PostsController
function index()
{
Post::with('comments')::get();
}
Now how can i get list of all posts along with comments?
I am trying to match post_id in the child table.
In Your Post Model:
public function comments()
{
return $this->hasMany('App\Model\Comment');
}
In Your Post Controller :
use Illuminate\Http\Request;
function index(Request $request)
{
$posts=Post::with('comments')->get();
// in json
return response()->json($posts);
// in your view
//return view('viewname')->with('posts',$posts);
}
when try to get all comment for one Article by Article::first() but first()
Bring just the first article
i try use find() like
$comments = Article::find()-> commentsArticle()->with('articles');
return Datatables::of($comments)
i get error so how i can Pass a value to view all comments for one article
or
my be there is way without using find()
Article model
class Article extends Model{
public $table = 'articles';
public function commentsArticle() {
return $this->hasMany('App\Comment');
}
}
controller
enter code here
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Yajra\Datatables\Datatables;
use App\Article;
use App\Comment;
class CommentController extends Controller{
public function commentsForOne Article()
{
$comments = Article::all()->commentsArticle->with('articles');
return Datatables::of($comments)->make(true);
}
}
last error i get
ErrorException (E_DEPRECATED)
Non-static method Yajra\Datatables\Datatables::collection() should
not be called statically
I hope find any idea or example like that will help me to learn
You are trying to get the first articles with its comments.
public function commentsForOneArticle($id)
{
$article = Article::fine($id);
//check if article exists to avoid errors
if ( $article ) {
return Datatables::of(Comment::where('article_id', $article->id))->make(true);
}
return "no article with id" . $id;
}
This was just an illustration. But it seems you need to understand first how Eloquent works. Watch this free Laracast https://laracasts.com/series/laravel-from-scratch-2017/episodes/7
For routes, you can define the route like this:
Route::get('comments/{article_id}', 'ArticleController#commentsForOneArticle');
And call it in Ajax like
$.ajax({url: "/comments/1",
success: function(result){
//do stuff here
},
error: function(error) {
console.log(error)
}
});
All this is just a guide and not THE solution.
Edit
To take data with the user in one go
$article = Article::with('user')->find($id);
//will include all the fields from user and article
Comments & author
To get the name of the comment author, you need to define the relationship in comment model
public function user() {
return $this->belongsTo(User::class);
}
Then get like this
if ( $article ) {
return Datatables::of(Comment::with('users')->where('article_id', $article->id))->make(true);
}
it is possible to get all details (user, posts, postimages) within one collection / json?
user->hasmany(posts)
post->hasmany(postimage)
user:
id | name
post:
id | user_id | text
postimage:
id | post_id | imgpath
user model:
public function posts() {
return $this->hasMany('App\posts')->orderBy('id', 'ASC');
}
posts model:
public function images(){
return $this->hasMany('App\postsimages');
}
get all posts from user works fine:
$myposts = users::find(Auth::user()->id)->posts;
i'm able to get all images from a post within a loop
foreach($myposts as $mypost) {
$postimages = $mypost->images;
}
what i want is to get all posts, images without the loop e.g
$myposts = users::find(Auth::user()->id)->posts->images
thanks
Yes, use hasManyThrough relationship.
posts model:
public function images()
{
return $this->hasMany('App\postsimages');
}
user model
public function posts()
{
return $this->hasMany('App\posts')->orderBy('id', 'ASC');
}
public function images()
{
return $this->hasManyThrough('App\posts', 'App\postsimages');
}
then
$postimages = Auth::user()->images;