Built api routes in laravel 5.x - json

I'm new in larevel. I want to create route in api.php. It's my code in this file
Route::middleware('auth:api')->get('/api', function (Request $request) {
return response()->json([
'name' => 'Abigail',
'state' => 'CA'
]);
});
I need to return json but when I put url mysite.com/api/api and page redirect me to mysite.com/user. How I can avoid redirect I get correct url?

Remove auth middleware and try again like:
Route::middleware('api')->get('/api', function (Request $request) {
return response()->json([
'name' => 'Abigail',
'state' => 'CA'
]);
});

You're getting redirected because you're using the auth middleware and are not authenticated. If the route does not need authentication just do:
Route::get('/api', function (Request $request) {
return response()->json([
'name' => 'Abigail',
'state' => 'CA'
]);
});

Here is a another example to parse direct model.
Laravel 5.2
Route::middleware('api')->get('/api/users', function (Request $request) {
return \App\Users::all();
});
You will get a json object for all users table data.

Related

Validate and store data in Laravel with axios

I am using React\NextJS as forntend and Laravel as backend,
Storing data with Axios post as per below,
const storeExpense = async (expenseData) => {
const response = await axios.post('/api/expenses/store/', {expenseData})
return response.data;
}
Now this will be sent as a JSON object to Laravel, I am not sure how can I validate and store this JSON object data to MySQL.
Earlier I was using Jquery AJAX where it was easy to store with Request validation and then with create.
Below is the request payload to the backend,
{"expenseData":{"expense_description":"React","expense_date":"2022-17-4","expense_amount":"123","expense_tax_amount":"14.15","expense_note":"given","expense_receipt_number":"Ok no","taxgroup_id":1,"paymentoption_id":1,"vendor_id":1,"accountcustomtype_id":2,"submit":null}}
Below was Controller and Model, used when sending data as Form
//Controller
public function store(StoreExpenseRequest $request)
{
Expense::storeExpense($request);
return response()->json([
'val' => 1,
'msg' => 'Success',
]);
}
//Model
public static function storeExpense($request)
{
Expense::create([
'vendor_id' => $request->vendor_id,
'accountcustomtype_id' => $request->accountcustomtype_id,
'expense_description' => $request->expense_description,
'expense_date' => Carbon::parse($request->expense_date)->format('Y-m-d'),
'expense_amount' => $request->expense_amount,
'taxgroup_id' => $request->taxgroup_id,
'expense_tax_amount' => $request->expense_tax_amount,
'paymentoption_id' => $request->paymentoption_id,
'expense_receipt_number' => $request->expense_receipt_number,
'expense_note' => $request->expense_note,
]);
}
But now this doesn't work with JSON data,
How can I achieve this with Axios JSON data?
Thank you,
It was resolved by changing Axios request Data,
await axios.post('/api/expenses/store/', expenseData)

Validate all JSON requests in Laravel

I am making a registration function with a RegisterRequest request class which should validate the request:
public function register(RegisterRequest $request)
{
//
}
The request validation (RegisterRequest) looks like this:
<?php
namespace App\Http\Requests\Api\User;
use App\Http\Requests\Request;
class RegisterRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true; // TODO: should secure this.
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required',
'email' => 'required|email|unique:users,email',
];
}
}
But I get the error that name and email are missing, I think this is because the request is send in JSON. How can I make this request validate the JSON input I am giving? Thanks in advance.
The way I am making the request:
handleSubmit (data) {
// Register User
this.$http
.post('/api/user/register', data)
.then(response => {
console.log(response)
// Clear form
// Show snackbar
})
.catch(error => {
console.error(error)
})
.finally(
// Update items in DataTable
console.log(data)
)
}
When I console.log(data); it shows me this:
{"name":"asdsfsdf","email":"sdfsfd#sdfs.com"}
when I try to validate like this:
$validator = Validator::make($request->json()->all(), [
'name' => 'required',
'email' => 'required|email|unique:users,email',
]);
It works, but I want to separate this logic from the controller.
Based on your comment, you're not sending the data correctly to the server --- you're sending it as an array key. In your AJAX/request call, send data as following (I'm using axios library as demo, but the schema can be applied in jquery or other js tools as well):
axios.post('/link/to/web/route', {
name: 'my name',
email: 'my email',
}).then(response=>{
alert('Data sent with success!')
}).catch(error=>{
alert('Error has occurred. Please check browser console');
console.log(error)
})
I managed to fix it by using the prepareForValidation method (https://laravel.com/docs/7.x/validation#prepare-input-for-validation):
protected function prepareForValidation()
{
$this->merge([
'name' => $this->json('name'),
'email' => $this->json('email')
]);
}
The rules function now successfully validates the JSON input.

Laravel sending email call_user_func() error

I am trying to send email in laravel for which I am using the mail::send function.
This is my code:
$data = [
'title'=>'Some Title',
'content'=>'Content',
'email'=> 'email',
'password'=>'password',
'remarks'=>'remarks'
];
Mail::send('admin.mails.activate', $data, ['user'=>$user], function ($message) use ($user) {
$message->to($user->email, $user->name)->subject('Account Activation Email')->from('support#webmail.com');
});
I am trying to pass the $data variable to the view file and $user variable to the callback function so that I could use user's email to send an email. But it is giving me this error:
call_user_func() expects parameter 1 to be a valid callback, array must have exactly two members
Mail::send() accepts 3 arguments (view, data, callback) but you've given it 4:
Mail::send('admin.mails.activate', $data, ['user'=>$user], function ($message) use ($user) {
$message->to($user->email, $user->name)->subject('Account Activation Email')->from('support#webmail.com');
});
I assume you meant to merge the ['user' => $user] array in with $data:
Mail::send('admin.mails.activate', array_merge($data, ['user' => $user]), function ($message) use ($user) {
$message->to($user->email, $user->name)->subject('Account Activation Email')->from('support#webmail.com');
});
or alternatively:
$data = [
'title'=>'Some Title',
'content'=>'Content',
'email'=> 'email',
'password'=>'password',
'remarks'=>'remarks',
'user' => $user
];
Mail::send('admin.mails.activate', $data, function ($message) use ($user) {
$message->to($user->email, $user->name)->subject('Account Activation Email')->from('support#webmail.com');
});
this is the problem
$message->to($user->email, $user->name)
change it to
$message->to($user->email)

Yii2 : ajax post request always redirect to login page

I'm trying to send data using ajax POST request but I'm always redirected to login page even if I authorize the method to anonymous users (['actions' => ['update', 'test'], 'allow' => true]). When I test with a GET request there is no problem.
My controller :
public function behaviors() {
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
['actions' => ['update', 'test'], 'allow' => true],
],
],
];
}
public function actionTest() {
Yii::$app->request->enableCsrfValidation = false;
echo 'ok';
}
I use Postman to test requests
The solution you used is not a solution actually, its like if you cant open the lock with a key just remove the lock.
Mostly you get the 400 Bad Request if you are making an Ajax Post request without sending the CSRF parameters, I never faced the problem like being redirected to the login page.
But if your problem is resolved by disabling the CSRF Validation then you should follow this method while making any ajax requests.
In your config, you define the csrf parameter name using csrfParamin the request component like this
'request' => [
'csrfParam' => '_csrf-app',
],
This can be different for you if it is already defined.
You have to send this param _csrf-app with the csrf value in the ajax request along with your post data. and for retrieving the value for the csrf you can use javascript yii.getCsrfToken() method, or Yii::$app->request->csrfToken if in view via php.
See this example call you can hardcode the name of the param _csrf-app or use Yii::$app->request->csrfParam if your script is inside the view file.
$.ajax({
url:'/add',
data:{'_csrf-app':yii.getCsrfToken()}
success:function(data){}
});
Hope this solves your problem.
lubosdz's suggestion solved the problem
Modified controller :
public function behaviors() {
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
['actions' => ['update', 'test'], 'allow' => true],
],
],
];
}
public function beforeAction($action) {
if ($action->id == 'test') {
$this->enableCsrfValidation = false;
}
return parent::beforeAction($action);
}
public function actionTest() {
echo 'ok';
}
I found a solution that looks a bit like yours Muhammad Omer Aslam : by serializing the form in JavaScript I can send directly all the fields and the csrf token generated by the ActiveForm.
$.ajax({
url: ...,
type: 'POST',
data: $('#myForm').serialize(),
success: (response) => { ... }
})

How do I replace the default auth.basic response with a JSON response?

I have a route group that looks like this:
Route::group(['prefix' => 'recipe','middleware'=>['auth.basic']], function (){
//Some things to do
});
When credentials are invalid Laravel outputs "Invalid credentials." How do I override this response with my own JSON response?
In AuthController, try this :
public function postLogin(Request $request)
{
$this->validate($request, [
'email' => 'required', 'password' => 'required',
]);
$credentials = [
'email' => $request->input('email'),
'password' => $request->input('password')
];
if (Auth::attempt($credentials, $request->has('remember')))
{
return redirect()->intended($this->redirectPath())
->with('success', 'You are successfully logged in');
}
return Response::json(array(
'success' => false,
'errors' => $this->getFailedLoginMessage(),
));
}
I just had a look at the Illuminate\Auth\SessionGuard. The method getBasicResponse() seems to be responsible for the response on a failed login attempt (with basic auth).
protected function getBasicResponse()
{
$headers = ['WWW-Authenticate' => 'Basic'];
return new Response('Invalid credentials.', 401, $headers);
}
How to actually overwrite it seems a little tricky though. You probably need to extend the SessionGuard Class and implement your own getBasicResponse() method. Thats the easy part, how to actually instantiate your own guard instead of the default one, I don't know yet.