Laravel 5 - insert multiple users - laravel

I have a simple User - Department relationship. My User Model has the following
public function department() {
return $this->belongsTo('App\Department', 'departmentId');
}
And my Department Model has
public function user() {
return $this->hasMany('App\User');
}
At the moment I am working with the departments side of things. My index function looks like the following
public function index() {
$departments = Helper::returnDepartmentsFromLdap();
return view('departments.index', compact('departments'));
}
What it basically does it gets all the departments from LDap (Active Directory) and displays them. On the index page for departments, I have
{!! link_to_route('departments.updateDepartments', 'Update Database', null, array('class' => 'btn btn-info')) !!}
So the database can be updated if new departments are added to our server. I do not have a create function as it is not needed.
Anyways, at the moment, my routes are like so
Route::model('departments', 'Department');
Route::bind('departments', function($value, $route) {
return App\Department::whereId($value)->first();
});
Route::resource('departments', 'DepartmentsController', ['except' => ['show', 'edit', 'create', 'delete', 'update', 'destroy']]);
Route::post('departments/updateDepartments', array('as' => 'departments.updateDepartments', 'uses' => 'DepartmentsController#updateDepartments'));
And in my updateDepartments function I am simply doing the following for now
public function updateDepartments()
{
dd("TEST");
}
If I click on the button on my index page to update the database, which should trigger the above, I am seeing a MethodNotAllowedHttpException.
Am I missing something obvious here?

try to use get:
because you can only pass data using get method with link link_to_route
Route::get('departments/updateDepartments', array('as' => 'departments.updateDepartments', 'uses' => 'DepartmentsController#updateDepartments'));

Route::post('departments/updateDepartments', ...) means you only allow POST requests on that route. Make sure the form method is POST instead of GET (default) on your index page

Related

Laravel Route: Multiple Route Group With Prefix and Route Model Binding

Hello wonderful people of SO!
I have a problem about Laravel Route which I cannot solve.
In User.php model I use getRouteKeyName() function
public function getRouteKeyName()
{
return 'user_name';
}
And also in Post.php model
public function getRouteKeyName()
{
return 'uuid';
}
In users table, 1 have one record
|----------------------------|
| id | ... | user_name | ... |
| 1 |-----| #simple |-----|
In posts table
|------------------------------------|
| id | ... | uuid | ... |
| 1 |-----| abcd-123-efg-456 |-----|
In route (web.php)
// for post (key: uuid)
Route::group(['prefix' => '{post}'], function () {
Route::get('/', function (Post $post) {
return $post;
});
});
// for users (key: user_name)
Route::group(['prefix' => '{user}'], function () {
Route::get('/', function (User $user) {
return $user;
});
});
Then let say we visit url: www.example.test/#simple/
In debugbar, I see query:
select * from posts where uuid = '#simple' limit 1
What I have tried
[#1] I put where clause in route groups for posts and users
Route::group([
'prefix' => '{post}',
'where' => [
'post' => '^[a-zA-Z0-9-]{36}$' // I'm not Regex professional
]
], function () {
Route::get('/', function (Post $post) {
return $post;
});
});
Route::group([
'prefix' => '{user}',
'where' => [
'user' => '^(#)[a-zA-Z0-9]$' // I'm not Regex professional
]
], function () {
Route::get('/', function (User $user) {
return $user;
});
});
So let's try again visit the url: www.example.test/#simple
What i got, 404
[#2] I deleted the getRouteKeyname in both User and post model
revisit url: www.example.test/#simple, still got 404
[#3] I tried to put Route Model Binding Column Name
Route::group([
'prefix' => '{post:uuid}', // This is what I changed
], function () {
Route::get('/', function (Post $post) {
return $post;
});
});
Route::group([
'prefix' => '{user:user_name}', // This is what I changed
], function () {
Route::get('/', function (User $user) {
return $user;
});
});
Still, query result is same: > select * from posts where uuid = '#simple' limit 1
What I want to achieve
Let say we visit url: www.example.test/#simple
Fetch a user with user_name is #simple or if the user is not exist, return 404
And also same for with posts
We visit url: www.example.test/abcd-1234-efgh-5678
Fetch a post with uuid is abcd-1234-efgh-5678 or 404 if not exist
Question:
[#1] How to tell Laravel Route: that I have 2 Route groups with different Model Binding? Sorry if this question is kinda confusing, cause my english is not really good
[#2] Have I implement Best practice for route groups and route model binding in Laravel?
Thanks in advance!
What is the result you intend to obtain?
If you are doing what I think you're doing (trying to see what's inside the post), you need to return something like $post->content (replace content with the column you want to get), you may even want to make a view and make the output nicer, plus use a controller for more processing.
As for route model binding, you can refer to this, both methods, using table:column and using getRouteKeyName are fine, however, the first one doesn't change the default column, and if you use {user} for another route, it will still use the ID column, however, the second one changes the default value, if you use {user} for another route, it will use the column you specified.
Also, you should use something like user/{user:user_name} and post/{post:uuid} instead of just {user:username} and {post:uuid}, as you have said, it won't know which route you're using. The uri has to be different.
Routes are evaluated in the order you put them, meaning that the second route with {post:uuid} will override the route with {user:username} since they have the same kind of uri, that is, they both consist of 1 wildcard and nothing else. To solve this, you simply have to make their uri different by adding a static part, for example, add post/ before {post:uuid} and/or add user/ before {user:user_name} like the example below:
Route::group([
'prefix' => 'post/{post:uuid}',
], function () {
Route::get('/', function (Post $post) {
return $post;
});
});
Route::group([
'prefix' => 'user/{user:user_name}',
], function () {
Route::get('/', function (User $user) {
return $user;
});
});
To make it very clear, your 2 routes have the same uri of 1 wildcard and nothing else, thus, the last one that appears with this uri will override all the previous routes with the same uri. Meaning that all the previous routes with this same uri before this will be treated like they don't exist, and when you go to a path with the uri in the format of /[insert something here], it fits into the format of having 1 wildcard and it will only go to the last one you specified, that is, the one for posts.
Since the route for users is declared before the one for posts and they share the same uri, only the one for posts will be used. Even when you are trying to find the user, it still uses the route for posts, if no such "post" with a uuid same as the user_name you provided exists, it will still return an error even when there is indeed such user with such username.
Also, you don't need a route group if there's simply 1 route, though it would be more readable and convenient if you're going to add more routes to the group in the future.
As far as I could understand your problem, here are the changes you need to make and it will work,
routes/web.php
Route::group([
'prefix' => 'post/{post:uuid}'
], function () {
Route::get('/', function (Post $post) {
return $post;
});
});
Route::group([
'prefix' => 'user/{user:user_name}'
], function () {
Route::get('/', function (User $user) {
return $user;
});
});
Regular Expression that you use above just does filter the {argument} and check if {argument} is alphanumeric basically, in above both cases it works the same except in user_name it also allows '-'

Router redirecting to the another page

I have route like
Route::get('admin/selfcontacteditdata','SelfcontectController#edit')->name('selfcontectedit');
Route::post('admin/selfcontactupdatedata','SelfcontectController#update')->name('selfcontectupdate');
If i just go to my browser and right admin/selfcontacteditdata it redirect me to
admin/newsshowdata
And my index function is
public function __construct()
{
return $this->middleware('auth');
}
public function index()
{
request()->validate([
'email' => 'required',
'mobileno' => 'required',
'facebook'=>'required',
'google'=>'required',
'map'=>'required',
]);
$data = selfcontect::find(1);
return view('/admin/selfcontectedit',compact('data'));
}
And my middleware is
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
My rest admin routes are working fine.
I had the same problem but I was writing table name wrong and my file was not saved as .blade please check are you also doing the same thing and there is no meaning of validation in edit function your edit function must be like
public function edit()
{
$data = selfcontect::find(1);
return view('/admin/selfcontectedit',compact('data'));
}
and your function name should be edit
You should use Accept key not Content/type
You can't redirect through view, actually your are calling view.
Correct syntax is
return view('view_name',compact('data'));
If you want to redirect to any route you have to call like this
return redirect()->to('admin/selfcontacteditdata');
Redirect to a Route
If in your routes.php file you have a route with a name, you can redirect a user to this particular route, whatever its URL is:
app/Http/routes.php:
get('books', ['as' => 'books_list', 'uses' => 'BooksController#index']);
app/Http/Controllers/SomeController.php
return redirect()->route('books');
This is really useful if in the future you want to change the URL structure – all you would need to change is routes.php (for example, get(‘books’, … to get(‘books_list’, …), and all the redirects would refer to that route and therefore would change automatically.
And you can also use parameters for the routes, if you have any:
app/Http/routes.php:
get('book/{id}', ['as' => 'book_view', 'uses' => 'BooksController#show']);
app/Http/Controllers/SomeController.php
return redirect()->route('book_view', 1);
In case of more parameters – you can use an array:
app/Http/routes.php:
get('book/{category}/{id}', ['as' => 'book_view', 'uses' =>
'BooksController#show']);
app/Http/Controllers/SomeController.php
return redirect()->route('book_view', [513, 1]);
Or you can specify names of the parameters:
return redirect()->route('book_view', ['category'=>513, 'id'=>1]);

Form submit intercepted by auth middleware in laravel 5

I've been working on a laravel 5.7 blog project. I want to comment an article.
I need to achieve this:
Before logging in, I can type anything in comment textarea
I submit comment (of course it would be intercepted by auth middleware)
then I'm redirected to login page
After logging in, I hope my app could submit previous form data (or comment) automatically instead of typing the same comment again
I think that's a very common business logic in many websites nowadays, but how am I supposed to achieve this?
My comments controller here:
public function __construct()
{
$this->middleware('auth');
}
public function store(Post $post) {
$comment = Comment::create([
'body' => session('comment')?:request('body'),
'post_id' => $post->id,
'user_id' => auth()->user()->id
//before logging in, you don't have an user_id yet.
]);
return back()->with('success', 'Add comment succeeded');
}
web.php Route here:
Route::post('/posts/{post}/comments', 'CommentsController#store')->name('addComment');
Basically auth middleware intercepted my form data submit, I want to go across the auth middleware with my form data. Not lost them after logging in.
Here is the solution.A little tricky.Save comment to the session first before go to auth middleware.After logging in, GET that route to create comment.
Route:
Route::get('/posts/{post}/comments', 'CommentsController#store')->name('addComment');
Route::post('/posts/{post}/comments', 'CommentsController#commentSave');
Comments controller:
public function __construct()
{
$this->middleware('auth', ['except' => ['commentSave']]);
}
public function commentSave(Request $request){
$url = \URL::previous();
session(['comment' => $request->input('body')]);
return redirect("$url/comments");
}
public function store(Post $post){
if(session('comment')){
$comment = Comment::create([
'body' => session('comment'),
'post_id' => $post->id,
'user_id' => auth()->user()->id
]);
session(['comment' => null]);
return redirect("posts/$post->id")->with('success', 'Add comment succeeded');
}
return redirect("posts/$post->id");
}
I think the solution to your problem is here:
https://laravel.com/docs/5.7/session#storing-data

Redirect users to the login if they are not authenticated and to the homepage if authenticated when accessing a url that they should not have access

After a user creates a conference he is redirected to a page "http://proj.test/conference/manage/2" to manage that specific conference.
A user that creates a conference with id "2" for example should be allowed to access "http://proj.test/conference/manage/2". But only this user that created this conference with id "2" should be allowed to access this conference.
The other users if they access "http://proj.test/conference/manage/2" should be redirected to the login page if are not authenticated and to the homepage if they are authenticated.
I was trying to do this with the code below, particularly with the code in the manage method, but when the user is redirected to an url for example "http://proj.test/conference/manage/2" it appears always:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'conference.user_id' in 'where clause' (SQL: select * from `conferences` where `conferences`.`user_id` = 1 and `conferences`.`user_id` is not null and `conferences`.`id` = 7 limit 1)
The issue should be because in the conferences table I have a field "conference_creator_id" instead of "user_id". But it's not possible to maintain the "conference creator_id"? But also, I dont know if this approach in the manage method is ok for this context and if with this approach is possible to do that thing of redirect a user, that accesses "http://layout.test/conference/manage/2", and he didn't create this conference with id 2, to the login page if is not authenticated and redirect to the homepage if he is authenticated. Do you know a proper approach to do that?
Store method:
public function store(Request $request)
{
$this->validate($request, [
'conference_name' => 'required|max:255|string',
...
]);
$conference = Conference::create([
'name' => $request->conference_name,
...
]);
return redirect()->route('conference.manage', ['id' => $conference->id]);
}
Manage method:
public function manage($id){
$conference = Auth::user()->conferences()->findOrFail($id);
return view('conferences.manage')>with('myconference',$conferene);
}
Routes:
Route::group(['prefix' => '', 'middleware' => 'auth'], function(){
Route::post('/conference/store', [
'uses' => 'ConferenceController#store',
'as' => 'conference.store'
]);
Route::get('/conference/create', [
'uses' => 'ConferenceController#create',
'as' => 'conference.create'
]);
Route::get('conference/manage/{id}', [ 'uses' => 'ConferenceController#manage', 'as'=>'conference.manage']);
});
Add the custom foreign key to the conferences relationship definition:
public function conferences()
{
return $this->hasMany(Conference::class, 'conference_creator_id');
}
But it's better to follow Laravel naming conventions described in my repo and change the column name to user_id.
And you need to use policies for authorization purposes.
You could add to your controller class:
public function __construct()
{
$this->middleware('auth');
}
This way it'll check whether the user is signed in or as a guest and deal with them accordingly depending on the result.
The alternative would be to wrap a Route group around anything that required 'auth' (as my answer states in your previous question).
A simple way will be to check the id of the current user
public function __construct()
{
//User should be logged in before accessing the `manage` method
$this->middleware('auth')->only(['manage']);
}
public function manage(Conference $conference){
//Redirect the user to the homepage when its ID is different of the ID of the user who created the conference
if ($conference->user_id != Auth::id()){
return redirect(url('/'));
}
return view('conferences.manage')>with('myconference',$conferene);
}

Resource route show route to index

I have a resource route:
Route::resource('product', 'ProductController#index', ['only' => ['index', 'show', 'destroy']]);
The index lists all items in the database:
public function index()
{
return view('product', ['products' => Product::all()]);
}
and at the moment the show just echos the ID:
public function show($id)
{
return 'Show '.$id;
}
if I go to url/product the correct data shows up.
if I go to url/product/{ProductID} the index page shows up... not the echo of the id.
Has anyone experienced this issue? Do you know if I have done something silly?
Remove the action name after the controller
Route::resource('product', 'ProductController', ['only' => ['index', 'show', 'destroy']]);
// -------------------------------------^
When using RESTful Resource Controllers, we only need to pass the controller name and it will stub the action itself.
source: http://laravel.com/docs/5.0/controllers#restful-resource-controllers

Resources