Laravel CRUD testing - php

In my Laravel application I am trying to get into feature testing and have started with a model called Announcement.
One test I'm running is whether a user can create an instance of Announcement and persist it to the database.
My test is as follows:
/** #test */
public function a_user_can_create_an_announcement()
{
$this->withoutExceptionHandling();
$this->setupPermissions();
$announcement = factory(Announcement::class)->raw();
$this->actingAs(factory(User::class)->create())->get(route('announcements.index'))->assertStatus(200);
$this->post(route('announcements.store', $announcement))->assertStatus(302);
$this->assertDatabaseHas('announcements', $announcement);
}
Now as far as I understand factory(Announcement::class)->raw(); returns a new Announcement as an array using the relevant model factory.
I then make a request to my store endpoint with the data array and expect to redirected so I add the following:
$this->post(route('announcements.store', $announcement))->assertStatus(302);
The final line is to check the announcement was written to the database table called announcements
I get the following error from the test case:
1) Tests\Feature\AnnouncementsTest::a_user_can_create_an_announcement
Failed asserting that a row in the table [announcements] matches the attributes {
"message": "King. 'When did you.",
"message_details": "The Caterpillar.",
"author": "beatrice-herzog",
"status": "pending",
"published_at": null,
"created_at": {
"date": "2019-05-16 04:13:12.000000",
"timezone_type": 3,
"timezone": "Europe\/London"
},
"updated_at": "2019-08-20T13:37:22.293428Z"
}.
Found: [
{
"id": 5,
"message": "King. 'When did you.",
"message_details": "<p>The Caterpillar.<\/p>",
"author": "hollis-dach",
"status": "pending",
"published_at": null,
"created_at": "2019-08-20 14:37:23",
"updated_at": "2019-08-20 14:37:23"
}
].
Here is my AnnouncementFactory
<?php
/* #var $factory \Illuminate\Database\Eloquent\Factory */
use Faker\Generator as Faker;
use App\User;
use App\Announcement;
use Carbon\Carbon;
$factory->define(Announcement::class, function (Faker $faker) {
$user = factory(User::class)->create();
return [
'message' => $faker->realText(25),
'message_details' => $faker->realText(20),
'author' => $user->username,
'status' => 'pending',
'published_at' => null,
'created_at' => $faker->dateTimeThisYear('now', 'Europe/London'),
'updated_at' => Carbon::now()
];
});
Here is my AnnouncementModel
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Purifier;
use Carbon\Carbon;
use App\Like;
class Announcement extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'message', 'message_details', 'status', 'published_at'
];
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = [
'published_at',
'created_at',
'updated_at',
];
/**
* Get the user that posted this announcement
*/
public function user()
{
return $this->belongsTo(User::class, 'author', 'username');
}
/**
* Get the users that have liked this article
*
* #return void
*/
public function likes()
{
return $this->morphToMany(User::class, 'likeable');
}
/**
* Purify the content of message details when it is set so that it isn't vulnerable to XXS attacks
*
* #param string $value
* #return void
*/
public function setMessageDetailsAttribute($value)
{
$this->attributes['message_details'] = Purifier::clean($value);
}
/**
* Generate a nicer format for created_at
*
* #return void
*/
public function getCreatedAtAttribute($value)
{
return Carbon::parse($value)->format('d F Y');
}
/**
* Determine whether an announcement is pending
*
* #return void
*/
public function getPendingAttribute()
{
return $this->status == 'pending' ? true : false;
}
/**
* Check if the user has liked this announcement
*
* #return void
*/
public function getUserHasLikedAttribute()
{
$like = $this->likes()->whereUserId(auth()->user()->id)->first();
return (!is_null($like)) ? true : false;
}
/**
* Get the users that have liked this article
*
* #return void
*/
public function getLikesCountAttribute()
{
return $this->likes()->count();
}
/**
* Get count of users who liked the announcement excluding the logged in user
*
* #return void
*/
public function getLikesCountExcludingAuthUserAttribute()
{
return $this->likes()->where('username', '<>', auth()->user()->username)->count();
}
/**
* Get random user who liked this announcement
*
* #return void
*/
public function getRandomUserWhoLikedThisAttribute()
{
return $this->likes()->where('username', '<>', auth()->user()->username)->inRandomOrder()->first();
}
/**
* Get all users who liked this announcement
*
* #return void
*/
public function getUsersWhoLikedThisAttribute()
{
return $this->likes()->where('username', '<>', auth()->user()->username)->get();
}
/**
* Scope an article by whether or not it's published
*/
public function scopePublished($query)
{
return $query->where('status', 'published');
}
/**
* Scope an article by whether or not it's drafted
*/
public function scopePending($query)
{
return $query->where('status', 'pending');
}
/**
* Scope an article by whether or not it's archived
*/
public function scopeArchived($query)
{
return $query->where('status', 'archived');
}
}
Do the attributes literally have to be identical or am I just using tests incorrectly?
Do factories use model accessors and mutators?

I don't think you need to be testing the created_at and updated_at fields in this case. The reason why your test is failing is because the created_at value on the array is an instance of Carbon\Carbon rather than a string representing the datetime.
I would just update your factory to remove the created_at and updated_at values.
Try changing your factory to the following:
$factory->define(Announcement::class, function (Faker $faker) {
$user = factory(User::class)->create();
return [
'message' => $faker->realText(25),
'message_details' => $faker->realText(20),
'author' => $user->username,
'status' => 'pending',
'published_at' => null
];
});

Basically you are checking the database with the wrong information.
1 - announcements.store is an api which creates a new announcements for you.
2 - when you are calling assertDatabase, it's mean you have some information in your hand which you can check against the database. But if you take a look at the exception you can see you want to check this
"message": "King. 'When did you.",
"message_details": "The Caterpillar.",
"author": "beatrice-herzog",
"status": "pending",
"published_at": null,
"created_at": {
"date": "2019-05-16 04:13:12.000000",
"timezone_type": 3,
"timezone": "Europe\/London"
},
"updated_at": "2019-08-20T13:37:22.293428Z"
with this
"message": "King. 'When did you.",
"message_details": "<p>The Caterpillar.<\/p>",
"author": "hollis-dach",
"status": "pending",
"published_at": null,
"created_at": "2019-08-20 14:37:23",
"updated_at": "2019-08-20 14:37:23"
So either way you need to change the clause you are using. in this case you need to fix this three fields values(created_at, updated_at, message_details) or just remove them.

Yes, the key / value pairs you pass to assertDatabaseHas have to be identical to the record in your database. The function just searches for a row having the given column (key) with the specified value.
Be careful about converting your models to arrays. The resulting array may contain unexpected fields (relations) so better explicitly state the fields you want to check for.
I suggest you only include the properties of your announcement you want to test omitting the timestamps and other meta information.
Like this:
$this->assertDatabaseHas('announcements', Arr::only($announcement, [
'message', 'status'
]));
or like this:
$this->assertDatabaseHas('announcements', [
'message' => $announcement->message,
'status' => $announcement->status,
]);

Related

How can I achieve this design in Flutter app with response coming from Laravel Api?

I am trying to develop an app for schools and parents where the class teachers will be able to upload pictures of a student when a student check-in to school and check-out from school. This app will have a backend which will be built using laravel 9. The whole app is based on API.
Image of App User Interface here
I want to show photos of check-in and check-out side by side based on the date. If check-out is not updated yet, then the check-in image will be there and the check-out section will be empty.
Here is the JSON response that I am working with:
{
"data": [
{
"id": 1,
"child_id": 1,
"date": "18-08-2022",
"time": "08:49:51",
"status": "check_in",
"image": "https://via.placeholder.com/640x480.png/008833?text=kids+et"
},
{
"id": 6,
"child_id": 1,
"date": "18-08-2022",
"time": "10:24:38",
"status": "check_out",
"image": "https://via.placeholder.com/640x480.png/00ffdd?text=kids+veritatis"
}
]
}
Laravel Controller:
<?php
namespace App\Http\Controllers\Api\V1;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreCheckInOutRequest;
use App\Http\Requests\UpdateCheckInOutRequest;
use App\Http\Resources\V1\CheckInOut\CheckInOutResource;
use App\Models\CheckInOut;
use App\Services\V1\CheckInOutQuery;
use Illuminate\Http\Request;
class CheckInOutController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$filter = new CheckInOutQuery();
$queryItems = $filter->transform($request); //[['column', 'operator', 'value']]
if (count($queryItems) == 0) {
return response()->json(['message' => 'No child id provided'], 400);
} else {
return CheckInOutResource::collection(CheckInOut::where($queryItems)->orderBy('date', 'desc')->get());
}
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(StoreCheckInOutRequest $request)
{
$checkInOut = CheckInOut::create($request->all());
return response()->json(['message' => 'Check in & out status created successfully.', 'data' => $checkInOut], 201);
}
/**
* Display the specified resource.
*
* #param \App\Models\CheckInOut $checkInOut
* #return \Illuminate\Http\Response
*/
public function show(CheckInOut $checkInOut)
{
return new CheckInOutResource($checkInOut);
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param \App\Models\CheckInOut $checkInOut
* #return \Illuminate\Http\Response
*/
public function update(UpdateCheckInOutRequest $request, CheckInOut $checkInOut)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param \App\Models\CheckInOut $checkInOut
* #return \Illuminate\Http\Response
*/
public function destroy(CheckInOut $checkInOut)
{
//
}
}
Laravel API Resource:
<?php
namespace App\Http\Resources\V1\CheckInOut;
use Illuminate\Http\Resources\Json\JsonResource;
class CheckInOutResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
return [
'id' => $this->id,
'child_id' => $this->child_id,
'date' => date('d-m-Y', strtotime($this->date)),
'time' => $this->time,
'status' => $this->status,
'image' => $this->image
];
}
}
Database Migration:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('check_in_outs', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('child_id');
$table->date('date');
$table->time('time');
$table->string('status')->comment('check_in, check_out');
$table->string('image')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('check_in_outs');
}
};
CheckInOut Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class CheckInOut extends Model
{
use HasFactory;
protected $fillable = [
'child_id',
'date',
'time',
'status',
'image'
];
protected $hidden = [
'created_at',
'updated_at'
];
public function child()
{
return $this->belongsTo(Child::class);
}
}
Please help me, how can I design my API response and handle the API response to achieve my goal of design in flutter? Image of App User Interface here
The backend information is irrelevant, we only have to take into account the response in json
Create a model of your response. (You can use https://quicktype.io/ and paste your json output to get the Model class in Dart, the class you will get already has methods to map the objects from json.)
The design is not difficult, you should visit https://docs.flutter.dev/development/ui/widgets/material.
API requests can be done with https://pub.dev/packages/http and you can show images with https://docs.flutter.dev/cookbook/images/network-image
. Hope it helps your asking for a lot of information.

Array to string conversion in Orchid Software attachments in Laravel

I am trying to attach documents to a model when saving. I am getting array to string conversion erro. Because, it puts the documents Ids in to an array.
Here is my model.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Orchid\Screen\AsSource;
use App\Models\Seller;
use Orchid\Attachment\Models\Attachment;
use Orchid\Attachment\Attachable;
use Orchid\Filters\Filterable;
use Orchid\Metrics\Chartable;
use App\Orchid\Presenters\PropertyPresenter;
use Laravel\Scout\Searchable;
class Property extends Model
{
use HasFactory;
use AsSource, Attachable,Filterable;
use Chartable;
/**
* #var array
*/
protected $fillable = [
'property_name',
'property_type',
'property_city',
'property_address',
'property_area',
'seller_id',
'property_cost',
'property_price',
'property_rent_price',
'status',
'contracts',
'images'
];
/**
* Get the parent seller of the property.
*/
public function seller()
{
return $this->belongsTo(Seller::class);
}
/**
* Name of columns to which http sorting can be applied
*
* #var array
*/
protected $allowedSorts = [
'property_name',
'property_type',
'property_city',
'status',
'created_at',
'updated_at'
];
/**
* #param Builder $query
*
* #return Builder
*/
public function scopeActive(Builder $query)
{
return $query->where('status', 'Available');
}
/**
* #param Builder $query
*
* #return Builder
*/
public function scopeStatus(Builder $query)
{
return $query->where('status', '!=', 'Sold');
}
// Many-to-Many (no foreign id on table, should be uploaded with groups() function)
public function documents()
{
return $this->hasMany(Attachment::class)->where('group','contracts');
}
/**
* Get the presenter for the model.
*
* #return PropertyPresenter
*/
public function presenter()
{
return new PropertyPresenter($this);
}
/**
* Get the indexable data array for the model.
*
* #return array
*/
public function toSearchableArray()
{
$array = $this->toArray();
// Customize array...
return $array;
}
}
Here are the form elements
Upload::make('property.contracts')
->title('Documents')
->maxFileSize(2)
->targetId()
->targetRelativeUrl()
->groups('documents')
->acceptedFiles('image/*,application/pdf,.psd'),
And here is the save/update function
/**
* #param Property $property
* #param Request $request
*
* #return \Illuminate\Http\RedirectResponse
*/
public function createOrUpdate(Property $property, Request $request)
{
$property->fill($request->get('property'))->save();
$property->attachment()->syncWithoutDetaching(
$request->input('property.contracts', [])
);
Alert::info('You have successfully created an property.');
return redirect()->route('platform.property.list');
}
Finally here is the migration file
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('properties', function (Blueprint $table) {
$table->id();
$table->string('property_name');
$table->string('property_type');
$table->string('property_city');
$table->text('property_address');
$table->double('property_area',15,2);
$table->unsignedBigInteger('seller_id');
$table->double('property_cost', 20.3);
$table->double('property_price');
$table->double('property_rent_price')->nullable();
$table->string('contracts')->nullable();
$table->string('images')->nullable();
$table->string('status')->default('Available');
$table->timestamps();
$table->foreign('seller_id')->references('id')->on('sellers');
});
}
It gives the array to string conversion error and here is the request body:
{ "property_name": "Villa02", "property_type": "residential", "property_city": "Garoowe", "property_address": "Test", "property_area": "12000", "seller_id": "1", "property_cost": "43000", "property_price": "50000", "property_rent_price": "300", "status": "Available", "contracts": [ "67" ], "images": "/storage/2022/04/15/e3cbed3acbfec1d40c54aa57aa651a05c80d6586.png" }
Thanks in advance.
Just unset the array before filling the model
public function createOrUpdate(Property $property, Request $request)
{
$propertyInputs = $request->get('property');
$contacts = $propertyInputs['contracts']??[];
unset($propertyInputs['contracts']);
$property->fill($propertyInputs)->save();
$property->attachment()->syncWithoutDetaching($contacts);
Alert::info('You have successfully created an property.');
return redirect()->route('platform.property.list');
}

Passing parameters in an Unit Test, function update in database CRUD Laravel

I've been creating some tests to try my create delete edit functions on laravel from my database, this is my code:
ConstituencyController.php :
<?php
namespace App\Http\Controllers;
use App\Http\Requests\StoreConstituencyRequest;
use App\Http\Resources\ConstituencyResource;
use App\Models\Constituency;
use Illuminate\Http\Request;
use phpDocumentor\Reflection\Types\Collection;
class ConstituencyController extends Controller
{
/**
* Display a listing of the constituencies.
*
*
*/
public function index()
{
$constituency = Constituency::all();
return ConstituencyResource::collection($constituency);
}
/**
* Show the form for creating a new resource.
*
*
*/
public function create()
{
//
}
/**
* Store a newly created constituency in storage.
*
* #param Request $request
*
*/
public function store(Request $request)
{
$name = $request->name;
$data = array("name"=>$name);
Constituency::insert($data);
}
/**
* Display the specified constituency.
*
* #param int $id
*
*/
public function show(int $id)
{
$constituency = Constituency::find($id);
return new ConstituencyResource($constituency);
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
*
*/
public function edit(int $id)
{
//
}
/**
* Update the specified constituency in storage.
*
* #param Request $request
* #param int $id
*
*/
public function update(Request $request, int $id)
{
$constituency = Constituency::find($id);
$constituency->name = $request->name;
$constituency->update();
}
/**
* Remove the specified constituency from storage.
*
* #param int $id
*
*/
public function destroy(int $id)
{
Constituency::find($id)->delete();
}
}
Constituency.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Constituency extends Model
{
use HasFactory;
public function candidate()
{
return $this->hasMany(Candidate::class);
}
public function town()
{
return $this->hasMany(Town::class);
}
}
ConstituencyResource.php :
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class ConstituencyResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
ConstituencyFactory.php :
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* #extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Constituency>
*/
class ConstituencyFactory extends Factory
{
/**
* Define the model's default state.
*
* #return array<string, mixed>
*/
public function definition()
{
return [
'name' => $this->faker->word(),
];
}
}
Now this is my test to update a constituency:
public function test_a_constituency_can_be_modified()
{
$constituency = Constituency::factory()->create();
$constituency_id = $constituency->id;
$response = $this->put('api/constituencies/'.$constituency_id);
$this->assertDatabaseHas('constituencies', [
'id' => $constituency->id,
'name' => $constituency->name,
'created_at' => $constituency->created_at,
'updated_at' => $constituency->updated_at,
]);
}
Now of course the test passes, but i'm not actually giving it some new parameters to change... I've been trying to give some parameters to the function to actually change some data but i can't figure out how to do that.... I don't think i'm gonna have to put the parameters in the URI but where then?
If you are using PHPUnit you likely want to make use of Data Providers:
Example from docs
/**
* #dataProvider additionProvider
*/
public function testAdd(int $a, int $b, int $expected): void
{
$this->assertSame($expected, $a + $b);
}
public function additionProvider(): array
{
return [
'adding zeros' => [0, 0, 0],
'zero plus one' => [0, 1, 1],
'one plus zero' => [1, 0, 1],
'one plus one' => [1, 1, 3]
];
}
The smart folks over at Tighten also have an excellent tutorial on data providers.
If you're using PEST then you'll want Data Sets.
Example from docs
dataset('emails', [
'enunomaduro#gmail.com',
'other#example.com'
]);
it('has emails', function ($email) {
expect($email)->not->toBeEmpty();
})->with('emails'); // <-- use the dataset
Using data providers and data sets allows you to reuse data, but also test against multiple inputs for your unit test. You could if you wanted just hard code a value after you're arrange statement (where you create the DB record) but that has limitations and providers are far more flexible.
Update - Example test
The following is an example of how you might go about things. Note this is not exhaustive and things like using $request->all() to update your model are not advisable but I have done so to keep things simple for illustritive purposes. This should give you an idea of where/how you could go about performing your testing. There are many ways/opinions on such things.
api.php
Route::put('/constituencies/{constituency}',
[ConstituencyController::class, 'update']
)->name('api.constituencies.update');
ConstituencyController.php
<?php
namespace App\Http\Controllers;
use App\Models\Constituency;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class ConstituencyController extends Controller
{
public function update(Request $request, Constituency $constituency)
{
$constituency->update($request->all());
return response()->json($constituency, Response::HTTP_OK);
}
}
ExampleTest.php
<?php
namespace Tests\Feature;
use Tests\TestCase;
use App\Models\Constituency;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Foundation\Testing\RefreshDatabase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*
* #test
* #dataProvider constituencyNameProvider
* #return void
*/
public function it_can_update_constituency_name_successfully($constituencyName)
{
// Arrange
$constituency = Constituency::factory()->create();
$payload = ['name' => $constituencyName];
// Act
$response = $this->put(route('api.constituencies.update', $constituency->id), $payload);
// Assert
$response->assertStatus(Response::HTTP_OK)
->assertJson([
'id' => $constituency->id,
'name' => $constituencyName
])
->assertJsonStructure([
'id', 'name', 'created_at', 'updated_at'
]);
}
public function constituencyNameProvider(): array
{
return [
['Ostwald'],
['Springtown'],
['Baybarrow'],
['Blackhaven'],
['Lochspring'],
];
}
}

Pusher not seeing messages that I am broadcasting

I followed this tutorial to set up a messenger on my laravel application. My laravel logs show the type of messages below, which tells me that messages are being broadcast, but I'm not seeing them show up on Pusher! I've checked and double checked my pusher credentials and cluster and they are right.
[2020-06-06 14:49:30] local.INFO: Broadcasting [message.posted] on channels [private-
conversation.1] with payload:
{
"message": {
"id": 17,
"content": "h",
"sender_id": 1,
"conversation_id": "1",
"created_at": "2020-06-06T14:49:30.000000Z",
"updated_at": "2020-06-06T14:49:30.000000Z",
"conversation": {
"id": 1,
"new_messages": 0,
"created_at": "2020-06-06T15:41:25.000000Z",
"updated_at": "2020-06-06T14:49:30.000000Z"
}
},
"socket": null
}
I've created an endpoint to send messages and I'm triggering it with Postman. Below are my controller and the event that I'm triggering that should be broadcasting to pusher:
Store method in my controller:
public function store($id, Request $request)
{
$sender_id = auth()->user()->id;
$conversation = Conversation::find($id);
$content = $request->content;
// check that user belongs to the conversation
// updated conversation updated_at
// save message
if (in_array($sender_id, $conversation->users->pluck('id')->toArray())) {
// if the user is a participant in the conversation, they can save message
$message = Message::create([
'sender_id' => $sender_id,
'content' => $content,
'conversation_id' => $id
]);
// update the conversation updated_at
$conversation->touch();
} else {
// if user is not a participant in the conversation
return response([
'message' => 'Sorry, you are not part of this conversation and cannot post messages here'
]);
}
// fire new message posted event
event(new MessageWasPosted($message));
return response([
'message' => 'Message successfully posted',
'content' => $content
]);
}
My event:
class MessageWasPosted implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* The message
*
* #var mixed
*/
public $message;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Message $message)
{
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('conversation.'.$this->message->conversation->id);
}
/**
* The event's broadcast name
*
* #return string
*
*/
public function broadcastAs()
{
return 'message.posted';
}
}
To make sure auth is not an issue, I just return true in a Channel that I'm using:
<?php
namespace App\Broadcasting;
use App\User;
use App\Conversation;
class ConversationChannel
{
public function __construct()
{
}
/**
* Authenticate the user's access to the channel.
*
* #param \App\User $user
* #return array|bool
*/
public function join(User $user, Conversation $conversation)
{
return true;
return $conversation->users->contains($user);
}
}
On the Pusher debug console I see nothing coming through... Eventhough every now and then I see a random connection happening, no messages are being sent. Is there something obvious I'm missing?
PS: I've tried public channels, and they don't work either.

How do I return collection from another model?

Currently, I can only return data for Orders table eg.
{
"data": [
{
"id": 1,
"external_id": 1,
"refer_order_id": 1364116832365,
...
},
I need to also return data related to that table. In Artisan Tinker it is done like this...
$order = App\Order::first();
$order->carts;
This will supply the Carts related to the Order table.
Resource/Order.php
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class Order extends ResourceCollection
{
/**
* Transform the resource collection into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'data' => $this->collection,
];
}
}
api.php
Route::get('/orders/bulkindex/', function () {
return new OrderCollection(Order::all());
});
Resources\Cart.php
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class Cart extends ResourceCollection
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'data' => $this->collection,
];
}
}
I'd like to return the data like so... WITH the carts info related to that data.
return [
'data' => $this->collection,
'carts' => CartResource::collection($this->carts),
];
This will return this error:
Exception Property [carts] does not exist on this collection instance.
You can eager load the model relationship but you can't access it after it has been collected
It must be returned with the query to collect
Route::get('/orders/bulkindex/', function () {
return new OrderCollection(Order::with(['carts', 'another'])->get());
});
This will return the relationship appended to the data, not sure how you can serialize it independently tho
Hope this helps
Use eager load:
Order::with('carts')->get();
With multiple table
Order::with(['table1', 'table2'])->get();

Categories