Closed alariva closed 6 years ago
Hi. I'm currently in vacation, so I will double check later but yeah in my memory it's totally recursive, so it handles as many level as you need, just by the same way that for first level. The most simple way is to give it a try and let me know if it fits for you or if you need something else! Mathieu.
Hey @alariva I'm just seeing your email. I'll answer it directly here: Hi Mathieu,
Ariel here, greetings from Argentina.
Amazing! Open source as a link between peoples, without any boundaries. Just the way it should be! 🎉 So greetings back from France! 🇫🇷
I stumbled upon your package laravel-json-syncer, which looks great. I'm kind of surprised of the difficuly I had to find it, being first published since more than an year ago, and being there so much activity around Eloquent models. Voilà , thanks for building this tool.
Thank YOU for you feedback. Indeed I'm not really good in marketing and communication, especially in english. If you are, feel free to talk about all my packages! 😅 Or if you want, to write about your needs and how it handled them, and I'll try to push it somewhere (Laravel News maybe?).
I'm willing to replace my current core export/import code with your package, as I need to move pieces from one DB to another (same structure, but different app instances). Honestly, I haven't tried yet as I just met it, but you will probably have news from me.
Yeah it's totally made for that! I've used it several times to export some objects and dependencies (nested relations) between environments, or to be able to duplicate/construct entities easily directly in json in admin panels.
I just wanted to ask if it will handle nested relationships in deep level (I've seen in the readme that it perfectly handles direct 1st level relationship), what about deeper levels?
As I wrote in my previous message, of course, and it's exactly the same. You can have as many level as you want, but only one to one/many relationship (no many to many), because it has to be serialized in a tree.
Thanks again and best regards
My real pleasure, feel free to ask anything!
Hi @mathieutu , sorry for the late reply. Thanks for the hints.
So I'm getting started. I've created a console command to perform a few tests exporting a model I call Patient
.
For testing purpose this is how I'm willing to export:
$patient = Patient::first($jsonOptions = 0);
echo $patient->exportToJson();
Since my Patient model is the app main domain object, it might be a bit bloated, and I think there is at least one attribute or relationship is causing conflict as I get:
$ php artisan export-json:patient
In Grammar.php line 127:
Argument 1 passed to Illuminate\Database\Grammar::columnize() must be of the type array, integer given, called in /home/alariva/fimedi/vendor/laravel/framework/src/Illuminate/Database/Que
ry/Grammars/Grammar.php on line 133
<?php
namespace App;
use App\Traits\HasServices;
use App\Traits\HasSettings;
use App\Traits\MasksAttributes;
use Carbon\Carbon;
use Iatstuti\Database\Support\NullableFields;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use MathieuTu\JsonSyncer\Contracts\JsonExportable;
use MathieuTu\JsonSyncer\Traits\JsonExporter;
use Sofa\Eloquence\Eloquence;
class Patient extends Model implements JsonExportable
{
use NullableFields, Eloquence, MasksAttributes, HasSettings, HasServices, SoftDeletes, JsonExporter;
protected $searchableColumns = ['firstname' => 1, 'lastname' => 1, 'email' => 2, 'nin' => 3, 'mobile' => 4];
protected $nullable = ['location', 'nin', 'height', 'physical_structure', 'job', 'notes', 'email', 'mobile',
'mobile_carrier', 'consultation_reason', 'first_visit', 'old_id', 'subscription', 'user_id', 'diet',
'physical_activity_level', 'wrist_circumference',
];
protected $fillable = ['firstname', 'lastname', 'birthdate', 'gender', 'location', 'nin', 'height',
'physical_structure', 'wrist_circumference', 'job', 'notes', 'email', 'mobile',
'mobile_carrier', 'consultation_reason', 'created_at', 'updated_at', 'first_visit',
'medical_record', 'old_id', 'subscription', 'user_id', 'diet', 'physical_activity_level',
'account_id',
];
protected $appends = ['age'];
protected $casts = ['account_id' => 'integer',
'wrist_circumference' => 'integer',
'height' => 'integer',
'age' => 'integer',
'old_id' => 'integer',
'user_id' => 'integer',
];
/**
* The attributes that should be mutated to dates.
*
* @var array
*/
protected $dates = [
'created_at',
'updated_at',
'deleted_at',
'birthdate',
'first_visit',
];
public static function boot()
{
parent::boot();
self::deleting(function (Patient $patient) {
foreach ($patient->controls as $control) {
$control->delete();
}
});
}
public function account()
{
return $this->belongsTo(Account::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function getIsRegisteredUserAttribute()
{
return $this->attributes['user_id'] !== null;
}
/**
* Accessor for Age.
*/
public function getAgeAttribute()
{
return Carbon::parse($this->attributes['birthdate'])->age;
}
/**
* Accessor for Birthdate.
*/
public function getBirthdateAttribute()
{
return Carbon::parse($this->attributes['birthdate'])->toDateString();
}
/**
* Determine if is person's birthday.
*/
public function isBirthday()
{
return Carbon::parse($this->attributes['birthdate'])->isBirthday();
}
/**
* Accessor for Birthdate.
*/
public function getFirstVisitAttribute()
{
return Carbon::parse($this->attributes['first_visit'])->toDateString();
}
/**
* Accessor for Medical Record.
*/
public function getMedicalRecordAttribute()
{
return json_decode($this->attributes['medical_record']);
}
public function controls()
{
return $this->hasMany(Control::class);
}
public function lastVisit()
{
if ($this->controls()->count()) {
return Carbon::parse($this->controls()->orderBy('visit_date', 'desc')->first()->visit_date)->toDateString();
}
}
public function getlastControlDateAttribute()
{
$lastControl = $this->controls->first();
return $lastControl ? Carbon::parse($lastControl->visit_date) : null;
}
public function firstControl()
{
return $this->controls()->orderBy('visit_date', 'asc')->first();
}
public function lastControl()
{
return $this->controls()->orderBy('visit_date', 'desc')->first();
}
public function penultimateControl()
{
return $this->controls()->orderBy('visit_date', 'desc')->skip(1)->take(1)->first();
}
public function lastControlInspections()
{
$lastControl = $this->lastControl();
if ($lastControl) {
return $lastControl->inspections;
}
return new \Illuminate\Database\Eloquent\Collection();
}
// ...
}
SIDENOTES: I could successfully export a simple model (0 levels deep, just the plain model). So my question arises with on the following: is it the same a HasOneOrMany()
relationship to HasMany()
?
Hi,
HasMany
and HasOne
classes extend HasOneOrMany
.
If you can export it without relationships I think your problem comes from one of them, so another model (Control?). Do you have the complete trace?
Oh! Look at that: $patient = Patient::first($jsonOptions = 0);
One should go to bed after 4am
. ;)
So, I'm able to export correctly at 0 deep level. Anything I'm missing to retrieve relationships?
alariva@trinsic:~/fimedi$ php artisan export-json:patient
{"firstname":"Ariel","lastname":"Vallese","birthdate":"1984-01-01","gender":"M","location":null,"nin":null,"height":1860,"physical_structure":"P","wrist_circumference":165,"job":null,"notes":null,"email":"email@email.com","mobile":null,"mobile_carrier":null,"consultation_reason":null,"created_at":{"date":"2018-05-11 00:37:02.000000","timezone_type":3,"timezone":"UTC"},"updated_at":{"date":"2018-08-27 12:11:32.000000","timezone_type":3,"timezone":"UTC"},"first_visit":"2018-05-11","medical_record":null,"subscription":null,"diet":"I","physical_activity_level":"ACTIVITY_LIGHTLY_ACTIVE"}alariva@trinsic:~/fimedi$
Sidenote: I've made exportable relationships explicit, but still getting the same result. Also made sure that this model has child models (like about 5)
public function getJsonExportableRelations() : array
{
return ['controls'];
}
UPDATE: I could Export an Account model (with Patients, who have Controls), and it looks like I got 1 level deep (accounts and patients but no controls) export fine. Getting better! :) I'll check this out.
So, I got it, and makes sense to me now:
TLDR; Every parent and child model you wish to export should implement interface and use trait. Works just perfect.
Thanks for your help! I'm going to open a new issue for a new Exception that has araised with a possibly conflicting package.
Hi @mathieutu
This tool looks great. Thanks!
I'm considering replacing some core functions in my project for this package. I've seen in the readme that it perfectly handles direct 1st level relationship. I just wanted to ask if it will handle nested relationships in deeper levels. If so, would you provide an example?
Thanks very much in advance