I wish to clarify the steps to get a new form properly submitted to my database using Laravel 5.2 and Bootstrap 3.
I have the login/register pages set up properly using Laravel's defaults, and they work fine. I now want to create a user profile page accessible to authenticated users. I am using one row in the database for all of their user info. Some fields were filled in during registration, and now I want them to have access to additional fields (while restricting access to certain registration fields like user name).
In the example code below, there are fields to upload a personal photo, enter a first name, and enter a last name. (None of these were done during registration.)
What I have already done (all code is below):
Create the view profile.blade.php
Create a controller profileController.php
Update routes.php in the controller directory.
A note:
When I try to submit the form as it appears below, I get, Type error: Argument 1 passed to App\Http\Controllers\ProfileController::update() must be of the type array, none given.
What are the next steps required to get this page working properly?
profile.blade.php:
#extends('layouts.app')
#section('content')
<div class="container" style="padding-top: 30px;">
<h1 class="page-header">User Profile</h1>
<div class="row">
<!-- left column -->
<div class="col-md-4 col-sm-6 col-xs-12">
<div class="text-center">
<i class="fa fa-user fa-5x"></i>
<h6>Please upload a photo...</h6>
<input type="file" class="text-center center-block well well-sm">
</div>
</div>
<!-- edit form column -->
<div class="col-md-8 col-sm-6 col-xs-12 personal-info">
<form class="form-horizontal" role="form" method="POST" action="{{ url('/profile') }}">
{!! csrf_field() !!}
<div class="form-group">
<label class="col-lg-3 control-label">First name:</label>
<div class="col-lg-8">
<input class="form-control" value="<?php echo Auth::user()->firstname; ?>" id="firstname" name="firstname" placeholder="First..." type="text">
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Last name:</label>
<div class="col-lg-8">
<input class="form-control" value="<?php echo Auth::user()->lastname; ?>" id="lastname" name="lastname" placeholder="Last..." type="text">
</div>
</div>
<div class="form-group">
<label class="col-md-3 control-label"></label>
<div class="col-md-8">
<button type="submit" class="btn btn-primary">
<i class="fa fa-btn fa-user"></i>Submit
</button>
<span></span>
<input class="btn btn-default" value="Cancel" type="reset">
</div>
</div>
</form>
</div>
</div>
</div>
#endsection
profileController.php:
<?php
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Http\Request;
class ProfileController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return view('profile');
}
protected function update(array $data)
{
return User::update([
'firstname' => $data['firstname'],
'lastname' => $data['lastname'],
]);
}
}
And I added the following in the routes middleware:
Route::get('/profile', 'ProfileController#index');
Route::post('/profile', 'ProfileController#update');
It's a protocol mismatch, since you're POSTing your form. You need to change your route to
route::post('/profile', 'ProfileController#index');
Using a validator is a great idea, since it will make sure that your input is exactly what you need it to be, and all required fields are filled out.
Your update function should look something like this:
public function update(Request $request)
{
$first_name = $request->input('firstname');
$last_name = $request->input('lastname');
$id = Auth::user()->id;
$user = \App\User::find($id);
$user->firstname = $first_name;
$user->lastname = $last_name;
$user->save();
return view('profile');
// Sanitize, validate, before you do ANYTHING with update
// Instead of returning the update result, you can instead show another view or forward them to another page.
}
Related
I am new to programming especially laravel. I am trying to make a CRUD and have already added example data in prequel (using Docker). I can see the data, but when I´m trying to create new posts with a form I get Code 419 page expired. I know that´s normal and the solution is to add #csrf to the form. But after doing this I get 403 Forbidden. I tried a lot but can´t find a solution to fix it.
I would be really happy if someone could help me fix my problem.
Here is my create.blade.php
#section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-12">
<div class="card">
<div class="card-header">{{ __('Alle Gerichte') }}</div>
<div class="card-body">
<form action = "/recipe" method="POST">
#csrf
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" name="name">
</div>
<div class="form-group">
<label for="beschreibung">Beschreibung</label>
<textarea class="form-control" id="beschreibung" name="beschreibung" rows="5"></textarea>
</div>
<input class="btn btn-primary mt-4" type="submit" value="absenden">
</form>
<a class="btn btn-primary btn-sm mt-3 float-right" href="/recipe"><i class="fas fa-circle-up"></i>Zurück</a>
</div>
</div>
</div>
</div>
</div>
#endsection
hi is that you have created validation rules
in StoreRecipeRequest
do that
public function authorize()
{
return true;
}
Controller Code will be like this:
public function store(StoreRecipeRequest $request)
{
//dd($request);
$recipe = new Recipe( [
'name' => $request->name,
'beschreibung' => $request->beschreibung,
]);
$recipe->save();
return redirect('/recipe');
}
Also if it's not solved. Then let's try it.
public function store(StoreRecipeRequest $request)
{
$recipe = new Recipe();
$recipe->name = $request->name;
$recipe->beschreibung = $request->beschreibung;
$recipe->save();
return redirect('/recipe');
}
also, can you add in your Recipe Model?
protected $fillable = [
'name',
'beschreibung',
];
i'm new in Laravel and i'm building a simple user registration system.
When i access edit route, it seems that it's not getting the requested resource data.
I did some research and all the stuff i read, is already in place. Am i missing something?
web.php(router):
use Illuminate\Support\Facades\Route;
// USER PAGES:
Route::resource('users', 'UsersController');
UsersController.php:
namespace App\Http\Controllers;
use App\Users;
use Illuminate\Http\Request;
class UsersController extends Controller
{
/**
* Show the form for editing the specified resource.
*
* #param \App\Users $users
* #return \Illuminate\Http\Response
*/
public function edit(Users $users)
{
return view('dashboard.user.edit', compact('users'));
}
/**
* Remove the specified resource from storage.
*
* #param \App\Users $users
* #return \Illuminate\Http\Response
*/
public function destroy(Users $users)
{
$users->delete();
return redirect()->route('users.index')
->with('success', "User was removed successfully.");
}
}
edit.blade.php:
<form id="user-data" action="{{route('users.update',$users->id)}}" method="POST" enctype="multipart/form-data">
#csrf
#method('PUT')
<input type="file" id="input-user-photo" name="user_avatar" style="display: none;">
<div class="card">
<div class="card-header">User Data</div>
<div class="card-body card-block">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-user"></i>
</div>
<input type="text" id="username" name="name" placeholder="Username" class="form-control" value="{{$users->name}}">
</div>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-envelope"></i>
</div>
<input type="email" id="email" name="email" placeholder="Email" class="form-control" value="{{$users->email}}">
</div>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-asterisk"></i>
</div>
<input type="password" id="password" name="password" placeholder="Password (For not changing, leave it blank)" class="form-control">
</div>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-asterisk"></i>
</div>
<input type="password" id="password-confirmation" placeholder="Password Confirmation" class="form-control">
</div>
</div>
<div class="form-actions form-group">
<a class="btn btn-secondary btn-md" href="<?php echo $_SERVER['HTTP_REFERER']; ?>">Cancel</a>
<button type="submit" class="btn btn-success btn-md">Submit</button>
</div>
</div>
</div>
</form>
On Screen (URL: /users/{{$anyUserId}}/edit):
Also, when i access destroy route it reaches the right controller's method "destroy" and even redirects properly, with success message, as specified in the method, but the resource is not deleted from database. In both cases, it seems to me that it is not finding the resource to inject as parameter within these methods.
Any clues? Thx in advance!
If the resource name is users the route parameter would be user (singular). The route parameters are by default the singular version of the resource name when using resource routing.
For implicit route model binding to work you need the typehinted parameter of your methods to match the route parameter:
public function edit(Users $user)
public function destroy(Users $user)
Side note: usually Model names are singular and their tables are plural.
I have a PHP Laravel CRUD application I made where I am using MVC style. I have controllers views and models. My database migration is made and my table in the database is made with php artisan migrate. I am using php 7.3 and laravel 5.8.
On my create view I go to create a single object in my database and my errors are thrown saying nothing in text box (no input) If I comment out the errors then just I click my submit button and nothing happens nothing is entered into my db. I have looked at many different crud examples and I am not sure why my object isn’t being created. Here is what I have
My env is setup correctly I just don’t get the not creating object.
//view create
#section('main')
<section id="section-content" class="text-center">
<div class="container contentdiv rounded">
<div class="row">
<div class="col-md-12">
<div class="pb-2 mt-4 mb-2 border-bottom clearfix">
<h2>Create Contact</h2>
</div>
<div >
<a class="btn btn-success" href="{{route('contacts.index')}}">Back</a>
</div>
</div>
<!-- <div class="col-md-10 mx-auto">
#if($errors->any())
<div class="alert alert-danger">
<ul>
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div><br />
#endif
</div> -->
<div class="row">
<div class="col-md-10 mx-auto mt-3">
<form method="POST" action="{{ route('contacts.store') }}">
#csrf
<div class="form-group row">
<label for="txtfn" class="col-sm-3"><b>First Name:</b></label>
<div class="col-sm-9">
<input type="text" class="form-control" name="txtfn" id="txtfn"/>
</div>
</div>
<div class="form-group row">
<label for="txtln" class="col-sm-3"><b>Last Name:</b></label>
<div class="col-sm-9">
<input type="text" class="form-control" name="txtln" id="txtln"/>
</div>
</div>
<div class="form-group row">
<label for="txtem" class="col-sm-3"><b>Email:</b></label>
<div class="col-sm-9">
<input type="text" class="form-control" name="txtem" id="txtem"/>
</div>
</div>
<button type="submit" class="btn btn-primary">Create Contact</button>
</form>
</div>
</div>
</div>
</section>
//controller
namespace App\Http\Controllers;
use App\Contact;
use Illuminate\Http\Request;
class ContactController extends Controller
{
public function store(Request $request)
{
$request->validate([
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required'
]);
$contact = new Contact([
'first_name' => $request->get('first_name'),
'last_name' => $request->get('last_name'),
'email' => $request->get('email'),
'job_title' => $request->get('job_title'),
'city' => $request->get('city'),
'country' => $request->get('country')
]);
$contact->save();
return redirect('/contacts')->with('success', 'Contact saved!');
}
public function index()
{
$contacts = Contact::all();
return view('contacts.index', compact('contacts'));
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return view('contacts.create');
}
// model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
protected $fillable = [
'first_name',
'last_name',
'email',
'city',
'country',
'job_title'
];
}
Your problem is that your input names do not correspond to the keys you are referencing in your store() method:
for example:
<input type="text" class="form-control" name="txtfn" id="txtfn"/>
here, your input name is txtfn, but in your store method, you are looking for first_name.
'first_name' => $request->get('first_name')
so, $request->get('first_name') returns null as if you didn't pass any value.
You must make your input names match with the keys you are using in your store method, either by changing input names, or by changing key names.
example:
<input type="text" class="form-control" name="first_name" />
<input type="text" class="form-control" name="last_name" />
<input type="text" class="form-control" name="email" />
I have created a form that uploads a file but it returns a null value when I submit. When I add in the enctype="multipart/form-data" it reloads the page and doesn't seem to go through my controller.
MY HTML FORM
<form class="form-horizontal" role="form" name="importform" method="POST" action="{{ route('import_type') }}" enctype="multipart/form-data">
{{ csrf_field() }}
<div class="control-group">
<label class="control-label"> </label>
<div class="controls">
<div class="control-group text-center">
<label class="btn btn-primary" for="file-selector">
<input id="file-selector" name="template_upload" type="file" value="" required autofocus style="display:none" onchange="$('#upload-file-info').html(this.files[0].name)" required> Upload List </label>
<span class='label label-default' id="upload-file-info"></span>
</div>
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn btn-primary" type="submit" id="import-submit" name="import-submit">
</div>
</div>
</form>
MY CONTROLLER: I am using the import method
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\ImportTypeRequest;
use \App\Guest;
use \App\Role;
use \App\User;
use \App\Type;
use Illuminate\Support\Facades\Auth;
class GuestController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$user = User::with('roles')->where('id', Auth::id())->get();
$types = Type::where('user_id', Auth::id())
->where('active',1)->get();
return view('view_import',compact('user','types'));
}
public function import(ImportTypeRequest $request)
{
$template_upload = $request->file('template_upload');
dd($template_upload);
}
}
Here are some suggested ways trying to solve this.
First of all in your import method add dd($request->all()) at its top and see what's the response. You should see all your form data and of course template_upload file. That's how you make sure that you see all the coming data from your form to your controller method.
Then try to get rid of ImportTypeRequest and just use Illuminate\Http\Request to see what will you get. If you got different result then the problem is in ImportTypeRequest class.
Then why don't you just use $request->template_upload?! It's cleaner I guess.
I have seen this post, however I don't believe it is relevant to my issue because I believe I am correctly passing post data through a post route.
Here is the relevant route code:
Route::get('/pass', 'PageController#pass');
Route::post('/pass/{request}',['uses' => 'PageController#passController']);
I would like to have one controller method for the 'pass' page, but to isolate the issue I have separated them.
Here are the relevant methods in PageController.php:
public function pass(){
return view('pass')->with(array(
'title'=>'Create A Pass'
));
}
public function passRequest($request){
$data['request'] = $request;
$validator = Validator::make($request->all(), [
'studentID' => 'required|max:255',
'teacherID' => 'required|max:255',
'destination' => 'required|max:255',
]);
if ($validator->fails()) {
return redirect('/')
->withInput()
->withErrors($validator);
}
$pass = new Pass;
$pass->student = DB::table('users')->where('studentID', $request->studentID)->first()->id;
$pass->teacher = DB::table('users')->where('teacherID', $request->teacherID)->first()->id;
$pass->destination = $request->destination;
$pass->save();
return view('home')->with(array(
'title'=>'Home',
'success'=>'null'
));
}
I used the method stated here in order to pass data to the controller. If this is bad practice/obsolete I'm open to any suggestions.
This is the form in the 'pass' page responsible for sending the post data
<form action="{{ url('pass') }}" method="POST" class="form-horizontal">
{!! csrf_field() !!}
<fieldset>
<!-- Text input-->
<div class="container">
<div class="form-group">
<label class="col-md-4 control-label" for="studentID">Student ID</label>
<div class="col-md-3">
<input id="studentID" name="studentID" type="text" class="form-control input-md">
</div>
</div>
</div>
<!-- Text input-->
<div class="container">
<div class="form-group">
<label class="col-md-4 control-label" for="teacherID">Teacher ID</label>
<div class="col-md-3">
<input id="teacherID" name="teacherID" type="text" class="form-control input-md">
</div>
</div>
</div>
<!-- Text input-->
<div class="container">
<div class="form-group">
<label class="col-md-4 control-label" for="destination">Destination</label>
<div class="col-md-3">
<input id="destination" name="destination" type="text" class="form-control input-md">
</div>
</div>
</div>
<div class="container">
<div class="form-group">
<div class="col-sm-offset-4 col-sm-6">
<button type="submit" class="btn btn-default">
<i class="fa fa-check"></i> Create Pass
</button>
</div>
</div>
</div>
</fieldset>
</form>
On submission of this form I get the MethodNotAllowedHttpException Exception.
If a stack trace of the error would be helpful, please let me know. If there are any suggestions on style, I'm open to that as well.
This form tag will generate a POST request to the URL /pass:
<form action="{{ url('pass') }}" method="POST" class="form-horizontal">
Your routes file does not allow that. It only allows GET requests to that url, but POST requests to /pass/{request}.
Not sure if its just a copy/paste mistake, but your POST route is set up to call PageController#passController method, but the method you shared from your controller is named passRequest. Those will need to match also.
In addition to what Jeff Lambert pointed out, you should not put the {request} variable in the route.
You should remove that and have laravel inject the Request object for you.
Import the Request class if you haven't already at the top of the class.
use Illuminate\Http\Request;
And your function should look like the following...
public function passRequest(Request $request)
{
...
}
If you have additional parameters to pass through the URL, then you may add them to the route, and add the arguments to the method after Request $request. Laravel will figure out what to do with it.
try this one...
Route::post('/pass/post','PageController#passController')->name('post_insert');
in your html form change to ...
<form action="{{ route('post_insert') }}" method="POST" class="form-horizontal">
change it also ...
public function passRequest(Illuminate\Http\Request $request){
....