Laravel form validation only works when hitting back button - php

I'm using Laravel 4.2. My issue happens after submitting the form with data that will fail during form validation (short pass, invalid email, etc).
My form is at /register. When I submit the form with invalid data, the page goes blank (white) and no data is entered into the database. The validation errors only show up after I hit the back button in the browser.
If I enter valid data, the form submits and adds data to the database correctly, and redirects the user to /account.
Any help would be greatly appreciated. I feel like it's something small that I'm overlooking, and it's kicking my ass.
Here's my code...
User.php
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends BaseModel implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/** Protect from mass-assignment **/
protected $fillable = array('username', 'email', 'password', 'password_confirmation');
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
public static $rules = array(
'username'=>'required|unique:users,username|alpha_dash|min:4',
'password'=>'required|between:8,32|confirmed',
'password_confirmation'=>'required|between:8,32',
'email'=>'required|email|unique:users,email'
);
}
UsersController.php
class UsersController extends BaseController {
public function getNew() {
return View::make('users.new')
->with('title', 'Create An Account');
}
public function postCreate() {
$validation = User::Validate(Input::all());
if ($validation->passes()) {
User::create(array(
'username'=>Input::get('username'),
'password'=>Hash::make(Input::get('password')),
'email'=>Input::get('email')
));
return Redirect::to('account')->with('message', 'Welcome! Your account has been created.');
} else {
Redirect::to('register')->withErrors($validation)->withInput();
}
}
}
Routes.php
Route::get('register', array('as'=>'register', 'uses'=>'UsersController#getNew'));
Route::post('register', array('before'=>'csrf', 'uses'=>'UsersController#postCreate'));
new.blade.php
#if($errors->has())
<p>The following errors have occured:</p>
<ul id="form-errors">
{{ $errors->first('username', '<li>:message</li>') }}
{{ $errors->first('password', '<li>:message</li>') }}
{{ $errors->first('password_confirmation', '<li>:message</li>') }}
{{ $errors->first('email', '<li>:message</li>') }}
</ul>
#endif
{{ Form::open(array('action'=>'register')) }}
<p>
{{ Form::label('username', 'Username') }}<br />
{{ Form::text('username', Input::old('username')) }}
</p>
<p>
{{ Form::label('email', 'Email Address') }}<br />
{{ Form::text('email', Input::old('email')) }}
</p>
<p>
{{ Form::label('password', 'Password') }}<br />
{{ Form::password('password') }}
</p>
<p>
{{ Form::label('password_confirmation', 'Confirm Password') }}<br />
{{ Form::password('password_confirmation') }}
</p>
<p>
{{ Form::submit('Register') }}
</p>
{{ Form::close() }}
basemodel.php
class BaseModel extends Eloquent {
public static function validate($data) {
return Validator::make($data, static::$rules);
}
}

In your UsersController::postCreate() function you're not returning the Redirect::to() in your else{} and so the response isn't being sent back to the user. The controller is just executing without returning anything and so you're left with a blank page.
Redirect::to('register')->withErrors($validation)->withInput();
needs to become
return Redirect::to('register')->withErrors($validation)->withInput();

Related

Laravel form validation doesn't seem to work

I'm making my first form in Laravel and the generation of the form is all working. It's just that the store function seems to blindly return the user to my contact page irrelevant of the result of the form validation.
So if the email address posted isn't an email but a random string I still get returned to the /contact page with the thank you message being sent to the view.
My controller looks like this:
namespace App\Http\Controllers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\DB;
use App\Http\Requests\ContactFormRequest;
class ContactController extends Controller {
public function create(){
return view('contact');
}
public function store(ContactFormRequest $request) {
return \Redirect::route('contact')
->with('message', 'Thanks for contacting us!');
}
}
And the form handler like this:
namespace App\Http\Requests;
use Illuminate\Http\Request;
class ContactFormRequest extends Request {
public function authorize() {
return true; // don't need to be registered to run form so true
}
public function rules() {
return [
'email' => 'required|email',
];
}
}
This is controlled by the following routes
if (config('app.tan_site_page_contact')===true){
Route::get('/contact', ['as' => 'contact', 'uses' => 'ContactController#create']);
Route::post('/contact', ['as' => 'contact_store', 'uses' => 'ContactController#store']);
});
And the form like this:
<ul>
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
#if(Session::has('message'))
<div class="alert alert-info">
{{Session::get('message')}}
</div>
#endif
{!! Form::open(array('route' => 'contact_store', 'id' => 'contactCallMeForm')) !!}
{!! Form::label('Your E-mail Address') !!}
{!! Form::text('email', null, array('required', 'class'=>'form-control', 'placeholder'=>'Your e-mail address')) !!}
{!! Form::submit('Contact Us!', array('class'=>'btn btn-primary')) !!}
{!! Form::close() !!}
The form html seems fine,with a token and valid url
<form method="POST" action="http://localhost/contact" accept-charset="UTF-8" id="contactCallMeForm" novalidate="">
<input name="_token" type="hidden" value="VNHchLZhfsXadVZXCZWHGdAuJ4zgmO6cDJIGhR59">
<label for="Your E-mail Address">Your E-mail Address</label>
<input required="required" class="form-control" placeholder="Your e-mail address" name="email" type="text">
<input class="btn btn-primary" type="submit" value="Contact Us!">
</form>
The problem here is your ContactFormRequest class.
You extends it from invalid Request class. You extend it from \Illuminate\Http\Request class but you should extend it from \Illuminate\Foundation\Http\FormRequest (or \App\Http\Requests\Request class)

Form doesn't get submitted

I have started to study Symfony2 since I will probably need in my work.
routing.yml:
account_register:
path: /register
defaults: {_controller: AppBundle:Register:index}
RegisterController:
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Entity\User;
class RegisterController extends Controller
{
/**
* #Route("/register")
*/
public function indexAction(Request $request)
{
$register = new User();
$form = $this->createFormBuilder($register)
->add('email', 'email', array('required' => false))
->add('password', 'password', array('required' => false))
->add('alias', 'text', array('required' => false))
->add('register', 'submit', array('label' => 'Register'))
->getForm();
$form->handleRequest($request);
if ($form->isValid()) {
// perform some action, such as saving the task to the database
$em = $this->getDoctrine()->getManager();
$em->persist($register);
$em->flush();
exit("Error");
//return $this->redirectToRoute('task_success');
}
return $this->render('pages/register.html.twig', array(
'form' => $form->createView(),
));
}
}
regiser.html.twig:
{% extends 'base.html.twig' %}
{% block body %}
<br /><br />
<div class = "window">
<form>
<br /><br /><br /><br /><br /><br /><br />
{{ form_start(form) }}
{{ form_errors(form) }}
<div id=center-text>Email</div>
<div class="textfield" id=center> {{ form_widget(form.email, {'attr': {'class': 'textfield', 'size': '22', 'maxlength': '100'}}) }} </div>
<br />
<div id=center-text>Password</div>
<div class="textfield" id=center> {{ form_widget(form.password, {'attr': {'class': 'textfield', 'size': '22', 'maxlength': '100'}}) }} </div>
<br />
<div id=center-text>Alias</div>
<div class="textfield" id=center> {{ form_widget(form.alias, {'attr': {'class': 'textfield', 'size': '22', 'maxlength': '100'}}) }}</div>
<br /><br />
<br />
<center>
{{ form_widget(form.register, {'attr': {'class': 'button'}}) }}
</center>
{{ form_end(form) }}
</form>
{% endblock %}
When i press the submit button only the url changes from http://localhost/website/web/app_dev.php/register
to
http://localhost/website/web/app_dev.php/register?form%5Bemail%5D=&form%5Bpassword%5D=&form%5Balias%5D=&form%5Bregister%5D=&form%5B_token%5D=hd70y_KjUEY8v51dQjnjU0ZMTJ0BYOihurV6IcIvghY
What is happening is the expected form's flow. The form that you are submitting is redirecting to the same page.
If you don't want your form to be in GET, you can change it for POST :
$form = $this->createFormBuilder($register)
->setMethod('POST')
->...
When you are redirected after submitting the form, $form->handleRequest($request) binds the request (your data submitted) with the form that is just created. $form->isValid() then checks if your data is valid according to your form.
If you don't see any change after being redirected, you should check if $form->isValid() returns true.
If you want to redirect your form to another controller method, you should create another resource and then set the action attribute of your form thanks to the setAction() method.
To sum up, everything that I just told you is written and explained on this page, and you definitely should read it ! :-).
Silly me, the html was my test code and then i added the symfony {{ blocks }} and forgot to remove the old tags

Laravel Eloquent Model - can't access database

I'm trying to write a simple site that can write and read of a simple mysql database, using Laravel, but I've run into a full stop as Laravel doesn't seem to be recognising my model. Either that or I am doing something wrong.
My model:
class Submission extends Eloquent
{
public static $timestamps = true;
protected $fillable = array('location', 'twitter', 'instagram', 'website');
}
My form:
#extends('layout')
#section('content')
{{ Input::old('twitter') }} <br />
{{ Input::old('instagram') }} <br />
{{ Input::old('website') }} <br />
{{ Form::open(array('url' => '/submission', 'files' => true)) }}
<div class="form-group">
{{ Form::label('twitter', 'Twitter') }}
{{ Form::text('twitter', '', array('class' => 'form-control')) }}
</div>
<div class="form-group">
{{ Form::label('instagram', 'Instagram') }}
{{ Form::text('instagram', '', array('class' => 'form-control')) }}
</div>
<div class="form-group">
{{ Form::label('website', 'Website') }}
{{ Form::text('website', '', array('class' => 'form-control')) }}
</div>
{{ Form::button('Submit image', array('class' => 'btn btn-success', 'type' => 'submit')) }}
<input type="hidden" name="post" value="yes">
{{ Form::close() }}
#stop
My controller:
public function postView()
{
$submission = new Submission;
$submission->twitter = Input::get('twitter');
$submission->instagram = Input::get('instagram');
$submission->website = Input::get('website');
$submission->save();
return Redirect::to('submission')->withInput();
}
My database looks like: id location twitter instagram website created_at updated_at
I know that my database config is correct as I can retrieve information using DB::table('submissions')->get(); so from what I can tell it's Laravel that's not recognising my model?
EDIT:
Turns out that changing public static $timestamps = true; to public $timestamps = true; fixed it.
Does this works :
DB::table('submissions')->get();
as it should return everything in the table. If it works then Eloquent can't find your table you can try to put that in your model:
protected $table = 'submissions';
It will define explicitly the table name in the model, even if it seems correct in your case
Otherwise you need to tell what exactly laravel answers when you made a request.
Do you have an error message in your browser ?
Do you have an error message in your log file (check the app/storage/logs folder)
Is your database configuration ok ? (app/config/database.php)
Did you create the table using a laravel migration ?
Hope it helps

Laravel 4 getting information from database for drop-down form

I am trying to make a simple authentication application and I have the login/signup form in place and it is working correctly. However, I am having issues with populating the drop-down field for a zip-code from another table. I am not really sure how i should approach this. Most of the time i would just use straight mysql query but I am assuming there is an easier way.
Controller: (would love for the zip_code table to go here.)
public function getSignUp() {
$userdata = array(
'email' => Input::get('email'),
'password' => Hash::make(Input::get('password'))
);
$user = new User($userdata);
$user->save();
return Redirect::to('dashboard');
}
Route
Route::post('signup', 'LoginController#getSignUp');
signup.blade.php
{{ Form::label('email', 'Email:') }}<br />
{{ Form::text('email') }}<br />
{{ Form::label('password', 'Password:') }}<br />
{{ Form::password('password') }}<br />
{{ Form::label('zip_code', 'Zip Code:') }}<br />
{{ Form::select('zip_code', array('zip_code' => '', 'city' => '')); }}<br />
{{ Form::submit() }}<br />
{{ Form::close() }}
This is how I would normally call database information before this
public function showHome()
{
$testimonials = DB::select('SELECT * FROM `testimonials` WHERE `id`=' . mt_rand(1, 2));
return View::make('home.index', array('pageTitle' => 'Home'))->with('testimonials', $testimonials);
}
but with me not returning a view and therefor no variables are going to be passed I am not sure how to achieve this
Any advice would be highly appreciated!
You can easily list out data from an Eloquent model for a select field using the lists() function.
Testimonial::lists('content', 'id');

Why did I get a string with when binding a request with Symfony2?

I'm trying to update an object:
public function editAction(Artist $artist)
{
if (!$artist) {
throw $this->createNotFoundException('Unable to find Artist entity.');
}
// We create the form from the external re-usable form made in TestBundle/Form/artist.php
$form = $this->createForm( new ArtistType, $artist);
// We get the request type
$request = $this->get('request');
// If it is a POST request, the user validated the form
if ($request->isMethod('POST')) {
// We make the link Request <-> Form
// Now, $request = Values entered by the user
$form->bind($request);
// We validate the values
if ($form->isValid()) {
// We save $artist in the DB
$em = $this->getDoctrine()->getManager();
$em->persist($artist);
$em->flush();
$this->get('session')->getFlashBag()->add('info', 'Artist edited successfully');
// Everything is fine, we redirect the user
return $this->redirect($this->generateUrl('ymtest_Artist'));
}
}
// We pass the createView() form method to the viexw so that it can print the form if the user arrived on this page with a GET method (he didnt validate the form yet)
return $this->render('YMTestBundle:Musician:edit.html.twig', array(
'form' => $form->createView(),
'artist' => $artist
));
}
But when I'm validating the form, I get an exception:
Expected argument of type object or array, string given
My form looks like this:
{# src/YM/TestBundle/Resources/views/Musician/add.html.twig #}
{% extends "YMTestBundle::layout.html.twig" %}
{% block bodyAdmin %}
<div class="container">
<form action="{{ path('ymtest_EditArtist', {'id': artist.id}) }}" method="post" {{ form_enctype(form) }}>
<div class="row">
{% if form_errors(form)|length != 0 %}
<div class="span12 alert alert-error" style="margin-left:0px">
{# Les erreurs générales du formulaire. #}
{{ form_errors(form) }}
</div>
{% endif %}
</div>
<div class="row">
<div class="span10 BoxesW">
<div>
{{ form_label(form.name, "Artist Name") }}
{{ form_errors(form.name) }}
{{ form_widget(form.name) }}
</div>
<div>
{{ form_label(form.biography, "Artist Biography") }}
{{ form_errors(form.biography) }}
{{ form_widget(form.biography, {'attr':{'class': 'span10' }, 'id': 'wysiwyg' }) }}
</div>
{{ form_rest(form) }}
</br>
<div>
<input type="submit" class="btn btn-primary" />
</div>
</div>
</div>
</form>
</div>
{% endblock %}
And the route is correct since I get the form before validating it.
Thanks for your help
UPDATE:
Here is My new controller:
<?php
namespace YM\TestBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Doctrine\ORM\EntityRepository;
use YM\TestBundle\Entity\Artist;
use YM\TestBundle\Form\ArtistType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
class MusicianController extends Controller
{
/**
* #Route("/Artist/edit/{id}")
* #ParamConverter("artist", class="YMTestBundle:Artist")
*/
public function editAction(Artist $artist)
{
if (!$artist) {
throw $this->createNotFoundException('Unable to find Artist entity.');
}
// We create the form from the external re-usable form made in TestBundle/Form/artist.php
$form = $this->createForm( new ArtistType, $artist);
// We get the request type
$request = $this->get('request');
// If it is a POST request, the user validated the form
if ($request->isMethod('POST')) {
// We make the link Request <-> Form
// Now, $request = Values entered by the user
$form->bind($request);
// We validate the values
if ($form->isValid()) {
// We save $artist in the DB
$em = $this->getDoctrine()->getManager();
$em->persist($artist);
$em->flush();
$this->get('session')->getFlashBag()->add('info', 'Artist edited successfully');
// Everything is fine, we redirect the user
return $this->redirect($this->generateUrl('ymtest_Artist'));
}
}
// We pass the createView() form method to the viexw so that it can print the form if the user arrived on this page with a GET method (he didnt validate the form yet)
return $this->render('YMTestBundle:Musician:edit.html.twig', array(
'form' => $form->createView(),
'artist' => $artist
));
}
}
EDIT
We found in the chat that the problem was in the entity annotations.
#Assert\Valid() was used on a string variable.
You have this action="{{ path('ymtest_EditArtist', {'id': artist.id}) }}" that I suppose generates an url like editArtist/1234 (so passing a string).
And then you have this public function editAction(Artist $artist) that's requiring an object of type Artist.
You should change it to something like:
public function editAction($artistid)
{
$em = $this->getDoctrine()->getManager();
$artist= $em->getRepository('YourBundle:Artist')->find($artistid);
if (!$artist) {
throw $this->createNotFoundException('No artist found for id '.$artistid);
}
//Do whatever you want
}
Remark: You don't need to call $em->persist($artist); when updating an object (http://symfony.com/doc/current/book/doctrine.html#updating-an-object).

Categories