Laravel: Add custom data to resource - laravel

First I get the translator by his id using this line of code
$translator = Translator::where('id', $translator_id)->first();
Then I send a notification to him by this code:
$response = Http::withHeaders([
'Authorization' => 'key=myKey',
'Content-Type' => 'application/json'
])->post('https://fcm.googleapis.com/fcm/send', [
"notification" => [
"title" => "title",
"body" => "body",
],
"data" => [
"title" => "title",
"body" => "body",
],
"to" => $token,
]);
Everything works fine but my problem is that when I return the TranslatorResource I want to add the notification response to it, so I do this in my controller
$resource = new TranslatorResource($translator);
$resource->notif = $response;
return $resource;
And in TranslatorResource I have this code:
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'phone' => $this->phone,
'cv' => $this->cv,
'specialization' => $this->specialization,
'tr_languages' => $this->tr_languages,
'all_languages' => $this->all_languages,
'isVerified' => $this->isVerified == 0 ? false : true,
'isActive' => $this->isActive == 0 ? false : true,
'completed_orders' => $this->completed_orders,
'canceled_orders' => $this->canceled_orders,
'rejected_orders' => $this->rejected_orders,
'current_orders' => $this->current_orders,
'isTranslator' => true,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
But I only get the data specified in the resource, the notif key isn't added, anyone know how to add this data to my resource when I return it ?

You can use additional method provided by laravel.
return (new TranslatorResource($translator))->additional(['notif ' => $response]);
Reference: Eloquent: API Resources
You can look for the section Adding Meta Data When Constructing Resources.

Related

Why does an inertia route change?

In a Laravel/Inertia application, I try to store vinylRecords.
Therefore I created a vinylRecords resource.
Route::resource('vinylRecords', VinylRecordController::class)->only(['index', 'create','store', 'edit', 'update']);
In the frontend, the store function looks like:
methods: {
submitForm() {
this.$inertia.post(route("vinylRecords.store"), this.form, {
onSuccess: (response) => {
alert(Object.keys(response.props))
this.form.reset();
},
});
}
},
Sometimes, the routing is right and the Laravel stores the new record. But most of time, Laravel redirects to the index method without storing the data.
The store method:
public function store(StoreVinylRecordRequest $request)
{
$data = $request->validated();
$record = VinylRecord::create($data);
$record->labels()->sync($data['label_ids']);
$record->styles()->sync($data['style_ids']);
$record->specials()->sync($data['special_ids']);
return Inertia::render('vinylRecord/index', [
'records' => VinylRecordResource::collection(VinylRecord::all()),
'vinylRecordId' => $record->id
]);
}
To solve the problem, I created a new controller with a new route to store the data:
Route::post('storeVinylRecord', [StoreVinylRecordController::class, 'store'])->name('storeVinylRecord');
But the problem was the same.
How is it possible, that the routing changes from one request to the other? Is there an big error in the code from my side?
Edited: Add the StoreVinylRecordRequest
public function rules()
{
return [
'artist' => 'required|string',
'title' => 'required|string',
'barcode' => 'nullable|integer',
'genre_id' => 'nullable|integer',
'country' => 'nullable',
'year' => 'nullable|integer',
'label_ids' => 'nullable',
'style_ids' => 'nullable',
'special_ids' => 'nullable',
'thumb' => 'nullable|string',
'cover_image' => 'nullable|string',
'quantity' => 'nullable|integer',
'speed' => 'nullable|integer',
'part_type' => 'nullable|string',
'storage_location' => 'nullable|string',
'supplier_id' => 'nullable|in:suppliers,id',
'purchasing_price' => 'nullable|numeric',
'selling_price' => 'nullable|numeric',
];
}

undefined index data laravel

i'm integrating this login api on laravel:
endpoint: http://127.0.0.1:8888/api/v1/users/login/
parameter:
{"data":{
"email":"admin#mail.com",
"password":"admin#123",
"user_type":"1",
"encrypted":false
},"encoded_data":"yes"}
controller:
i'm posting data from form:
$request->validate([
'username' => 'required',
'password' => 'required',
'user_type' => 'required'
]);
$ds = $request->all();
$url = $this->base_api_url . 'api/v1/users/login/';
$apiRequest = [
'data' => [
'email' => $ds['username'],
'password' => $ds['password'],
'user_type' => $ds['admin'],
'encrypted' => false
],
'encoded_data' => 'yes',
];
$apiResponse = Http::acceptJson()->post($url, $apiRequest);
dd($apiResponse);
its return:
{"error":1,"success":false,"message":"Undefined index: data"}
this is the parameter i'm sending in $apiRequest:
array:2 [▼
"data" => array:4 [▼
"email" => "admin#mail.com"
"password" => "admin#123"
"user_type" => "1"
"encrypted" => false
]
"encoded_data" => "yes"
]
api working fine on postman:
I think you are requesting json format data so you need to get with by using this$request->json()->all() by using this you can access the key value.
Laravel Http::post sends a normal post request (form data). You should also send the Content-type: application/json header so the Laravel API understands it.
Try using the following:
$apiResponse = Http::accept('application/json')->post($url, $apiRequest);
// or
$apiResponse = Http::acceptJson()->post($url, $apiRequest);

Timestamps are making my phpunit tests fail

When I use the following PostResource, and Post Test, my tests succeed:
PostResource.php
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'content' => $this->content,
'slug' => $this->slug,
];
}
PostController.php
public function show(Post $post)
{
return new PostResource($post);
}
ReadPostTest.php
/** #test */
public function a_user_can_read_a_single_post()
{
$post = factory(Post::class)->create([
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
]);
//dd($post);
$response = $this->json('GET', '/posts/' . $post->id)
->assertStatus(200)
->assertJsonFragment([ 'data' => [
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
]]);
}
When I add created_at and updated_at to my tests and resource I get a failure. The test bellow show when I didn't add .000000Z.
phpunit
There was 1 failure:
1) Tests\Feature\ReadPostsTest::a_user_can_read_a_single_post
Unable to find JSON:
[{
"data": {
"title": "A new post",
"content": "Some content",
"slug": "a-new-post",
"created_at": "2018-12-06 21:13:26",
"updated_at": "2018-12-06 21:13:26"
}
}]
within response JSON:
[{
"data": {
"id": 1,
"title": "A new post",
"content": "Some content",
"slug": "a-new-post",
"created_at": "2018-12-06T21:13:26.000000Z",
"updated_at": "2018-12-06T21:13:26.000000Z"
}
}].
Failed asserting that an array has the subset Array &0 (
'data' => Array &1 (
'title' => 'A new post'
'content' => 'Some content'
'slug' => 'a-new-post'
'created_at' => '2018-12-06 21:13:26'
'updated_at' => '2018-12-06 21:13:26'
)
).
--- Expected
+++ Actual
## ##
'title' => 'A new post',
'content' => 'Some content',
'slug' => 'a-new-post',
- 'created_at' => '2018-12-06 21:13:26',
- 'updated_at' => '2018-12-06 21:13:26',
+ 'created_at' => '2018-12-06T21:13:26.000000Z',
+ 'updated_at' => '2018-12-06T21:13:26.000000Z',
),
)
I tried adding 000000Z that and got the same problems.
There was 1 failure:
1) Tests\Feature\ReadPostsTest::a_user_can_read_a_single_post
Unable to find JSON fragment:
[{"data":{"content":"Some content","created_at":"2019-12-20 21:42:33.000000Z","id":1,"slug":"a-new-post","title":"A new post","updated_at":"2019-12-20 21:42:33.000000Z"}}]
within
[{"data":{"content":"Some content","created_at":"2019-12-20T21:42:33.000000Z","id":1,"slug":"a-new-post","title":"A new post","updated_at":"2019-12-20T21:42:33.000000Z"}}].
Failed asserting that false is true.
It seems like my created_at and up_dated at timestamps are messed up for a reason that I have no idea why? 2019-12-20T21:42:33.000000ZThat's probably what's getting my tests to fail. How do I fix this?
Use carbon on your post model factory and then use $post->created_at and $post->updated_at in the json assertion:
public function a_user_can_read_a_single_post()
{
$post = factory(Post::class)->create([
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
"updated_at" => Carbon::now()->timestamp,
"created_at" => Carbon::now()->timestamp
]);
//dd($post);
$response = $this->json('GET', '/posts/' . $post->id)
->assertStatus(200)
->assertJsonFragment([ 'data' => [
'id' => 1,
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
"updated_at" => $post->updated_at,
"created_at" => $post->created_at
]]);
}
For some reason a string of timestamps doesn't work. Hopefully someone else can comment as to why.
You probably want to use Carbon's setTestNow() to fix what 'now' means during the test.
Written with the assumption you are using Laravel.
// Immutable, so you don't go insane.
$now = \Carbon\CarbonImmutable::now()->micro(0);
// Fix Carbon's 'now' to that time
\Illuminate\Support\Carbon::setTestNow($now)
// \Carbon\CarbonImmutable::setTestNow($now);
// Your tests here
// u = microseconds, but it's not set to '000000' in 'now', if you forget `->micro(0)`.
// The 'Y-m-d\TH:i:s.u\Z' format works with Laravel 6.20.19 in march 2021, but YMMV.
// ->assertJSon(['created_at' => $now->utc()->format('Y-m-d\TH:i:s.000000\Z'),])
// Release Carbon's 'now' time to follow your clock again.
\Illuminate\Support\Carbon::setTestNow(null)
// \Carbon\CarbonImmutable::setTestNow(null);
It looks like you're struggling with the timestamps format. I had the same issue and solved it through the JSON serialization, found in the Carbon documentation. In your case, it must look like this:
public function a_user_can_read_a_single_post()
{
$post = factory(Post::class)->create([
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
"updated_at" => Carbon::now()->timestamp,
"created_at" => Carbon::now()->timestamp
]);
$response = $this->json('GET', '/posts/' . $post->id)
->assertStatus(200)
->assertJsonFragment([ 'data' => [
'id' => 1,
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
"updated_at" => $post->updated_at->jsonSerialize(),
"created_at" => $post->created_at->jsonSerialize()
]]);
}
It may be a little late, but hopefully helps to others.
Good luck buddy.
It works for me when I do this (Note: I put the date with ones to simplify the process):
use Carbon\Carbon;
class ExampleTest extends TestCase
{
protected function setUp(): void
{
Carbon::setTestNow(Carbon::create(1111, 1, 11, 11));
}
/** #test */
public function your_awesome_test()
{
$this->postJson(route('route.name'),[
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
])->assertJsonFragment([
'data' => [
'id' => 1,
'title' => 'A new post',
'content' => "Some content",
'slug' => "a-new-post",
"updated_at" => Carbon::setTestNow(),
"created_at" => Carbon::setTestNow()
]
];
}
}

CakePHP IntegrationTestTrait Post Returns HTTP Status 302

I am trying to perform a simple test from posting data onto a table in CakePHP. I am using IntegrationTestTrait.
I am not able to POST data successfully. My $this->_response is yielding:
object(Cake\Http\Response) {
'status' => (int) 302,
'contentType' => 'text/html',
'headers' => [
'Content-Type' => [
(int) 0 => 'text/html; charset=UTF-8'
],
'Location' => [
(int) 0 => '/'
]
],
'file' => null,
'fileRange' => [],
'cookies' => object(Cake\Http\Cookie\CookieCollection) {
[protected] cookies => []
},
'cacheDirectives' => [],
'body' => ''
}
My TestCase code looks like this:
public function testAddStudentSuccess() {
$data = [
'last_name' => 'Test',
'first_name' => '05',
'middle_name' => '',
'preferred_name' => '',
'id_number' => '10005',
'contact_id' => '',
'users[0][email]' => 'test_05#email.com'
];
//Test Pre-condition
$query = $this->Students->find('all')->where([
'id_number' => $data['id_number']
]);
$this->post('/students/add', $data);
debug($this->_response);
}
I debugged further and found that the Test is not even invoking the Controller add() functions.
I thought the issue was an Authentication Issue is I tried following all the authentication work arounds prescribed in the documentation. However, it did not work.
Does anyone know how I can debug this further? Any help is appreciated. Thank you.

Call to undefined method Chatkit\Chatkit::sendMultipartMessage()

I have chatkit version 1.1 installed. I used sendMessage() method to send text message. Now i want to use sendMultipartMessage() method but got "Call to undefined method Chatkit\Chatkit::sendMultipartMessage()". sendSimpleMessage is not working as well.
Chatkit Version
"pusher/pusher-chatkit-server": "^1.1",
"pusher/pusher-php-server": "^3.4",
public function SendMessage(Request $request){
//return $request->all();
$user = $this->LoggedInUser();
$chatkit = $this->Authenticate();
$room_id = Session::get($user->username);
$chatkit->sendMultipartMessage([
'sender_id' => $user->username,
'room_id' => $room_id,
//'text' => $request->message,
'parts' => [
[ 'type' => 'image/png',
'url' => 'https://placekitten.com/200/300' ],
[ 'type' => 'text/plain',
'content' => 'simple text' ],
[ 'type' => 'binary/octet-stream',
'file' => file_get_contents('https://placekitten.com/200/300'),
'name' => 'kitten',
'customData' => [ "some" => "json" ],
'origin' => 'http://example.com'
]
]
]);
Pusher Authentication:
public function Authenticate(){
return new Chatkit([
'instance_locator' => config('services.chatkit.locator'),
'key' => config('services.chatkit.key'),
]);
}
You will need to upgrade your Chatkit library. The method you are using was introduced in v1.2. See the changelog for details.

Resources