Laravel 5 Validation in controller - php

I have 2 methods in my Controller and I need to validate it but I don't know how.
1st method which should allow all image extensions:
public function testing(Request $request) {
if($request->hasFile('img')) {
$image = Input::file('img');
$filename = time() . '.' . $image->getClientOriginalExtension();
$path = public_path('images/' . $filename);
Image::make($image->getRealPath())->resize(200, 200)->save($path);
$file = $request->file('img');
return ['url' => url('images/' . $filename)];
}
}
2nd method which should only allow 1 word and if there is space, trim it into 1 word:
public function postDB(Request $request) {
$newName = $request->input('newName');
$websites = new Website();
$websites->name = $newName;
$websites->save();
return redirect('template')->with('status', 'Website has been saved successfully!');
}

First write new Request for your data
php artisan make:request ImageRequest
Than write in ImageRequest:
public function authorize()
{
return true;
}
public function rules()
{
return [
'img' => 'file|image',
]
}
If you want to customize error messages:
public function messages()
{
return [
'img.image' => 'Some custom message ...',
];
}
Last inject request to your method (don`t forget about use App\Http\Requests):
public function testing(Requests\ImageRequest $request) {
//for retrieving validation errors use:
$imgErrors = $errors->first('img');
}
More information about Form Request Validation
Or you can use Validator facade (don`t forget about use Validator):
$validator = Validator::make(
$image, [
'img' => 'file|image',
]
);
More information about A Note On Optional Fields

Related

How to create custom validation rule for dependent input fields in laravel

In my input form, I have two fields; momentFrom & momentTo. I need to put a validation which gives error message if any of the following criteria fails.
momentFrom is greater than or equal to momentTo.
momentFrom is less than now.
My code for storing the data:
public function store(Request $request, Requisition $requisitionObj) {
$momentFrom = strtotime($request->txtTravelDate . " " . $request->txtTimeFrom);
$momentTo = strtotime($request->txtTravelDate . " " . $request->txtTimeTo);
$timeValidation = $requisitionObj->validateTiming($momentFrom, $momentTo);
if ($timeValidation['error']) {
echo 'ERROR: ' . $timeValidation['message'];
return view('requisitions.create');
} else {
/* store form data into requisition object */
$requisitionObj->travel_date = $request->txtTravelDate;
$requisitionObj->moment_from = $momentFrom;
$requisitionObj->moment_to = $momentTo;
$requisitionObj->save();
return redirect()->route('requisitions.index');
}
}
I have seen laravel custom validation rules where only one field can be validated at a time. But in my scenario I need to check both fields at a time depending on each other. How can I achieve this?
Thanks for any help in advance!
Creating new Rule Class
You can create your custom rule with the artisan command: php artisan make:rule YourRuleNamethis will create a new Rule Class file into the Rules folder.
By default the created file contains a constructor, a passes method and a message method.
Rules Logic
If you have some complicated rules where you need the request or some models, you can pass them via the constructor.
public function __construct(Request $request, User $user, ....)
{
//save them into class variables to access them later
$this->request = $request;
$this->user = $user;
}
Otherwise you can directly put your validation logic into the passes method:
public function passes($attribute, $value){
//some code
return #myCondition
}
Last you are able to specify the message if the validation fails.
public function message()
{
return 'Your message';
}
To use your rule simply add it to your rules array:
$rules = [
'my_attribute' => [new MyCustomRule(),...],
]
At last, I have solved this problem using FormRequest and AppServiceProvider. Thought this would help others who come to this place.
First I have created FormRequest validator using following artisan command.
php artisan make:request StoreRequisition
Then added primary validation rules and messages into it.
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreRequisition extends FormRequest {
public function authorize() {
return true;
}
public function rules() {
$rules = [
'txtTravelDate' => 'required|date_format:Y-m-d|after_or_equal:today',
'txtTimeFrom' => 'required|date_format:H:i|travel_time_validate',
'txtTimeTo' => 'required|date_format:H:i',
];
return $rules;
}
public function messages() {
return [
'txtTravelDate.required' => 'Travel date is required!',
'txtTravelDate.date_format' => 'Invalid format for Travel Date!',
'txtTravelDate.after_or_equal' => 'Travel Date should be today or later!',
'txtTimeFrom.required' => 'Time From is required!',
'txtTimeFrom.date_format' => 'Invalid format for Time From!',
'txtTimeFrom.travel_time_validate' => 'Invalid time selected!',
'txtTimeTo.required' => 'Time To is required!',
'txtTimeTo.date_format' => 'Invalid format for Time To!',
'listFunction.required' => 'Department to be selected!',
'txtPickLoc.required' => 'Pickup Location is required!',
'txtDropLoc.required' => 'Drop Location is required!',
'listPurpose.required' => 'Travel Purpose to be selected!'
];
}
}
Then inside app\Providers\AppServiceProvider, added the extra validation logic.
public function boot() {
Validator::extend(
'travel_time_validate',
function ($attribute, $value, $parameters, $validator) {
$inputs = $validator->getData();
/* convert time to moments */
$momentFrom = strtotime($inputs['txtTravelDate'] . " " . $inputs['txtTimeFrom']);
$momentTo = strtotime($inputs['txtTravelDate'] . " " . $inputs['txtTimeTo']);
$result = true;
if ($momentFrom >= $momentTo) {
$result = false;
}
return $result;
}
);
}
My Controller:
public function store(StoreRequisition $request, Requisition $requisitionObj) {
$validatedData = $request->validated();
/* store form data into requisition object */
$requisitionObj->requester_id = Auth::user()->id;
$requisitionObj->travel_date = $request->txtTravelDate;
$requisitionObj->time_from = $request->txtTimeFrom;
$requisitionObj->time_to = $request->txtTimeTo;
$requisitionObj->purpose_id = $request->listPurpose;
/* Finally save the record into the database */
$requisitionObj->save();
return redirect()->route('requisitions.index');
}
Example how make custom rule for validation in Laravel 8.x / Lumen 8.x.
public static function rules(){
return [
'number' => [
'required', 'min:1', 'max:30', 'string', self::testNumber(),
],
];
}
public static function testNumber(){
return function($attribute, $value, $fail){
if ($value === 'foo'){
$fail('The '.$attribute.' is invalid.');
}
};
}

File exist but laravel can't find it (FileNotFoundException)

I'm trying to check if the file exists to delete it when the post is deleted but it's never finding it.
If I change the Storage::exists() for Storage::get() just to check, I get the File Not Found Exception with the path C:/xampp/htdocs/cms/blog/public/images/apple.jpg which I can see the picture if I put in the browser.
Store function on PostController
public function store(CreatePostRequest $request)
{
$input = $request->all();
if ($file = $request->file('file')) {
//
$name = $file->getClientOriginalName();
$file->move(public_path('images/'), $name);
$input['path'] = $name;
}
$new_post = Post::create($input);
return redirect(route('post.show', $new_post->id));
}
Destroy function on PostController
public function destroy($id)
{
$post = Post::findOrFail($id);
if (Storage::exists(public_path('images/') . $post->path))
Storage::delete(public_path('images/') . $post->path);
$post->delete();
return redirect(route('posts.index'));
}
I also have this on my filesystems.php
'links' => [
public_path('storage') => storage_path('app/public'),
public_path('images') => storage_path('app/images'),
],
I can easily show the image in blade with just src="{{'/images/' . $post->path}}"
You could try using unlink.
$image_path = $post->path;
unlink($image_path);
The second option is to use the File Facade.
use Illuminate\Support\Facades\File;
$filename = $post->path;
File::delete($filename);
Make sure that the image path is correct.
I Had to use the Illuminate\Support\Facades\File sugested by Aless
Fixed destroy funcion on PostController
public function destroy($id)
{
$post = Post::findOrFail($id);
$imagePath = public_path('images/') . $post->path;
if (File::isFile($imagePath))
File::delete($imagePath);
$post->delete();
return redirect(route('posts.index'));
}

how I can pass the token to header not in body using jwt.auth middleware :laravel 5.6

I use post man to test my api , So when I send the token in header I get token not provided , but when i pass it in body raw in json format I get a succes result, So I want to get succes result when I pass my token in header
How I can make this change ??
This my Postcompanies controller
class CompaniesController extends Controller
{
public function index(Request $request)
{
# code...
// $Ads = ads::all();
// return $this->sendResponse($Ads->toArray(), 'Ads read succesfully');
// This is the name of the column you wish to search
$input = $request->all();
$validator = Validator::make($input, [
'user_id'=> 'required'
] );
$Companies = Companies::where('user_id','=', $request->user_id)->first();
return response()->json(['Companies'=>$Companies]);
}
public function stockcompanies (Request $request){
$input = $request->all();
$validator = Validator::make($input, [
'title'=> 'required',
'description'=> 'required',
'logo_path'=> 'image|nullable|max:1999'
] );
$user_id = Auth::id();
if($request->hasFile('logo_path')){
// Get filename with the extension
$filenameWithExt = $request->file('logo_path')->getClientOriginalName();
// Get just filename
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
// Get just ext
$extension = $request->file('logo_path')->getClientOriginalExtension();
// Filename to store
$fileNameToStore= $filename.'_'.time().'.'.$extension;
// Upload Image
$path = $request->file('logo_path')->storeAs('public/cover_images', $fileNameToStore);
} else {
$fileNameToStore = 'noimage.jpg';
}
if ($validator -> fails()) {
# code...
return response()->json($validator->errors());
}
//$Cards = CreditCards::create($input,$user_id);
$companies = Companies::create([
'title' => $request->get('title'),
'description' => $request->get('description'),
'logo_path' => $fileNameToStore,
'user_id' => $user_id
]);
return response()->json(['Companies'=>$companies]);
}
}
and this is my api :
Route::group(['middleware' => ['jwt.auth']], function() {
Route::post('postmycompanies', 'CompaniesController#stockcompanies');
Route::get('test', function(){
return response()->json(['foo'=>'bar']);
});
I resolve my probleme :
I use a custom middelware
namespace App\Http\Middleware;
use Closure;
use JWTAuth;
use Exception;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
class JwtMiddleware extends BaseMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
try {
$user = JWTAuth::parseToken()->authenticate();
} catch (Exception $e) {
if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException){
return response()->json(['status' => 'Token is Invalid']);
}else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException){
return response()->json(['status' => 'Token is Expired']);
}else{
return response()->json(['status' => 'Authorization Token not found']);
}
}
return $next($request);
}
}
Next, we need to register our middleware. Open app/http/Kernel.php and add the following:
[...]
protected $routeMiddleware = [
[...]
'jwt.verify' => \App\Http\Middleware\JwtMiddleware::class,
];
[...]
Next, Open routes/api.php and add the content with the following:
Route::group(['middleware' => ['jwt.verify']], function() {
Route::post('postmycompanies', 'CompaniesController#stockcompanies');
});

How to make Laravel controller store file upload with a relationship

I am trying to store an uploaded file with a relationship to an Employee model. I am unable to retrieve the employee id after uploading the file to save it to the DB table as a foreign key.
Routes:
Route::resource('employees', 'EmployeesController');
Route::post('documents', 'DocumentsController#createdocument')
So I am on a URL that says http://localhost/public/employees/8 when I hit upload it redirects to http://localhost/public/documents and the file does upload but shows error when writing to DB.
Here is my code. How can I do it?
public function createdocument(Request $request, Employee $id)
{
$file = $request->file('file');
$allowedFileTypes = config('app.allowedFileTypes');
$maxFileSize = config('app.maxFileSize');
$rules = [
'file' => 'required|mimes:'.$allowedFileTypes.'|max:'.$maxFileSize
];
$this->validate($request, $rules);
$time = time(); // Generates a random string of 20 characters
$filename = ($time.'_'.($file->getClientOriginalName())); // Prepend the filename with
$destinationPath = config('app.fileDestinationPath').'/'.$filename;
$uploaded = Storage::put($destinationPath, file_get_contents($file->getRealPath()));
if($uploaded){
$employee = Employee::find($id);
$empdoc = new EmpDocuments();
$empdoc->name = $filename;
$empdoc->employee_id = $employee->id;
$empdoc->save();
}
return redirect('employees');
}
These are my models.
Employee.php
public function EmpDocuments()
{
return $this->hasMany('App\EmpDocuments');
}
public function createdocument(){
return $this->EmpDocuments()->create([
'name' => $filename,
'employee_id' => $id,
]);
}
EmpDocuments.php
public function Employee()
{
return $this->belongsTo('App\Employee');
}
With the above models and controller I am now getting error
General error: 1364 Field 'employee_id' doesn't have a default value (SQL: insert into empdocuments.
How do I capture the employee_id?
Managed to fix it, in case someone has similar problem. Ensure you pass the id with the route action for it to be capture in the next request.
Here is the final controller.
public function update(Request $request, $id)
{
$file = $request->file('file');
$allowedFileTypes = config('app.allowedFileTypes');
$maxFileSize = config('app.maxFileSize');
$rules = [
'file' => 'required|mimes:'.$allowedFileTypes.'|max:'.$maxFileSize
];
$this->validate($request, $rules);
$time = time(); // Generates a random string of 20 characters
$filename = ($time.'_'.($file->getClientOriginalName())); // Prepend the filename with
$destinationPath = config('app.fileDestinationPath').'/'.$filename;
$uploaded = Storage::put($destinationPath, file_get_contents($file->getRealPath()));
if($uploaded){
$employee = Employee::find($id);
$empdoc = new EmpDocuments();
$empdoc->name = $filename;
$employee->empdocuments()->save($empdoc);
return redirect('employees/' . $id . '#documents')->with('message','Document has been uploaded');
}
}
Do you have a relationship between Employee and EmpDocuments ??
If I am understanding well EmpDocuments belongsTO Employees right??
I'm trying to help but I need to understand, one employee can have many documents right?? but each document belongs to just one employee right??
If is like that you should make a relationship in your employee model,
` public function employeeDocuments(){
return $this->hasMany(EmpDocuments::class);
}`
Then in the same model
`public function createEmployeeDocuments(){
return $this->employeeDocuments()->create([
'your_db_fields' =>your file,
'your_db_fields' => your other some data,
]);
}`
The id will be inserted automatically
I hope I helped you!!
https://laravel.com/docs/5.3/eloquent-relationships
Are your fillable empty???
To use the Eloquent create method you need to set you fillable array to mass assignment. Try this, if is still not working tell me and I will try to do my best.
protected $fillable = [ 'employee_id', 'Your_db_field', 'Your_db_field', 'per_page', 'Your_db_field', 'Your_db_field' ];

Yii2 conditional validation for image file upload

I am very new to Yii.
I have to apply image validation (.svg and .png allowed) only if user have selected the image.
public function rules() {
return [
[['logo'], 'file', 'extensions'=>'svg, png'],
];
}
When user select image it works fine.
But on update form we have only name of file. Now if we submit the form it will apply validation. I need validation only if user changes the image.
My Controller code
if ($model->load(Yii::$app->request->post())) {
$model->logo = UploadedFile::getInstance($model, 'logo');
if (!empty($model->logo)) {
$model->logo->name = $model->logo->baseName . Yii::$app->formatter->asTimestamp(date('Y-d-m h:i:s')) . '.' . $model->logo->extension;
$logoPath = Yii::getAlias('#common') . '/web/uploads/logo/' . $model->logo->name;
$model->logo->saveAs($logoPath, false);
}
if ($model->updateSite()) {
return $this->redirect(['site-list']);
}
}
Please let me know if you need more clarification.
Thanks.
Using scenarios may be helpful in this case.
Define validation rules to dependend on scenario
public function rules() {
return [
[['logo'], 'file', 'extensions'=>'svg, png', 'on' => 'imageUploaded'],
];
}
Then define scenario for model in controller. Something like this.
if ($model->load(Yii::$app->request->post())) {
$model->logo = UploadedFile::getInstance($model, 'logo');
if (!empty($model->logo)) {
$model->scenario = 'imageUploaded';
...
}
}
It's also possible to define anonymous function for conditional validation.
public function rules() {
return [
[['logo'], 'file', 'extensions'=>'svg, png', 'when' => function ($model) {
//return true to apply the rule
return $model->isImageUploaded();
}],
];
}
More on rules and scenarios can be found here https://github.com/yiisoft/yii2/blob/master/docs/guide/input-validation.md#declaring-rules-

Categories