Controller method not found laravel - laravel

Hello i have been using implicit controllers for a hile now but today i am having an issue i just cannot understand, i have the following in my Route.php:
/**
* Purchase
*/
Route::controllers([
'purchase' => 'PurchaseController'
]);
and in my controller i have created this method:
public function postNsano(NsanoRequest $request)
{
$data = [
'code' => $request->code,
'msg' => $request->msg,
'reference' => $request->referencecode
];
if ($request->code == "00")
{
Session::put('nsano_callback_post_data', $data);
return [
'code' => '00',
'msg' => 'success'
];
}
else
{
return [
'code' => '01',
'msg' => 'rollback'
];
}
}
Now for some reason when i try and post to this URL:
sample.com/purchase/nsano
I get this error: "Controller Method Not Found"
Which is odd for me because i can see the method right there.
I took out the $request and just used Input::get() instead and now it works can someone please explain this to me?
This is my request:
class NsanoRequest extends Request {
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'code' => 'required',
'msg' => 'required',
'reference' => 'required'
];
}
}

Implicit controller routing needs the HTTP verb in the method name:
public function postNsano(NsanoRequest $request)
{
//
}

Your request validates do not correct so it jumps to an url to prompt error but not found.
If you add some parameters like this and than OK.

Related

How to fix '0 passed and exactly 1 expected' error in laravel

I'm Created Form Request,it doesn't work. But if I put validation in the controller it is work.
i think it happend after (php artisan make:auth).
Because before that it was working properly.
//StorBlogPost :
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
$rules = [
'name' => 'bail|required',
'camera' => 'bail|required|numeric',
'weight' => 'bail|required|numeric',
'price' => 'bail|required|numeric',
'barcode' => 'bail|required',
'production_at' => 'bail|required'
];
return $rules;
}
//controller :
public function store(StoreBlogPost $request)
{
$request->validate();
product::create($request->except('_token'));
}
error :
"Too few arguments to function App\Http\Requests\StoreBlogPost::Illuminate\Foundation\Providers{closure}(), 0 passed and exactly 1 expected"
You don't need to call $request->validate() in your controller. Laravel calls this automatically.

Laravel custom error message from inside custom validator function using $validator->errors->add()

I have custom validation rule appointment_status. I am performing various test cases on it and decide what error message is best and throwback. it will be different for every case. I want the $validator->errors()->add('status', __('Invalid status for an appointment in past') to set the error message and it's adding. but it's not returning back to the controller. I can't access this message anywhere. it shows only the status.appointment_status one which is set in messages() function.
Custom Request class:
namespace Modules\ShopManager\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class AppointmentsRequest extends FormRequest
{
public function __construct()
{
\Validator::extend('appointment_status', 'Modules\ShopManager\Validators\CustomValidator#appointmentStatus');
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
$rules = [
'services' => 'required',
'sdate' => 'required|date_format:m-d-Y|time_range:sTime,edate,eTime,timezone',
'edate' => 'required|date_format:m-d-Y|workinghours_range:sdate,sTime,edate,eTime,timezone',
'sTime' => 'required|date_format:h:i a',
'eTime' => 'required|date_format:h:i a',
'cname' => 'required',
'cphone' => 'required_without:cemail',
'cemail' => 'nullable|required_without:cphone|email',
'timezone' => 'required',
'status' => 'required|appointment_status:sdate,sTime,edate,eTime,timezone',
];
return $rules;
}
public function messages()
{
return [
'status.appointment_status' => 'Invalid status'
];
}
public function attributes()
{
return [
'services' => 'Services',
'date' => 'Date',
'sTime' => 'Start Time',
'eTime' => 'End Time',
'cname' => 'Customer name',
'cphone' => 'Customer phone',
'cemail' => 'Customer email',
'internal_note' => 'Internal note',
'status' => 'Status',
];
}
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
}
The custom validator function:
public function appointmentStatus($attribute, $value, $parameters, $validator)
{
$dateTimeOperations = new DateTimeOperations;
$sdate = array_get($validator->getData(), $parameters[0]);
$startTime = array_get($validator->getData(), $parameters[1]);
$edate = array_get($validator->getData(), $parameters[2]);
$endTime = array_get($validator->getData(), $parameters[3]);
$timezone = array_get($validator->getData(), $parameters[4]);
$now = $dateTimeOperations->getNow($timezone);
$start = $dateTimeOperations->getTimestamp($sdate, $startTime, $timezone);
$end = $dateTimeOperations->getTimestamp($edate, $endTime, $timezone);
switch ($value) {
case constants('appointments.status.pendig'):
$start->lessThan($now)
? $validator->errors()->add('status', __('Invalid status for an appointment in past'))
: '';
}
return $validator->errors()->any();
}
Adding an error just to the field without specifying the rule I don't think will work, that's why the message from the validation request takes precedence.
So change it to this:
$validator->errors()->add('status.appointment_status', __('Invalid status for an appointment in past'))
And also in your case do you maybe have a typo: pendig to be pending?
You have to create custom validator rules and add below code inside your rule wherever required, See example below:
$validator->after(function ($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});

How to test a fake file upload to a route that validate the file in Laravel?

I'm trying to write a test unit for the route 'store' in my controller, pass a fake file to be tested too through the validator of my method, but all i got is that the data is not a file :
Illuminate\Foundation\Testing\TestResponse {
+baseResponse: Illuminate\Http\JsonResponse {
#data: "{
"message":"The given data was invalid.",
"errors":{"invoice":["The invoice must be a file."]}
}"
Code :
Test :
$data = factory('App\Domain\X\X')->raw(['creator_id' => $user->id]);
$data['invoice'] = UploadedFile::fake()->create('invoice.xlsx');
$response = $this->json('POST', route('x.store', $data));
Controller :
public function store(XXXRequest $request)
{
...
Request :
class XXXRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required',
'invoice' => 'nullable|file',
];
}
try this:
Test:
$data = factory('App\Domain\X\X')->raw(['creator_id' => $user->id]);
$data['invoice'] = UploadedFile::fake()->create('invoice.xlsx');
$response = $this->json('POST', route('x.store', $data), [
'name' => 'abc',
'invoice' => $data['invoice']
]);
Just create an UploadedFile from a local file and add it to your request:
use Illuminate\Http\UploadedFile;
$filename = public_path('tests/invoice.pdf');
$file = new UploadedFile($filename, 'invoice.pdf', 'application/pdf', filesize($filename), null, true);
$this->post('/', [
'invoice' => $file,
]);
You can read about testing file uploads here or visit official documentation
/**
* Example
*
* #test
*/
public function test_correct_file_uploading(): void
{
// Set fake storage ('local', 's3', etc)
Storage::fake('local');
$response = $this->json('POST', '/path_to_your/controller/method', [
'file' => UploadedFile::fake()->create('invoice.xlsx', 1024)
]);
// Assert response successful
$response->assertSuccessful();
// Assert the file was stored
Storage::disk('local')->assertExists('invoice.xlsx');
}

Customize Validation Messages in Laravel Requests

How do i customize my Validation Messages in My REQUESTS FILE?
how do i add messages next to the rules?
What i want is to put customized messages just like the common validation. Is it possible? to do just the normal way of validation in the Requests?
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class ArticleRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'title' => 'required|min:5',
'content' =>'required',
'user_id' => 'required|numeric',
'category_id' => 'required|numeric',
'published_at' => 'required|date'
];
}
}
You can define a messages() method with validation rules for that form request only:
class StoreArticleRequest extends Request
{
//
public function messages()
{
return [
'title.required' => 'The title is required.',
'category_id.numeric' => 'Invalid category value.',
];
}
}
It takes the form of the field name and the rule name, with a dot in between, i.e. field.rule.
You may customize the error messages used by the form request by
overriding the messages method. This method should return an array of
attribute / rule pairs and their corresponding error messages:
public function messages()
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
https://laravel.com/docs/5.3/validation#customizing-the-error-messages
I use this solution to translate the field labels:
...
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'title' => 'required|min:5',
'content' =>'required',
'user_id' => 'required|numeric',
'category_id' => 'required|numeric',
'published_at' => 'required|date'
];
}
/**
* Get the validation attributes that apply to the request.
*
* #return array
*/
public function attributes()
{
return [
'title' => __('app.title'),
'content' => __('app.content'),
'user_id' => __('app.user'),
'category_id' => __('app.category'),
'published_at' => __('app.published_at')
];
}

Laravel JsonResource: array_merge_recursive(): Argument #2 is not an array

I have a JsonResource of Post that should return a single post. But after joining some other data I get this error: array_merge_recursive(): Argument #2 is not an array.
This does not work:
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($slug)
{
// $post = Post::findOrFail($id);
$post = Post::where('slug', $slug)->first();
// return single post as resource
return new PostResource($post);
}
When I directly return $posts, I get a json back, almost fine. But it doesnt contain the joined data comment.
Here is the class Post extends JsonResource.
public function toArray($request)
{
// return parent::toArray($request);
$img = '.'.pathinfo('storage/'.$this->image, PATHINFO_EXTENSION);
$imgName = str_replace($img,'', $this->image);
$img = $imgName.'-cropped'.$img;
return [
'id' => $this->id,
'title' => $this->title,
'body' => $this->body,
'excerpt' => $this->excerpt,
'image' => asset('/storage/' . $this->image),
'image_small' => asset('storage/' . $img),
'author_id' => $this->author_id,
'category_id' => $this->category_id,
'seo_title' => $this->seo_title,
'slug' => $this->slug,
'meta_description' => $this->meta_description,
'meta_keywords' => $this->meta_keywords,
'status' => $this->status,
'featured' => $this->featured,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'user' => User::find($this->author_id),
'commentCount' => $this->comment->where(['status' => 1, 'id_post' => $this->id])->count(),
];
}
// **Big mistake below here**:
public function with($request)
{
// return [
// 'version' => '1.0.0',
// ];
}
Model:
class Post extends Model
{
public $primary_key = 'id';
public $foreign_key = 'id_post';
public function user()
{
return $this->belongsTo('App\User', 'id_author', 'id');
}
public function comment()
{
return $this->belongsTo('App\Comment', 'id', 'id_post');
}
}
Why do I get a warning about array_merge_recursive()?
I wan't reproduce issue with your code, but - are you sure you included everything? Looking at https://laravel.com/docs/5.6/eloquent-resources#writing-resources it's possible to define additional data data will be returned too like this:
/**
* Get additional data that should be returned with the resource array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function with($request)
{
return [
'meta' => [
'key' => 'value',
],
];
}
So I was able to reproduce the issue when I added to this Post resource class the following method:
public function with($request)
{
return 'test';
}
as you see it's returning just string and not array and then I was getting same error as you did.
But when I didn't have this method implemented at all or when I return just an array, everything is fine.
So to sum up - make sure you don't have with method defined that returns something else than array.

Resources