i am trying to implement update profile functionality, here's the form which is saving the data
form
and here's the controller which is supposed to be saving image to the path controller
there is relation in photo and user which is in the user class.
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'firstName', 'lastName','userName' ,'email', 'password','photo_id',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function photo(){
return $this->belongsTo('App\Photo');
}
and here are the request files.
public function rules()
{
return [
'firstName'=> 'required',
'lastName' => 'required',
'userName' => 'required',
'photo_id' => 'required',
'email' => 'required',
];
}
When you want to use files you should add:
'files' => true
to your form options:
{!! Form::model($user, [..., 'files' => true]) !!}
(in place of ... you should put your other options - sorry I won't write text from image)
According to your question, I am going to assume your problem is just about images not being moved to correct path. In your controller try changing it like this
$file->move(yourdirectory .'/images/', $name);
Notice the . and / at the beginning of the directory. If you want the public path use public_path() function.
Related
Ok so I'm half way trough my app and I notice that I can pass code into my database. For example I use standard laravel authentication and if I type e.g.<?php die(); ?> instead of first name it passes right trough and goes into database. I'm confused now , I tought that laravel takes care of those things and thats one of the reasons I chose this framework. This is my last resort, I have been searching something in laravel documentation and all over the web about this and I found nothing.
Register Controller:
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'role' => ['required', 'string', 'max:100'],
'gendre' => ['required', 'string', 'max:100'],
'firstname' => ['required', 'string', 'max:100'],
'lastname' => ['required', 'string', 'max:100'],
'country' => ['required', 'string', 'max:100'],
'company' => ['required', 'string', 'max:100'],
'phone' => ['required', 'string', 'max:15'],
'email' => ['required', 'string', 'email', 'max:100', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
return User::create([
'role' => $data['role'],
'gendre'=>$data['gendre'],
'firstname' => $data['firstname'],
'lastname' => $data['lastname'],
'country' => $data['country'],
'company' => $data['company'],
'phone' => $data['phone'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
}
}
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 implements MustVerifyEmail
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'firstname', 'lastname' , 'email','password', 'company', 'phone','country','role','gendre'
];
/**
* 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',
];
}
I only did some minor changes to what laravel already provides, nothing that special.
And Migration:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('role');
$table->string('gendre');
$table->string('firstname');
$table->string('lastname');
$table->string('country');
$table->string('company');
$table->string('phone');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
I think there may be a little bit of confusion going on here!
SQL Injection Attacks
The Laravel framework uses things like prepared statements to prevent SQL Injection Attacks. The stops things like
"; DELETE FROM `users`"
being appended to a database query when inserting data provided by form requests.
Escaping Rendered Characters
Trying to render content into a blade template will also be escaped by default unless you explicitly tell it otherswise
# $php_code = "<?php die(); ?>"
{{ $php_code }}
This will render as a a string of "".
# $php_code = "<?php die(); ?>"
{!! $php_code !!}
This will render the php and stop the script from running
TLDR;
The fact the the input is "<?php die(); ?>" is fine provided it is treated as a string. At the end of the day, It's just a string of valid characters
I am getting an error while trying to Auto Login After successful registration in laravel 6 getting the following error.
Argument 1 passed to Illuminate\Auth\SessionGuard::login() must implement interface Illuminate\Contracts\Auth\Authenticatable, null given, called in
My Registercontroller is
class RegisterController extends Controller
{
use RegistersUsers;
protected $redirectTo = RouteServiceProvider::HOME;
public function __construct()
{
$this->middleware('guest');
// $this->middleware(['auth','verified']);
}
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'min:3'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
protected function create(array $data)
{
$username = slugify($data['name'])."-".mt_rand(10000, 99999);
$user = User::create([
'name' => $data['name'],
'username' => $username,
'email' => $data['email'],
'password' => Hash::make($data['password']),
'email_token' => base64_encode($data['email']),
]);
Auth::loginUsingId($user->id);
}
}
User Model
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use App\Jobs\SendEmailJob;
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'email','name','password','username','picture',
'ip_address','email_verified_at','email_token','verified'
];
/**
* 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',
];
function socialProviders(){
return $this->hasMany(socialProvider::class);
}
// This is the code define in the sendEmailVerificationNotification
public function sendEmailVerificationNotification()
{
SendEmailJob::dispatch($this);
}
}
You have overwritten the registration logic, but you have ignored the fact that create method needs to return an instance of App\User - or at least a class that implements Authenticatable.
Take a look at the original logic; you will see that the docblock shows that an instance of App\User is being returned and that the original implementation returns the result of the User::create() call.
To get your custom method working, update it like so:
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'username' => slugify($data['name'])."-".mt_rand(10000, 99999);,
'email' => $data['email'],
'password' => Hash::make($data['password']),
'email_token' => base64_encode($data['email']),
]);
}
Laravel will take care of logging the user in by default anyway.
I have generated Laravel's authentication code using
php artisan make:auth
The auto-generated registration form provides the following fields:
Name, Email, and Password.
I'm trying to add First Name, Last Name instead of just Name. I've successfully created the DB Table and the form(view) with the fields. When I test and register a user the password and email fields are saved but not the First Name and Last Name.
My guess is that I'm missing a file that I have not modified.
What page defines the fields that get written into the database?
This is my validator and auth code in authcontroller:
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'first_name' => 'required|max:255',
'last_name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:8|confirmed',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
return User::create([
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
If I change 'first_name' to 'name' on the controller and the database table it does save. Validator works well.
You need to go to you AuthController which should be in app/Http/Controllers/Auth.
In there you will need to change the validator() and create() methods to include firstname and lastname fields.
Hope this helps!
The modification that I was missing was on the user.php file:
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'first_name', 'last_name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
The fields that I added needed to be included as protected $fillable. I made that change and everything is working.
I'm trying to find out why when I dd($request->all()) in the store method of my controller everything is correct, however when I send it to the model function register() its no where to be seen.
I'm not quite sure what I'm doing wrong.
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class UsersController extends Controller
{
public function store(Request $request, User $user)
{
$this->authorize('delete', $user);
$this->validate($request, [
'firstName' => 'required|min:3',
'lastName' => 'required|min:3',
'displayName' => 'required|min:3',
'emailAddress' => 'required|email|unique:users,email',
'password' => 'required|min:3',
'role' => 'required|exists:roles,id'
]);
$userRegistered = $user->register(
new User($request->all())
);
if ($userRegistered) {
flash()->success('Success', 'The user has been successfully created!');
} else {
flash()->error('Error', 'The user could not be successfully created!');
}
return redirect()->to(route('users'));
}
}
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Authenticatable
{
use SoftDeletes;
/**
* Fillable fields for a user.
*
* #var array
*/
protected $fillable = [
'first_name',
'last_name',
'display_name',
'email',
'password',
'role_id'
];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function register(User $user)
{
return $user->create([
'first_name' => $user->firstName,
'last_name' => $user->lastName,
'display_name' => $user->displayName,
'email' => $user->emailAdress,
'password' => $user->password,
'role_id' => $user->role
]);
}
}
You've mixed up the formatting of your variables between your request data and your User model.
According to your validation logic, the request data is coming is as camelCase. Yet, according to your $fillable array, the fields on your User model are snake_case. But, even then, in your register method, you're attempting to access the fields on the User model using camelCase.
You haven't given enough information for a definitive answer, but you need to fix the formatting of your variables. For example, change your request fields names from camelCase to snake_case, and make sure you access your fields on the model using snake_case.
You have to pass a list of attributes to "validate" method.
//...
$this->validate($request->all(), [
'firstName' => 'required|min:3',
'lastName' => 'required|min:3',
'displayName' => 'required|min:3',
'emailAddress' => 'required|email|unique:users,email',
'password' => 'required|min:3',
'role' => 'required|exists:roles,id'
]);
One more thing..check if you are using "web" middleware. (Kernel.php => MiddlewareGroups). Add that middleware to your route.
So I am trying to group all my validation rules into its respective files in folders for easy maintenance. Below is how my folder structures look:
Project
--app
--config
--(more folders)
--domains
----App
--------Entities
--------Repositories
--------Services
--------Validators
----Core
--------Validators
So what I wanted to achieve is under Core\Validators I created a LaravelValidator.php which look like this
<?php namespace Core\Validators;
use Validator;
abstract class LaravelValidator {
/**
* Validator
*
* #var \Illuminate\Validation\Factory
*/
protected $validator;
/**
* Validation data key => value array
*
* #var Array
*/
protected $data = array();
/**
* Validation errors
*
* #var Array
*/
protected $errors = array();
/**
* Validation rules
*
* #var Array
*/
protected $rules = array();
/**
* Custom validation messages
*
* #var Array
*/
protected $messages = array();
public function __construct(Validator $validator)
{
$this->validator = $validator;
}
/**
* Set data to validate
*
* #return \Services\Validations\AbstractLaravelValidator
*/
public function with(array $data)
{
$this->data = $data;
return $this;
}
/**
* Validation passes or fails
*
* #return Boolean
*/
public function passes()
{
$validator = Validator::make(
$this->data,
$this->rules,
$this->messages
);
if ($validator->fails())
{
$this->errors = $validator->messages();
return false;
}
return true;
}
/**
* Return errors, if any
*
* #return array
*/
public function errors()
{
return $this->errors;
}
}
Then in my App\Validators I created a file name RegistrationFormValidator.php which look like this
<?php namespace App\Validators\Profile;
class RegistrationFormValidator extends \Core\Validators\LaravelValidator
{
protected $rules = array(
'first_name' => 'required',
'last_name' => 'required',
'username' => 'required',
'password' => 'required',
'rTPassword' => 'required',
'profile_url' => 'required',
'email' => 'required|email',
'gender' => 'required',
'dob' => 'required',
);
}
so usually in laravel 4.2, to validate something all i do is construct the validation rules and then call it in services which look like this
<?php namespace App\Services\Profile;
/*
|-----------------------------------------------------------
| This section injects the repositories being used
| in this service.
|-----------------------------------------------------------
*/
use App\Repositories\Profile\ProfileRepository;
use Core\ValidationFailedException;
use App\Validators\Profile\RegistrationFormValidator;
use Validator;
class ProfileService implements ProfileServiceInterface
{
protected $_profile;
protected $v;
/*
|-----------------------------------------------------------
| All construsted models variables must carry
| the '_' sign to identify it as a model variable
|-----------------------------------------------------------
*/
public function __construct(ProfileRepository $_profile, RegistrationFormValidator $v)
{
$this->_profile = $_profile;
$this->v = $v;
}
/*
|-----------------------------------------------------------
| 1. All try and catch error handling must be done
| in the respective controllers.
|
| 2. All data formattings must be done in this section
| then pass to repository for storing.
|
| 3. No controller actions allown in this section
|-----------------------------------------------------------
*/
public function createProfile($array)
{
if($this->v->passes())
{
//save into db
}
else
{
throw new ValidationFailedException(
'Validation Fail',
null,
$this->v->errors()
);
}
}
}
But the problem is once i upgraded into laravel 5 i did the same thing and when i try to execute the code it returns me with this error
ErrorException in ProfileService.php line 26:
Argument 2 passed to App\Services\Profile\ProfileService::__construct() must be an instance of App\Validators\Profile\RegistrationFormValidator, none given
My code works absolutely fine in L4.2 but once i upgraded it wont work anymore. I also know that i can do validation like such
public function createProfile($array)
{
$v = Validator::make($array, [
'first_name' => 'required',
'last_name' => 'required',
'username' => 'required',
'password' => 'required',
'rTPassword' => 'required',
'profile_url' => 'required',
'email' => 'required|email',
'gender' => 'required',
'dob' => 'required',
]);
if($v->passes())
{
}
else
{
throw new ValidationFailedException(
'Validation Fail',
null,
$v->errors()
);
}
}
But the problem is if i would have more validation rules or scenario it will flood the whole service file.
Any suggestions or solutions that will guide me? thanks in advance!
In Laravel 5 you have something similar, which handles better the validation and makes validation clean and easy. It is called Form Request Validation. The idea there is the same - to have different classes that handle validation in different scenarios.
So whenever you need a validation you can create new FormRequest, like this:
php artisan make:request RegisterFormRequest
A new class will be generated under app/Http/Requests. There you can see it has two methods authorize and rules. In the first one you can make a check if given user is allwed to make this request. In the second method you can define your rules, just like in the validator.
public functions rules() {
return array(
'first_name' => 'required',
'last_name' => 'required',
'username' => 'required',
'password' => 'required',
'rTPassword' => 'required',
'profile_url' => 'required',
'email' => 'required|email',
'gender' => 'required',
'dob' => 'required',
);
}
Then you can change your controller method like this:
public function postCreateProfile(RegisterFormRequest $request) {
// your code here
}
The are a few cool things here. First one - the class will be automatically constructed in injected in your controller method by the IoC container, you don't need to do something special. The second cool thing is that the validation check is done before the Request object is passed to the controller, so if any validation error occurs you will be redirected back with all errors according to your rules set. This means that writing your code in the postCreateProfile method you can assume if this code get executed the validation is passed at this position and no additional check are needed by you.
I suggest you to migrate your code to use Laravel 5 Form Requests, because what you need is already implemented in the framework, and yes basically this is the point of the migration of one version to another. You can also check the documentation for more examples.