Laravel Exceptions: throwing error when not attaching nullable input file - php

I have a form when the user submits lostFound model. The validation request is as follows:
public function rules()
{
return [
'LFImage' => 'required|image|mimes:jpeg,jpg,png,gif,webp', // TODO: Read about 'Sometimes'.
'handoverStatement' => 'nullable|image|mimes:jpeg,jpg,png,gif,webp',
];
}
So, one attached is required (LFImage) and the other isn't (handoverStatement).
I created a dynamic image upload action:
class UploadImageAction implements UploadImageContract {
public function handle(Request $request, $image, $imageLocation)
{
$storedImage = ($request->hasFile($image))
? $request->file($image)->store($imageLocation)
: NULL;
if(!$storedImage)
{
throw new ImageUploadException('Something went wrong with the image upload.' . $storedImage);
}
return $storedImage;
}
}
Then calling it in the controller store() with try, catch:
// Add new Record.
public function store(LostFoundRequest $request, LostFoundService $lostFoundService, UploadImageContract $uploadImageAction)
{
try {
$LFImage = $uploadImageAction->handle($request, 'LFImage', 'lostFound/lostItems');
$handoverStatement = $uploadImageAction->handle($request, 'handoverStatement', 'lostFound/handoverStatements');
$lostFoundService->storeLostFound($request, $LFImage, $handoverStatement);
return redirect('data-entry/lost-and-found')->with('success', 'Item Added Successfully');
} catch (ImageUploadException $exception) {
// Handle upload image error
return back()->withErrors($exception->getMessage());
} catch (LostFoundException $exception) {
// Handle lostfound created error
return back()->withErrors('lostFound', $exception->getMessage());
} catch (\Throwable $exception) {
throw $exception;
}
}
Every time I submit the form without attaching handoverStatement I get the exception error (The data isn't saved, yet LFImage is uploaded to the dir).
What am I missing here?
Note: the ImageUploadException class doesn't have any methods:
<?php
namespace App\Exceptions;
use Exception;
class ImageUploadException extends Exception {}

Related

BadMethodCallException Call to undefined method App\restaurent_name::session()

i am new to laravel
this is my code for controller
I am writing a code to save the data from the user in Mysql
And then redirect me to the list page with updated table and a flash message that the data has been updated successfully
i also tried using session->('key') but it didn't work
<?php
namespace App\Http\Controllers;
use App\restaurent_name;
use Illuminate\Http\Request;
class RestaController extends Controller
{
function Index()
{
return view('home');
}
function list()
{
$data = restaurent_name::all();
return view('list',["Data"=>$data]);
}
function add(Request $req)
{
//return $req->input();
$save = new restaurent_name;
$save->name=$req->input("name");
$save->address=$req->input("address");
$save->contact=$req->input("contact");
$save->save();
$save->session()->has('status');
//$save->session()->put('status', 'Task was successful!');
//$save->session()->flash('status','Restaurent added succesfully');
return redirect('/list');
}
}
the data gets saved properly into the database but the issue is that i am not able to receive message from flash session
This the error message i receive when i try to use flash session
`
Illuminate\Database\Eloquent\Model::throwBadMethodCallException C:\xampp\htdocs\Laravel
Projects\Restaurants\vendor\laravel\framework\src\Illuminate\Support\Traits\ForwardsCalls.php:50
$pattern = '~^Call to undefined method (?P<class>[^:]+)::(?P<method>[^\(]+)\(\)$~';
if (! preg_match($pattern, $e->getMessage(), $matches)) {
throw $e;
}
if ($matches['class'] != get_class($object) ||
$matches['method'] != $method) {
throw $e;
}
static::throwBadMethodCallException($method);
}
}
/**
* Throw a bad method call exception for the given method.
*
* #param string $method
* #return void
*
* #throws \BadMethodCallException
*/
protected static function throwBadMethodCallException($method)
{
throw new BadMethodCallException(sprintf(
'Call to undefined method %s::%s()', static::class, $method
));
}
}
`
You can do that with :
return redirect('/list')
->with('status', 'Restaurent added succesfully')
->with('status2', 'Task was successful!');
With Session Flash :
Session::flash('status', 'Restaurent added succesfully');
Session::flash('status2', 'Task was successful!');
return redirect('/list');

How to keep DRY while creating common controllers in Laravel?

As I was working on my Laravel app, I noticed that I was creating controllers' methods which were very similar. For example, I have models: Task, Block, Lesson, etc. And in every controller there are very similar methods:
public function index()
{
return new GeneralResource(/model/::all());
}
public function show(/model/ $model)
{
return new GeneralResource($model);
}
public function store(/model/Request $request)
{
try {
$model = /model/::create($request->validated());
return response()->json(['status' => 'success']);
} catch (\Exception $e) {
echo $e->getMessage();
}
}
public function update(/model/Request $request, /model/ $model)
{
try {
$model->update($request->validated());
return response()->json(['status' => 'success']);
} catch (\Exception $e) {
echo $e->getMessage();
}
}
public function destroy(/model/ $model)
{
try {
$model->delete();
return response()->json(['status' => 'success']);
} catch (\Exception $e) {
echo $e->getMessage();
}
}
Maybe I could extend Controller class with these methods and pass parameters as protected properties, but I am not sure how this can be done.
Please, help.
What you are looking for is called Template Method. You can do it for each method from the controllers :)
More info:
https://refactoring.guru/design-patterns/template-method/php/example
https://designpatternsphp.readthedocs.io/en/latest/Behavioral/TemplateMethod/README.html

Prevent create a record if error in observer Laravel

How I can block create a record on a model if function gives me an error?
I have Observer:
public function created(Post $post)
{
Auth::guest() ? $post->sendEmailNotification($post->guest_token) : '';
}
I need: if sendEmailNotification get an exception, then not create the record. Now, if I get an exception, post whatever creating.
You have to use creating instead of created, creating is fired before the creation so just catch the exception and return false :
public function creating(Post $post)
{
try {
if (Auth::guest()) {
$post->sendEmailNotification($post->guest_token);
}
} catch (\Exception $e) {
return false;
}
}

How to return custom API response for "No query results for model", Laravel

I am building an RESTful API in Laravel 5.2.
In my resource controllers I want to use implicit model binding to show resources. e.g.
public function show(User $users)
{
return $this->respond($this->userTransformer->transform($users));
}
When a request is made for a resource that doesn't exist Laravel automatically returns the NotFoundHttpException
NotFoundHttpException
I want to return my own custom response but how can I do that for a query that is done using route model binding?
Would something like this Dingo API response answer be able to be implemented?
Or will I stick with my old code which was something like this:
public function show($id)
{
$user = User::find($id);
if ( ! $user ) {
return $this->respondNotFound('User does not exist');
}
return $this->respond($this->userTransformer->transform($users));
}
So I could see if a resource (user) was not found and return an appropriate response.
See if you can catch ModelNotFound instead.
public function render($request, Exception $e)
{
if ($e instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
dd('model not found');
}
return parent::render($request, $e);
}
I think a good place would be in the Handler.php file under /app/Exceptions
public function render($request, Exception $e)
{
if ($e instanceof NotFoundHttpException) {
// return your custom response
}
return parent::render($request, $e);
}
In Laravel 7 and 8 you can do something like this.
In app/Exception/Handler.php class, add the render() method like below(if it doesn't exist).
Note that instead of type hinting Exception class you should use Throwable .
use Throwable;
public function render($request, Throwable $e)
{
if ($e instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
//For API (json)
if (request()->wantsJson()) {
return response()->json([
'message' => 'Record Not Found !!!'
], 404);
}
//Normal
return view('PATH TO YOUR ERROR PAGE');
}
return parent::render($request, $e);
}

Laravel 4 Passing exception variables

I'm confused by the error that is being received while attempting to throw an exception, Undefined variable: validation
This is the first time I've tried to create a custom exception and I must be doing something wrong. Here I'm just trying to validate a row being inserted into the database (which works), the problem I'm having is with the exception.
Controller
public function store()
{
try
{
$this->deals->insertDeal(Input::all());
}
catch(ValidationError $e)
{
return Redirect::route('deals.create')
->withInput()
//this is the unknown variable
->withErrors($validation->errors);
}
return Redirect::route('deals.create')
->with('message', 'Deal Created');
}
Model
public function insertDeal($input)
{
$validation = new Services\Validators\Deal;
if ($validation->passes()) {
$deals = Deals::create($input);
}
$errors = $validation->errors;
throw new ValidationError($validation->errors);
}
Custom Validation Error
class ValidationError extends Exception {}
App::error(function(ValidationError $e){
});
To recap, i'm just not sure why i'm getting the error of undefined variable when I try to trigger the exception. Thanks for the help.
Basically, $validation is not available within the scope of the store() method. You can pass the errors through the exception by rewriting your ValidationError class:
class ValidationError extends Exception
{
protected $errors;
public function __construct($errors)
{
$this->errors = $errors;
}
public function getErrors()
{
return $this->errors;
}
}
and accessing the errors in store():
public function store()
{
try {
$this->deals->insertDeal(Input::all());
} catch(ValidationError $e) {
return Redirect::route('deals.create')
->withInput()
->withErrors($e->getErrors());
}
return Redirect::route('deals.create')
->with('message', 'Deal Created');
}

Categories