I have a working function in my controller but I want to add a permissions gate in order to use the function.
Basically, right before the collect line in the first section, I want to add Gate::allows('can-fix', 'testFix') ?: parent::denyAccess(); but I'm testing it and even though I don't have the 'testFix' ability, it still lets me through
I don't want to add a gate at the route level, I want it to actually access the controller method but kick me out if I'm not allowed to do anything in the method itself.
Am I declaring the gate incorrectly here?
public function editCategorySort(categorySur $category, Request $request, $categoryGroup)
{
Gate::allows('can-fix', 'testFix') ?: parent::denyAccess();
collect($request->input('sur'))
->each(function ($asset) use ($categoryGroup, $category) {
$data = [
'category_sur' => $asset['category_sur'],
'type' => $asset['type'],
];
$category_sur_id = $asset['id'];
$category->updateCategoryGroup($categoryGroup, $category_sur_id, $data);
});
}
I am not sure how you defined your gate, but the code below works for me.
controller
Route::get('/test', function () {
Gate::allows('can-fix') ?: dd('you do not have the access');
dd('yes you can reach here');
});
app\Providers\AuthServiceProvider.php
public function boot()
{
$this->registerPolicies();
Gate::define('can-fix', fn () => true);
}
so if fn () => true the result is "yes you can reach here"
if fn () => false the result is "you do not have the access"
Hope this helps!
Related
Update:
This line of code in the frontend was the culprit:
<inertia-link v-if="options.edit" :href="'/admin/gallery/edit/1'">
I had to change it to:
<inertia-link v-if="options.edit" :href="'/admin/gallery/1/edit'">
to make it comply with the laravel resource format for edit, provided by #Babak.
Original Post:
How would I transform this route in web.php:
Route::get('/admin/gallery/edit/{id}', function ($id) {
$data = Gallery::find($id);
return inertia('backend/cms-gallery-edit', ['data' => $data]);
});
to a resource route with its resource controller function:
Route::resource('/admin/gallery', GalleryController::class);
GalleryController.php:
public function edit($id)
{
$data = Gallery::find($id);
// assign id to end of route
return inertia('backend/cms-gallery-edit', ['data' => $data]);
}
Edit:
I've tried both approaches of #Babak's answer, which work for index and create routes but the edit route still throws a 404. It is the only route encompassing an id.
web.php:
Route::resource('/admin/gallery', GalleryController::class)->only('index', 'create', 'edit');
GalleryController.php:
public function edit($gallery)
{
$data = Gallery::find($gallery);
return inertia('backend/cms-gallery-edit', ['data' => $data]);
}
Inertia passes the id from the frontend via href:
<inertia-link v-if="options.edit" :href="'/admin/gallery/edit/1'">
Browser shows:
GET http://127.0.0.1:8000/admin/gallery/edit/1 404 (Not Found)
There is a fixed structure for laravel resource route method, you can see full list here. For edit page, it will generate something like '/admin/gallery/{gallery}/edit'
You can write it like below:
In your web.php file:
Route::resource('/admin/gallery', GalleryController::class)->only('edit');
And in your controller, name of the resource must be the same as your function's parameter.
public function edit($gallery)
{
$data = Gallery::find($gallery);
// assign id to end of route
return inertia('backend/cms-gallery-edit', ['data' => $data]);
}
Or, you can customize it using parameter method. Refer to here
Route::resource('/admin/gallery', GalleryController::class)->only('edit')->parameters([
'gallery' => 'id'
]);
And your controller
public function edit($id)
{
$data = Gallery::find($id);
// assign id to end of route
return inertia('backend/cms-gallery-edit', ['data' => $data]);
}
I have this route declared on laravel:
Route::get('pages/{page}/{slug}', 'Common\Pages\CustomPageController#show')
->middleware(['web', 'prerenderIfCrawler']);
This route works fine and works if you make requests to:
https://example.com/pages/1/test-page
https://example.com/pages/2/other-page
https://example.com/pages/3/url-test
The problem is that I need a more friendly url as well as.
https://example.com/test-page
https://example.com/other-page
https://example.com/url-test
I want remove the suffix called pages, The numbers for the pages will never change and will be static for each one.
I've tried to make static routes for each one but can't get it to work.
Route::get('other-page', array('as' => 'other-page', function() {
return App::make('Common\Pages\CustomPageController')->show(2);
}))->middleware(['web', 'prerenderIfCrawler']);
I would appreciate a little help.
You could always get the URL segment in the Controller and use that to know what page you are on. If you don't want to do that you could pass extra information in the 'action' to specify the page:
Route::middleware(['web', 'prerenderIfCrawler'])->group(function () {
Route::get('test-page', [
'uses' => 'Common\Pages\CustomPageController#show',
'page' => 'test-page',
]);
...
});
Then you can get this extra information in the Controller:
public function show(Request $request)
{
$page = $request->route()->getAction('page');
...
}
If you knew all the pages you can use a route parameter with a regex constraint to restrict it to only those page names:
Route::get('{page:slug}', ...)->where('page', 'test-page|other-page|...');
public function show(Page $page)
{
...
}
You could just make use of a wildcard to catch your routes like this:
Route::get('/{slug}', 'Common\Pages\CustomPageController#show')
->middleware(['web', 'prerenderIfCrawler']);
Then in your controller:
public function show($slug)
{
$page = Page::where('slug', $slug)->first();
// ...
}
Just be careful with where you place the route. It should be at the end of your routes otherwise it will catch all the request of your app.
// ...
// my other routes
// ...
Route::get('/{slug}', ...);
By the way, if you want to bind your page models using the slug attribute do this:
Route::get('/{page:slug}', 'Common\Pages\CustomPageController#show')->//...
^^^^^^^^^
Then in your controller:
public function show(Page $page)
{ ^^^^^^^^^^
// ...
}
Check this section of the docs.
I can't get the data from the database. Getting an error:
ErrorException (E_ERROR)
Undefined variable: user
(View:/Users/alex/Desktop/sites/tj/resources/views/user/submissions.blade.php)
Controller:
public function __construct()
{
$this->middleware('auth', ['except' => ['getById',
'getByUsername', 'submissions', 'comments', 'showSubmissions',
'showComments']]);
}
and
public function showSubmissions($username)
{
$user = new UserResource(
User::withTrashed()->where('username', $username)->firstOrFail(),
true
);
$submissions = SubmissionResource::collection(
Submission::whereUserId($user->id)
->withTrashed()
->orderBy('created_at', 'desc')
->simplePaginate(15)
);
return view('user.submissions', compact('user', 'submissions'));
}
View:
{{ $user->username }}
API:
Route::get('/user', 'UserController#getByUsername');
I need get information about user (username).
What is the problem and where is the error?
Based on your comment you have this route:
Route::get('/submission', function () {
return view('user.submissions');
});
When you are loading this view, you are not passing the user object to it. Then when the view is running, it is trying to access a variable that does not exist.
To fix this, you need to pass a variable to the view you are loading. For example, you could do something like this:
Route::get('/submission', function () {
return view('user.submissions', ['user' => auth()->user()]);
});
Note that you can change how you get the user instance depending on your use case. I am just getting the authenticated user to demonstrate the principle.
I am using Hashid to hide the id of a resource in Laravel 5.
Here is the route bind in the routes file:
Route::bind('schedule', function($value, $route)
{
$hashids = new Hashids\Hashids(env('APP_KEY'),8);
if( isset($hashids->decode($value)[0]) )
{
$id = $hashids->decode($value)[0];
return App\Schedule::findOrFail($id);
}
App::abort(404);
});
And in the model:
public function getRouteKey()
{
$hashids = new \Hashids\Hashids(env('APP_KEY'),8);
return $hashids->encode($this->getKey());
}
Now this works fine the resource displays perfectly and the ID is hashed.
BUT when I go to my create route, it 404's - if I remove App::abort(404) the create route goes to the resource 'show' view without any data...
Here is the Create route:
Route::get('schedules/create', [
'uses' => 'SchedulesController#create',
'as' => 'schedules.create'
]);
The Show route:
Route::get('schedules/{schedule}', [
'uses' => 'Schedules Controller#show',
'as' => 'schedules.show'
]);
I am also binding the model to the route:
Route::model('schedule', 'App\Schedule');
Any ideas why my create view is not showing correctly? The index view displays fine.
Turns out to solve this, I had to rearrange my crud routes.
Create needed to come before the Show route...
There's a package that does exactly what you want to do: https://github.com/balping/laravel-hashslug
Also note, that it's not a good idea to use APP_KEY as salt because it can be exposed.
Using the above package all you need to do is add a trait and typehint in controller:
class Post extends Model {
use HasHashSlug;
}
// routes/web.php
Route::resource('/posts', 'PostController');
// app/Http/Controllers/PostController.php
public function show(Post $post){
return view('post.show', compact('post'));
}
Everything looks right to me. It's so simple, but I dont know. I've looked everywhere.
Problem: It doesn't redirect. It doesn't give error nothing happens.
But when I enter the browser http://site.dev/fail
it shows "fail" word on screen (so it works).
routes.php:
Route::post('getir' , 'Ahir\Ticket\Controllers\TicketController#postInsert');
Route::get('fail', function() { return 'fail'; });
Route::get('success', function() { return 'success'; });
edit everything
Scenario:
on site.dev/ (homepage) I press submit that form has this.
form action="getir" method="POST" role="form"
so button redirect me to
Route::post('getir' , 'Ahir\Ticket\Controllers\TicketController#postInsert');
so this postInsert is triggered below at controller ticket.
controller ticket:
<?php namespace Ahir\Ticket\Controllers;
use BaseController, Input;
//use Ahir\Ticket\Repositories\TicketInterface;
use Ahir\Ticket\Adapters\AdapterInterface ;
class TicketController extends BaseController {
public function __construct(AdapterInterface $adapter) //TicketInterface $repository
{
//$this->repository = $repository;
$this->adapter = $adapter;
}
public function postInsert()
{
$this->adapter->postInsert();
}
}
then it comes here
codes
public function postInsert()
{
// create the validation rules ------------------------
$rules = array(
'title' => 'required',
'content' => 'required',
);
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
// i added here return vardump('fail'); it displays on screen.
// so i know that program comes here
// but the redirect below neither gives error nor redirect.
//nothing happens here. idk why!
return Redirect::to('fail')->withErrors($validator);
} else {
// validation successful ---------------------------
$this->obj->insert([
'title' => Input::get('title') ,
'content' => Input::get('content')
]);
//here DOESNT work too.
return Redirect::to('success');
}
The problem is that you don't return anything from the calling function.
Your application calls the postInsert() method on your ticket controller. This function calls another function which returns a Redirect.
But you don't pass that returned Redirect back to the application, so the postInsert() function just terminates without any output. The application doesn't know what happens within the postInsert() function, it just waits for something to be returned. And since nothing is returned, the HTTP response is simply empty. In order to pass that Redirect back to the application, you also have to return it from the calling function:
public function postInsert()
{
return $this->adapter->postInsert();
}