Transform eloquent model using fractal - php

I am trying to use fractal to convert dates in my eloquent model when sending it to a web page via ajax. However, I'm not getting the expected transformed data object. Here's my code:
Transformer:
<?php
namespace App\Transformers\Models;
use App\Models\Student;
use League\Fractal;
class StudentTransformer extends Fractal\TransformerAbstract
{
public function transform(Student $student)
{
return [
'name' => $student->name,
'birth_date' => date('d-m-Y', strtotime($student->birth_date)),
'start_date' => date('d-m-Y', strtotime($student->start_date)),
'is_active' => $student->is_active ? 'Yes' : 'No',
'course_title' => $student->course_title,
'university_id' => $student->university_id,
'institution_id' => $student->institution_id,
'course_id' => $student->course_id,
];
}
}
Routes file:
Route::get('/', function () {
$student = App\Models\Student::first();
$response = new League\Fractal\Resource\Item($student, new App\Transformers\Models\StudentTransformer);
return response()->json([$response]);
});
returns this:
[
{ }
]
if I dd(), like so:
Route::get('/', function () {
$student = App\Models\Student::first();
$response = new League\Fractal\Resource\Item($student, new App\Transformers\Models\StudentTransformer);
dd($response);
});
I get the following, with no apparent transformations made
Item {#299 ▼
#data: Student {#305 ▼
#fillable: array:10 [▼
0 => "name"
1 => "birth_date"
2 => "start_date"
3 => "is_active"
4 => "course_title"
5 => "university_id"
6 => "institution_id"
7 => "course_id"
]
#connection: null
#table: null
#primaryKey: "id"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:13 [▼
"id" => 1
"name" => "Michel Jast"
"birth_date" => "1979-12-22"
"start_date" => "2015-08-02"
"is_active" => 1
"course_title" => "quia"
"university_id" => "10954"
"institution_id" => 1044
"course_id" => 1
"created_at" => "2015-11-23 09:40:35"
"updated_at" => "2015-11-26 10:24:14"
]
#original: array:13 [▼
"id" => 1
"name" => "Michel Jast"
"birth_date" => "1979-12-22"
"start_date" => "2015-08-02"
"is_active" => 1
"course_title" => "quia"
"university_id" => "10954"
"institution_id" => 1044
"course_id" => 1
"created_at" => "2015-11-23 09:40:35"
"updated_at" => "2015-11-26 10:24:14"
]
#relations: []
#hidden: []
#visible: []
#appends: []
#guarded: array:1 [▶]
#dates: []
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
}
#meta: []
#resourceKey: null
#transformer: StudentTransformer {#301 ▼
#availableIncludes: []
#defaultIncludes: []
#currentScope: null
}
}
Any ideas what I'm missing here?

My implementation is the following :
Route::get('/', function () {
$student = App\Models\Student::first();
$response = new League\Fractal\Resource\Item($student, new App\Transformers\Models\StudentTransformer);
$manager = new \League\Fractal\Manager();
$manager->setSerializer(new \League\Fractal\Serializer\ArraySerializer());
return response()->json($manager->createData($response)->toArray());
});
You have to create a \League\Fractal\Manager instance and assign a serializer into it. The manager will return the data into array or others.
In fractal page, there is more detail.

Ive not used Factral in a project but I think you need to do something like.
Route::get('/', function () {
$student = App\Models\Student::first();
$response = new League\Fractal\Resource\Item($student, new App\Transformers\Models\StudentTransformer);
return response()->json($response->toArray());
});

Related

Call to a member function toArray() on array -Laravel

// $result=[];
foreach ($chapter['chapter_content'] as $row) {
$result = CoursePublishChaptercontent::create([
'courseId' => $postdata[$i]['courseId'],
'course_chapter_id' => $postdata[$i]['course_chapter_id'],
'file_id' => $postdata[$i]['file_id'],
'course_chapter_content_id' => $postdata[$i]['course_chapter_content_id'],
]);
}
dd($result->toArray());
dd($result) shows the below data. I cannot call $result->toArray(); outside the foreach - it shows the error Undefined variable: result. When declaring $result before foreach as $result=[];, it shows the error Call to a member function toArray() on array. How can i fix it?Can someone tell me how to achieve this? I also tried declaring $result as '' & null before foreach. Both shows errors Call to a member function toArray() on string & Call to a member function toArray() on null respectively.
App\Models\CoursePublishChaptercontent {#441
#table: "course_publish_chapter_contents"
#fillable: array:9 [
0 => "course_chapter_id"
1 => "file_id"
2 => "courseId"
3 => "course_chapter_content_id"
]
#connection: "pgsql"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
+preventsLazyLoading: false
#perPage: 15
+exists: true
+wasRecentlyCreated: true
#attributes: array:12 [
"courseId" => 1
"course_chapter_id" => 18
"content_type_id" => 1
"file_id" => null
"course_chapter_content_id" => 17
"id" => 106
]
#original: array:12 [
"courseId" => 1
"course_chapter_id" => 18
"content_type_id" => 1
"course_chapter_content_id" => 17
"content_description" => null
"id" => 106
]
#changes: []
#casts: array:1 [
"deleted_at" => "datetime"
]
#classCastCache: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [
0 => "*"
]
#forceDeleting: false
#enableLoggingModelsEvents: true
#oldAttributes: []
}
You are on the right track. You can use the collect() helper to convert the result array into a collection and than you can use the toArray() method.
This is one way to do it:
$result = [];
foreach ($chapter['chapter_content'] as $row) {
$result[] = CoursePublishChaptercontent::create([
'courseId' => $postdata[$i]['courseId'],
'course_chapter_id' => $postdata[$i]['course_chapter_id'],
'file_id' => $postdata[$i]['file_id'],
'course_chapter_content_id' => $postdata[$i]['course_chapter_content_id'],
]);
}
dd(collect($result)->toArray());

Laravel 5.8: Parameter passed to the event listener is getting null

I have created an Event called UserWalletNewTransaction.php and added this to it:
public $transaction;
public function __construct($transaction) {
$this->$transaction = $transaction;
}
And also registered it at EventServiceProivder.php:
use App\Listeners\UserWalletNotification;
protected $listen = [
UserWalletNewTransaction::class => [
UserWalletNotification::class,
],
Now in order to fire this event at the Controller, I coded this:
$newTransaction = UserWalletTransaction::create(['user_id' => $user_id, 'wallet_id' => $wallet_id, 'creator_id' => $creator_id, 'amount' => $amount_add_value, 'description' => $trans_desc]);
event(new UserWalletNewTransaction($newTransaction));
Then at the Listener, UserWalletNotification.php, I tried:
public function handle(UserWalletNewTransaction $event) {
dd($event->transaction);
}
But it returns null somehow.
However if I dd($event) instead, I get this:
So what is going wrong here? I can properly insert new record at user_wallet_transactions and the variable $newTransaction should contain the transaction information but it's not.
Here is also the Model UserWalletTransaction.php:
protected $fillable = ['user_id','wallet_id','amount','description','creator_id'];
protected $table = 'user_wallet_transactions';
I would really appreciate any idea or suggestion from you guys about this...
Thanks in advance.
UPDATE #1:
If I do dd($newTransaction) at the Controller before event(), I get this:
UPDATE #2:
Here is the full code of event, UserWalletNewTransaction.php:
class UserWalletNewTransaction
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* #return void
*/
public $transaction;
public function __construct($transaction)
{
$this->$transaction = $transaction;
}
}
UPDATE #3:
Here is the full result of dd($event) at the Listener:
App\Events\UserWalletNewTransaction {#2533 ▼
+newTransaction: null
+socket: null
+"{"user_id":"373","wallet_id":"2","creator_id":2,"amount":"-60","description":null,"updated_at":"2021-07-18 13:33:59","created_at":"2021-07-18 13:33:59","id":61}": App\UserWalletTransaction {#2535 ▼
#fillable: array:5 [▼
0 => "user_id"
1 => "wallet_id"
2 => "amount"
3 => "description"
4 => "creator_id"
]
#table: "user_wallet_transactions"
#connection: "mysql"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: true
#attributes: array:8 [▼
"user_id" => "373"
"wallet_id" => "2"
"creator_id" => 2
"amount" => "-60"
"description" => null
"updated_at" => "2021-07-18 13:33:59"
"created_at" => "2021-07-18 13:33:59"
"id" => 61
]
#original: array:8 [▼
"user_id" => "373"
"wallet_id" => "2"
"creator_id" => 2
"amount" => "-60"
"description" => null
"updated_at" => "2021-07-18 13:33:59"
"created_at" => "2021-07-18 13:33:59"
"id" => 61
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▼
0 => "*"
]
}
}
I just figured out the problem... You are doing $this->$transaction when it should be $this->transaction.
I also had this problem, in case it is the case: remove the underscores in the properties of the event. ($_order has to be $order)

Laravel save when update not working (strange behavior)

I'm using Laravel 8 and I try to update data, but it won't save, and it really strange.
Controller
private function _generatePaymentToken($kode)
{
$this->initPaymentGateway();
$pnd = new Pendaftar;
$pnd = $pnd::where('nohp', $kode)->get();
if ($pnd->count()) {
$customerDetails = [
'first_name' => $pnd[0]->nama,
'last_name' => $pnd[0]->nama,
'email' => $pnd[0]->email,
'phone' => $pnd[0]->nohp,
];
$params = [
'transaction_details' => [
'order_id' => $pnd[0]->kode_transaksi,
'gross_amount' => 5000,
],
'customer_details' => $customerDetails,
'expiry' => [
'start_time' => date('Y-m-d H:i:s T'),
'unit' => setting('site.unit_expire'),
'duration' => setting('site.time_expired'),
],
];
$snap = \Midtrans\Snap::createTransaction($params);
$pendaftar = Pendaftar::find($pnd[0]->id);
$pendaftar->token = $snap->token;
$pendaftar->save;
// dd($pendaftar->save);
return $snap;
} else {
return view('404');
}
}
Model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Pendaftar extends Model
{
protected $table = 'pendaftar';
protected $primary_key = 'id';
protected $fillable = ['nama, email, nohp,orangtuawali, alamat, tempat_tanggal_lahir,asal_sekolah, satutahun_regular, satutahun_hybrid,duatahun, sarjana_plus, ihcp, ecp, periode_pendaftaran, created_at, updated_at, deleted_at, kode_refrensi, kode_transaksi,kampus,token'];
}
The $pendaftar->save before return is not working
I try to dd($pendaftar->save) it give me null
and if I dd($pendaftar) it gives me this
App\Pendaftar {#1840
#table: "pendaftar"
#primary_key: "id"
#fillable: array:1 [
0 => "nama, email, nohp,orangtuawali, alamat, tempat_tanggal_lahir,asal_sekolah, satutahun_regular, satutahun_hybrid,duatahun, sarjana_plus, ihcp, ecp, periode_pendaftaran, created_at, updated_at, deleted_at, kode_refrensi, kode_transaksi,kampus,token"
]
#connection: "mysql"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:22 [
"id" => "6"
"nama" => "Putu Elanda"
"email" => "biruxxx#mail.com"
"nohp" => "0878xxx"
"orangtuawali" => "Nyoman Elendiana"
"alamat" => "Singaraja"
"tempat_tanggal_lahir" => "Singaraja / 10 Januari 1996"
"asal_sekolah" => "SMK N 3 Singaraja"
"satutahun_regular" => null
"satutahun_hybrid" => null
"duatahun" => null
"sarjana_plus" => null
"ihcp" => "Profesi 2 Tahun "
"ecp" => "Food Entrepreneurship and Culinary Art"
"periode_pendaftaran" => "Januari"
"created_at" => "2020-12-20 14:15:03"
"updated_at" => "2020-12-20 14:15:03"
"deleted_at" => null
"kode_refrensi" => "BHT08"
"kode_transaksi" => "2012POSA"
"kampus" => null
"token" => "9067715d-aa54-4b10-a457-5445f06df3c4"
]
#original: array:22 [
"id" => "6"
"nama" => "Putu Elanda"
"email" => "biruxxx#mail.com"
"nohp" => "0878xxx"
"orangtuawali" => "Nyoman Elendiana"
"alamat" => "Singaraja"
"tempat_tanggal_lahir" => "Singaraja / 10 Januari 1996"
"asal_sekolah" => "SMK N 3 Singaraja"
"satutahun_regular" => null
"satutahun_hybrid" => null
"duatahun" => null
"sarjana_plus" => null
"ihcp" => "Profesi 2 Tahun "
"ecp" => "Food Entrepreneurship and Culinary Art"
"periode_pendaftaran" => "Januari"
"created_at" => "2020-12-20 14:15:03"
"updated_at" => "2020-12-20 14:15:03"
"deleted_at" => null
"kode_refrensi" => "BHT08"
"kode_transaksi" => "2012POSA"
"kampus" => null
"token" => ""
]
#changes: []
#casts: []
#classCastCache: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [
0 => "*"
]
}
I don't really know what wrong with this, or maybe is there's something I miss?
Your $fillable array is defined incorrectly - each column name should be an element of the array - wrapped in quotes. Otherwise none of the fields would be allowed for mass assignment.
Which means even if the update or save methods will not throw error - data won't be saved to database for these columns.
namespace App;
use Illuminate\Database\Eloquent\Model;
class Pendaftar extends Model
{
protected $table = 'pendaftar';
protected $primary_key = 'id';
protected $fillable = [
'nama',
'email',
'nohp',
'orangtuawali',
'alamat',
'tempat_tanggal_lahir',
'asal_sekolah',
'satutahun_regular',
'satutahun_hybrid',
'duatahun',
'sarjana_plus',
'ihcp',
'ecp',
'periode_pendaftaran',
'created_at',
'updated_at',
'deleted_at',
'kode_refrensi',
'kode_transaksi',
'kampus,token'
];
}
And as #bhucho has pointed out save() is a method not property, so statement should be
$pendaftar->save();

How to get Laravel set table to 'stick' for collection

We have a Laravel model and sometimes we want to get data from it's default table, but other times from a different table. It all works from a data perspective, but when the collection is returned from the alternate table, the 'table' attribute still references the original table (even though the data is from the other one as expected).
If we dd() getTable(), it is correct:
$model = COUNTRY;
$table = "countires";
$org_id = 1;
$org_collection = $model->setTable('merge_' . $table)->get()
->where('organization_id', $org_id)->keyBy('id');
dd($model->getTable()); // *** THIS SHOWS THE 2nd TABLE AS EXPECTED
dd() ouput:
"merge_countries"
But with the exact same code, if we dd() the result the table attribute in the collection is still the 1st one ('orgs') and not 'merge_orgs' as expected even though the data is correctly coming from the 'merge_orgs' table:
$model = COUNTRY;
$table = "countires";
$org_id = 1;
$org_collection = $model->setTable('merge_' . $table)->get()
->where('organization_id', $org_id)->keyBy('id');
dd($org_collection); // *** THIS SHOWS THE 1st TABLE EVEN THOUGH THE getTable() ABOVE DOES NOT
dd() output:
Collection {#297
#items: array:1 [
3 => Country {#295
#connection: "common"
#table: "countries" <---- WHY IS THIS NOT 'merge_countries'???
#hidden: array:2 [
0 => "created_at"
1 => "updated_at"
]
#appends: array:1 [
0 => "level"
]
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:7 [
"id" => 3
"organization_id" => 1
"region_id" => 2
"name" => "Southpark"
"active" => 1
"created_at" => "2018-06-21 14:05:36"
"updated_at" => "2018-06-21 13:25:27"
]
#original: array:7 [
"id" => 3
"organization_id" => 1
"region_id" => 2
"name" => "Southpark"
"active" => 1
"created_at" => "2018-06-21 14:05:36"
"updated_at" => "2018-06-21 13:25:27"
]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#visible: []
#fillable: []
#guarded: array:1 [
0 => "*"
]
}
]
}
Any idea how to address this? We're not sure what else to even try at this point. Laravel if 5.6 if that matters.
OK, there is a fix reference and more detail at github.com/laravel/framework/issues/26058. In the interim you can also override the model newInstance method in the trait to work around it:
public function newInstance($attributes = [], $exists = false)
{
// Overridden in order to allow for late table binding.
$model = parent::newInstance($attributes, $exists);
$model->setTable($this->table);
return $model;
}

Laravel. Keep eloquent relationship after join

suddenly i faced problem which I can't solve by myself. I wrote query which returns me some data:
$users = User::whereIn('users.status', array(2,3))
->leftJoin('firsts', 'firsts.user_id', '=', 'users.id')
->leftJoin('seconds', 'seconds.user_id', '=', 'users.id')
->leftJoin('thirds', 'thirds.user_id', '=', 'users.id')
->leftJoin('offers', 'offers.user_id', '=', 'users.id')
->where(function($query){
$query->where('users.status', '=', '2');
$query->where('firsts.status', '=', 'approved');
$query->where('seconds.status', '=', 'approved');
$query->where('offers.user_id', '=', 'approved');
})
->orWhere(function($query){
$query->where('users.status', '=', '3');
$query->where('users.stripe_active', '=', '1');
$query->where('firsts.status', '=', 'approved');
$query->where('seconds.status', '=', 'approved');
$query->where('thirds.status', '=', 'approved');
$query->where('offers.status', '=', 'approved');
})
->get();
I were expecting simple object as a return from query. At the moment I have one proper record in my users table, but this query returns me that object 6 times, and I can't understand why. Results I'm expect:
Collection {#353 ▼
#items: array:1 [▼
0 => User {#354 ▼
#dates: array:2 [▶]
#table: "users"
#fillable: array:3 [▶]
#hidden: array:2 [▶]
+admin: "eval.butkus#gmail.com"
+admin2: "Evaldas"
#connection: null
#primaryKey: "id"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:31 [▼
"id" => 1
"username" => "evaldas"
"password" => "$2y$10$ARTGHBTqIl/X6UsblylF5ugMPFlASwDKUEVbS5Nh3TjtycGG/NU7."
"email" => "eval.butkus#gmail.com"
"remember_token" => "A42ezMckkvjCLrpj4jxyHf2iSQWp3iAGfzGoTqMygDimFSzXNx6FW42qCOhP"
"name" => ""
"subscribe" => 0
"profile_picture" => "VNlQxOlCbXkCGEQ6ZdFS1pbK2tixhsmmhQPhLNLMBRKqDzXegWbqQiJOsplMADKg.jpg"
"about_you" => ""
"writing_service" => 0
"f_card" => 0
"logo" => ""
"website" => ""
"youtube" => ""
"status" => 3
"code" => ""
"active" => 1
"address" => ""
"phone" => ""
"news" => 0
"terms" => 1
"radius" => 0
"created_at" => "2015-07-13 10:26:47"
"updated_at" => "2015-07-15 10:25:30"
"stripe_active" => 1
"stripe_id" => "cus_6c0xE8OxR7fdXJ"
"stripe_subscription" => "sub_6c0x4RzEoBplCb"
"stripe_plan" => "small"
"last_four" => "4242"
"trial_ends_at" => null
"subscription_ends_at" => null
]
#original: array:31 [▶]
#relations: []
#visible: []
#appends: []
#guarded: array:1 [▶]
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
}
]
}
Results i get:
Collection {#364 ▼
#items: array:6 [▼
0 => User {#365 ▼
#dates: array:2 [▶]
#table: "users"
#fillable: array:3 [▶]
#hidden: array:2 [▶]
+admin: "eval.butkus#gmail.com"
+admin2: "Evaldas"
#connection: null
#primaryKey: "id"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:53 [▼
"id" => 2
"username" => "evaldas"
"password" => "$2y$10$ARTGHBTqIl/X6UsblylF5ugMPFlASwDKUEVbS5Nh3TjtycGG/NU7."
"email" => "sadsad"
"remember_token" => "A42ezMckkvjCLrpj4jxyHf2iSQWp3iAGfzGoTqMygDimFSzXNx6FW42qCOhP"
"name" => "sadsa"
"subscribe" => 0
"profile_picture" => "VNlQxOlCbXkCGEQ6ZdFS1pbK2tixhsmmhQPhLNLMBRKqDzXegWbqQiJOsplMADKg.jpg"
"about_you" => ""
"writing_service" => 0
"f_card" => 0
"logo" => ""
"website" => "das"
"youtube" => ""
"status" => "approved"
"code" => ""
"active" => 1
"address" => "asfas"
"phone" => "dasd"
"news" => 0
"terms" => 1
"radius" => 0
"created_at" => "2015-07-15 07:31:37"
"updated_at" => "2015-07-15 07:44:31"
"stripe_active" => 1
"stripe_id" => "cus_6c0xE8OxR7fdXJ"
"stripe_subscription" => "sub_6c0x4RzEoBplCb"
"stripe_plan" => "small"
"last_four" => "4242"
"trial_ends_at" => null
"subscription_ends_at" => null
"country" => "Highland"
"mobile" => "asd"
"descripsion" => "Ddescription"
"landline" => "asdas"
"company_name" => "das"
"facebook" => "dsad"
"twitter" => "sadsa"
"linkedln" => "dsadasd"
"company_number" => "sad"
"google" => "sadasd"
"vat" => "asdsad"
"experience" => ""
"privacy" => 0
"user_id" => 1
"post_code" => "AB115QN"
"latitude" => "57.14270109"
"longitude" => "-2.093014619"
"identify" => "grEa6JEaj6P0I7Zc3ZCq5CADojzApSJZ.jpg"
"bill" => "N8WKjRlSttsHNt1crrNdwxG7uqWEg5GB.jpg"
"comment" => "asdsad"
"image" => "7dmURWxbzO4pinqbek0yzdIKqEyZrjOD.jpg"
"title" => "new offer"
]
#original: array:53 [▶]
#relations: []
#visible: []
#appends: []
#guarded: array:1 [▶]
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
}
1 => User {#366 ▶}
2 => User {#367 ▶}
3 => User {#368 ▶}
4 => User {#369 ▶}
5 => User {#370 ▶}
]
}
Could any explain how did i lose all the relationships between tables and how can I avoid it? Since structure of result changed, I can't use loops, relationships and etc. Thanks!.
If im reading this right, you just want to
(delete join onto orders)...->groupBy('users.id')->get();
That will return you one user matching the conditions.
You can achieve this with 2 queries, first group by on users (don't join orders), then do a second query for the orders. What else to join would depend on which tables you are using to filter users by vs which tables you are using to add data to orders with.
Put data to add to orders in the second query, stuff your using to filter users in the first. You could also try a subquery but that isn't supported well in eloquent.
Also your whereIn is completely pointless, as you are already testing for where user status is 2 or 3.
Edited for a little more clarity,I was a little hasty. Originally thought that the poster wanted one row back - which wasn't the case.

Categories