Not found for some routes - laravel

I have a problem with some of my routes in Laravel. this my code in web.php file:
Route::group(['namespace' => 'Admin', 'middleware' => ['auth:web']], function () {
Route::get('/admin/audio/create/{audio?}', 'AdminAudioController#create')->name('admin.audioCreate');
Route::get('/admin/article/create/{article?}', 'AdminArticleController#create')->name('admin.articleCreate');
}
and this my link in blade
<i class="fa fa-edit"></i>
<i class="fa fa-edit"></i>
and this are my Controllers:
AdminAudioController
<?php
namespace App\Http\Controllers\Admin;
use App\Article;
use App\Http\Requests\ArticleRequest;
class AdminArticleController extends AdminController
{
public function index()
{
$articleList = Article::where('removed', false)->latest()->paginate(10);
return view('admin.article.archive', compact('articleList'));
}
public function create(Article $article = null)
{
return view('admin.article.create', compact('article'));
}
}
AdminArticleController
<?php
namespace App\Http\Controllers\Admin;
use App\Article;
use App\Http\Requests\ArticleRequest;
class AdminArticleController extends AdminController
{
public function index()
{
$articleList = Article::where('removed', false)->latest()->paginate(10);
return view('admin.article.archive', compact('articleList'));
}
public function create(Article $article = null)
{
return view('admin.article.create', compact('article'));
}
}
but my second link with name "admin.articleCreate" doesn't work and get "404 not found" what should I do?
and this is my article model
class Article extends Model
{
protected $primaryKey = 'articleId';
use Sluggable;
protected $fillable = [
'title',
'subTitle1', 'subTitle2',
'image',
'description',
'body',
'enable',
];
protected $casts = [
'image' => 'array'
];
/**
* Return the sluggable configuration array for this model.
*
* #return array
*/
public function sluggable(): array
{
return [
'slug' => [
'source' => 'title'
]
];
}
public function getRouteKeyName()
{
return 'slug';
}
}

When you call the method create(Article $article = null) on your controller, Laravel uses Model Binding to resolve your model and the model binding uses the method you have added to your model
public function getRouteKeyName()
{
return 'slug'; // by default it will be $primaryKey which is 'id'
}
In short, Laravel will try to use slug to find your model while your giving him articleId
So to fix it you have few options
Using the slug in the URL (the one I would recommend)
// blade.php
<i class="fa fa-edit"></i>
Using the primary articleId in the URL
// blade.php
<i class="fa fa-edit"></i>
// Article.php.php
public function getRouteKeyName()
{
return 'articleId';
}
Using a query
// blade.php
<i class="fa fa-edit"></i>
//Controller.php
public function create($article = null)
{
$article = Article::where('YOUR_FIELD', $article)->firstOrFail();
return view('admin.article.create', compact('article'));
}

you have code
return view('admin.article.create', compact('$article'));
but need
return view('admin.article.create', compact('article'));

I can see you have mentioned $article in side compact.
Can you please check once, I think the create method should look like this:
public function create(Article $article = null)
{
return view('admin.article.create', compact('article'));
}

Related

Favorite functionality for my laravel application

I'm currently trying to make a favorite functionality to my laravel application. I'm trying to access the post table with eloquent, but it says property posts(the function in the favorite model) does not exist.
Update: I updated the query. If I dump $favorite I get two items, which is correct, but now I get this error message instead:Property [posts] does not exist on the Eloquent builder instance. (View: C:\xampp\laravelprojects\Skakahand\resources\views\profile\index.blade.php)
<div class="favorite-section">
<p>Mina favoriter</p>
{{$favorite->posts->title}}
</div>
This is my controller:
public function index(User $user)
{
$favorite = Favorite::where('user_id', auth()->user()->id)
->get();
return view('profile.index',[
'user' => $user,
'favorite' => $favorite
]);
}
Favorite model:
class Favorite extends Model
{
use HasFactory;
protected $fillable = [
'user_id'
];
public function users()
{
return $this->belongsTo(User::class);
}
public function posts()
{
return $this->belongsTo(Post::class);
}
}
and post model:
class Post extends Model
{
use HasFactory;
/* use Sluggable; */
protected $fillable = [
'title',
'body',
'category',
'decision',
'number',
'place',
'image_path',
'slug',
'price',
'user_id',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function favorites(){
return $this->hasMany(Favorite::class);
}
}
First correct Model like this
class Favorite extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'post_id',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function post()
{
return $this->belongsTo(Post::class);
}
}
In controller change code like this for for avoid lazy loads
public function index(User $user)
{
$favorites = Favorite::where('user_id', auth()->user()->id)
->with('post')
->get();
return view('profile.index',[
'user' => $user,
'favorites' => $favorites
]);
}
in blade use code like
<div class="favorite-section">
<p>Mina favoriter</p>
<ul>
#foreach($favorites as $favorite)
<li>{{ $favorite->post->title ?? '' }} </li>
#endforeach
</ul>
</div>
just include ->with() for relationship,
your query should look like this
$favorite = Favorite::where('user_id', auth()->user()->id)->with('post')
->get();
return view('profile.index',compact('favorite','user'));

Laravel Roles and Permissions based on Role specific Ability

I have a project in which I want a Specific page to be viewed by a specific user which have a role of viewing for example I have User 1 that has an Admin Role and the Admin Role has the Ability to View this page in my design I made 3 models Users, Roles, and Abilities
User Model:
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password','district','area','committee','position',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function answer()
{
return $this->hasMany('App\Answer');
}
public function roles()
{
return $this->belongsToMany('App\Role');
}
public function hasRole($role)
{
if ($this->roles()->where('name', $role)->first()) {
return true;
}
return false;
}
public function assignRole($role)
{
$this->roles()->save($role);
}
}
Role Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
protected $fillable = ['name'];
public function abilities()
{
return $this->belongsToMany('App\Ability');
}
public function hasAbility($ability)
{
if ($this->abilities()->where('name', $ability)->first()) {
return true;
}
return false;
}
public function assignAbility($ability)
{
$this->abilities()->save($ability);
}
public function users()
{
return $this->belongsToMany('App\User');
}
}
Ability Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Ability extends Model
{
protected $fillable = ['name'];
public function roles()
{
return $this->belongsToMany('App\Role');
}
}
This is my UserPolicy:
<?php
namespace App\Policies;
use App\User;
use App\Role;
use Illuminate\Auth\Access\HandlesAuthorization;
class UserPolicy
{
use HandlesAuthorization;
public function view (Role $role)
{
return $role->hasAbility('view');
}
public function manage (User $user)
{
return true;
}
public function edit (User $user)
{
return true;
}
public function update (User $user)
{
return true;
}
public function add (User $user)
{
return true;
}
}
And the Controller of The Policy
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use App\User;
use App\Role;
class MemberController extends Controller
{
public function index(Role $role)
{
$this->authorize('view', $role);
return view ('members.create')->with('users', User::all());
}
public function manage(User $user)
{
$this->authorize('manage', $user);
return view ('members.manage')->with('users', User::all());
}
public function edit(User $user)
{
$this->authorize('edit', $user);
return view ('members.edit')->with('user', User::all())->with('roles', Role::all());
}
public function update(Request $request, User $user)
{
$this->authorize('update', $user);
$user->roles()->sync($request->roles);
return redirect('/members/edit');
}
public function store(User $user)
{
$this->authorize('add', $user);
$this->validate(request(), [
'name' => ['required', 'string', 'max:255'],
'district' => ['required', 'string', 'max:255'],
'area' => ['required', 'string', 'max:255'],
'committee' => ['required', 'string', 'max:255'],
'position' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
$data = request()->all();
$member = new User();
$member->name = $data['name'];
$member->district = $data['district'];
$member->area = $data['area'];
$member->committee = $data['committee'];
$member->position = $data['position'];
$member->email = $data['email'];
$member->password = Hash::make($data['password']);
$member->save();
return redirect('/members/create');
}
}
The index function should be the one related to the function view in the UserPolicy
and this is the can located in my blade.php file
#can('view', \App\Role::class)
<li class="">
<a class="" href="/members/create">
<span><i class="fa fa-user-plus" aria-hidden="true"></i></span>
<span>Add Member</span>
</a>
</li>
#endcan
in the policy when I link it to the name of the role of the logged in user everything works just fine but if I want to link it to an ability of the role it doesn't work so any idea on how the View Function in the UserPolicy should be implemented ?
The first parameter that is passed to the policy is the authenticated User, not its Role. I don't think it works. Maybe if you reimplement using an EXISTS query.
public function view (User $user)
{
return $user->roles()->whereHas('abilities', function ($ability) {
$ability->where('name', 'view');
})
->exists();
}
->exists() turns the query into an EXISTS query, which will return a boolean value if the query finds anything without having to return any rows.
https://laravel.com/docs/7.x/queries#aggregates
You could put that logic into an User method.
# User model
public function hasAbility($ability): bool
{
return $this->roles()->whereHas('abilities', function ($ability) {
$ability->where('name', 'view');
})
->exists();
}
public function view (User $user)
{
return $user->hasAbility('view');
}

Can not update a boolean value in table by vue and laravel

I have a boolean field when I try to update from false to true for a single or multiple records it works but when trying to update it back to false it works for the first record only and can not repeat to update multiple records at the same time without refreshing the page 1- my vue component that handles the request is like this:
<template>
<div v-for="(channel, index) in items" :key="channel.id">
<a href="" #click.prevent="toggleVisibility(channel)">
<i v-if="channel.active" class="fas fa-stop default-stop" data-toggle="tooltip" title="Stop Channel">
</i>
<i v-else class="fas fa-play" data-toggle="tooltip" title="Start Channel"></i>
</a>
</div>
</template>
export default {
name: "Channels",
props: ['allChannels'],
data() {
return {
items: this.allChannels
}
},
methods: {
toggleVisibility(channel) {
axios[channel.active ? 'delete' : 'post'](`/visible-channels/${channel.name}`);
}
}
}
and my routes:
Route::post('/visible-channels/{channel}', 'ChannelsController#activate');
Route::delete('/visible-channels/{channel}', 'ChannelsController#deactivate');
my controller:
public function activate(Channel $channel, Request $request)
{
if ($request->method() == 'POST') {
$channel->update(['active' => true]);
}
return back();
}
public function deactivate(Channel $channel, Request $request)
{
if ($request->method() == 'DELETE') {
$channel->update(['active' => false]);
}
}
The model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
class Channel extends Model
{
protected $guarded = [];
protected $casts = [
'active' => 'boolean',
];
protected static function boot()
{
parent::boot();
static::updating(function () {
return Cache::forget('activeChannels');
});
}
public function getRouteKeyName()
{
return 'name';
}
}
Since laravel stores boolean as 1 and 0 in database, You should probably set active property to boolean in your model
That's because laravel treat false as string so when you set active to false it compares it as 'false' == true which is true so it stores 1 in database.
class Channel extends Model
{
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'active' => 'boolean',
];
}
I figured it out just change in the boot function to wait until the update finish
static::updated(function () {
return Cache::forget('activeChannels');
});

How do I see published posts count with Eloquent using a ServiceProvider

I have a Blog Categories in the sidebar.blade.php
#foreach ($categories as $category)
<li>
<i class="fa fa-angle- right"></i> {{$category->title}}
<span class="badge pull-right">{{$category->posts()->count()}}</span>
</li>
#endforeach
But this count give me all the posts in my database, even the ones that are scheduled to post at a later date.
PostsController
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Post;
use App\Category;
class PostsController extends Controller
{
protected $limit = 3;
public function index()
{
$posts = Post::with('author')
->latestFirst()
->published()
->paginate($this->limit);
return view('posts.index', compact('posts'));
}
public function category(Category $category)
{
$categoryName = $category->title;
$posts = $category->posts()
->with('author')
->latestFirst()
->published()
->paginate($this->limit);
return view('posts.index', compact('posts', 'categoryName'));
}
Here's the Post.php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
use GrahamCampbell\Markdown\Facades\Markdown;
class Post extends Model
{
//Table Name
protected $table = 'posts';
// Primary Key
public $primaryKey = 'id';
// Timestamps
public $timestamps = true;
/*protected $fillable = [
'title',
'excerpt',
'body',
'categery_id',
'image',
];*/
protected $dates = ['published_at'];
public function author()
{
return $this->belongsTo(User::class);
}
public function category()
{
return $this->belongsTo(Category::class);
}
public function getImageUrlAttribute($value)
{
$imageUrl = "";
if( ! is_null($this->image))
{
$imagePath = public_path() . "/img/" . $this->image;
if(file_exists($imagePath)) $imageUrl = asset("img/" . $this->image);
}
return $imageUrl;
}
public function getDateAttribute()
{
return is_null($this->published_at) ? '' : $this->published_at->diffForHumans();
}
public function getExcerptHtmlAttribute(){
return $this->excerpt ? Markdown::convertToHtml(e($this->excerpt)) : NULL;
}
public function getBodyHtmlAttribute()
{
return $this->body ? Markdown::convertToHtml(e($this->body)) : NULL;
}
public function scopeLatestFirst($query)
{
return $query->orderBy('published_at', 'desc');
}
public function scopePublished($query)
{
return $query->where('published_at', '<=', Carbon::now());
}
}
Here's my Category.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $table = 'categories';
/*protected $fillable = [
'title',
'excerpt',
'body',
'categery_id',
'image',
'slug'
];*/
public function posts()
{
return $this->hasMany(Post::class);
}
public function getRouteKeyName()
{
return 'slug';
}
}
Web.php
Route::get('/', 'PagesController#index');
Route::get('/about', 'PagesController#about');
Route::get('/category/{category}', [
'uses' => 'PostsController#category',
'as' => 'category'
]);
Route::resource('books', 'BooksController');
Route::resource('posts', 'PostsController');
Route::resource('categories', 'CategoriesController', ['except'=> ['create']]);
ComposerServiceProvider.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Category;
use App\Post;
class ComposerServiceProvider extends ServiceProvider
{
public function boot()
{
view()->composer('layouts.sidebar', function($view){
$categories = Category::with(['posts' => function($query){
$query->published();
}])->orderBy('title', 'asc')->get();
return $view->with('categories', $categories);
});
}
}
To recap on what I need done...
I want to just have my published post to be accounted for in the counter to show, not all the of the posts in my database..
(<span class="badge pull-right">{{$category->posts->count()}}</span>)
Post.php
public function scopePublished($query)
{
return $query->where('published_at', '<=', Carbon::now());
}
But this is not working right for me, does anyone know why?
Try this one:
<span class="badge pull-right">{{$category->posts()->published()->count()}}</span>
Didn't try but this should do the trick.

InvalidArgumentException route notdefined

I have error like (1/1) InvalidArgumentException
Route [home] not defined. whenever i used the store function but i'm pretty sure that i use the redirect method right what could be the possible error, all i wanted was to redirect to home once the store method is done.
web.php
<?php
Route::get('/', function () {
return view('main');
});
Route::get('/create', 'BuildingController#createBuilding');
Route::post('/store', 'BuildingController#store');
Route::post('home', 'BuildingController#getAllBuilding');
Building.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Building extends Model
{
public $timestamps = false;
protected $fillable = [
'id',
'building_name',
'building_information',
'building_image'
];
}
BuildingController.php
<?php
namespace App\Http\Controllers;
use App\Building;
use Image;
use Illuminate\Http\Request;
use App\Repositories\Building\BuildingRepository;
class BuildingController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
private $building;
public function __construct(BuildingRepository $building)
{
$this->building = $building;
}
public function createBuilding()
{
return view('building.create');
}
public function store(Request $request)
{
$this->validate($request, array(
'building_name'=>'required',
'building_information'=>'required',
'building_image' => 'required'
));
$image = $request->file('building_image');
$filename = time() . '.' . $image->getClientOriginalExtension();
$location = public_path('images/' .$filename);
Image::make($image)->resize(800,400)->save($location);
$buildings = array('building_name' => $request->building_name,
'building_information' => $request->building_information,
'building_image' => $filename);
$this->building->create($buildings);
return redirect()->route('home');
}
public function getAllBuilding()
{
$buildings = $this->building->getAll();
return view('building.home')->with('buildings', $buildings);
}
public function getSpecificRecord()
{
$buildings = $this->building->getById(1);
return view('building.show')->with('buildings', $buildings);
}
}
EloquentBuilding.php
<?php
namespace App\Repositories\Building;
use \App\Building;
class EloquentBuilding implements BuildingRepository
{
private $model;
public function __construct(Building $model)
{
$this->model = $model;
}
public function getById($id)
{
return $this->model->findOrFail($id);
}
public function getAll()
{
return $this->model->all();
}
public function create(array $attributes)
{
return $this->model->create($attributes);
}
public function update($id, array $attributes)
{
}
public function delete($id)
{
}
}
BuildingRepository.php
<?php
namespace App\Repositories\Building;
interface BuildingRepository
{
public function getById($id);
public function getAll();
public function create(array $attributes);
public function update($id, array $attributes);
public function delete($id);
}
Since you're using route(), you need to name the route. Also, make it get:
Route::get('home', 'BuildingController#getAllBuilding')->name('home');
Or:
Route::get('home', ['as' => 'home', 'uses' => 'BuildingController#getAllBuilding']);
You are trying to use route with post, replace it with get and also add/specify name attribute to call route using name.
Route::get('home', 'BuildingController#getAllBuilding')->name('home');
OR
Route::get('home', ['as' => 'home', 'uses' => 'BuildingController#getAllBuilding']);
Above both are comes with same output...

Resources