Compare two Doctrine_Record objects - doctrine

How do I compare two Doctrine_Record objects to see if they are "equal"?
On the domain login I am considering, two objects are equal if they have the same properties values, except the id and the created_at and updated_at fields (a la Timestampable).

First idea which comes into my mind is:
class User extends Doctrine_Record
{
public function equals(User $user)
{
$left = $this->toArray();
$right = $user->toArray();
unset($left['id'], $left['created_at'], $left['updated_at']);
unset($right['id'], $right['created_at'], $right['updated_at']);
return $left == $right;
}
}

Related

How can I check if a primary key value exists in another table or not?

I have id(Primary key) of country in multiple tables and I want to check if its value exists or not in another referenced table.
Tried using the below code but I don't think this is the right way. Can anyone please suggest something...
public function check($id)
{
$state = State::pluck('country_id');
$country = DB::select("select count(*) from country where ? not in (?)",[$id,$state]);
if($country == 0)
{
//
}
else{
//
}
}
You can check if a relationship for a record is present (or exists), using exists.
Assuming you have a relationship on your Country model called states:
public function states
{
return $this->hasMany(State::class);
}
You can check if a Country has any States related to it in your database.
// returns true if there are related states, otherwise false
Country::first()->states()->exists();
You can use whatever filtering criteria you want, so rather than first() you could use find($id) or where('field', $value) etc.
Use Exists Method here
public function check($id)
{
$state = State::pluck('country_id');
$country = DB::table('country') //table set
->whereIn('column_name',$state) //if array then used whereIn method
->where('column_name',$id) //if single value use where method
->exists();
if($country)
{
//
}
else{
//
}
}

Does the Inverse ralation object is the same with the original?

I have been using Laravel for months, and the inverse ralation bothers me.
Considering the following example.
There are two Eloquent models, and the relation is defined as below
class Customer extends \Illuminate\Database\Eloquent\Model
{
public function orders()
{
return $this->hasMany(Order:class);
}
}
class Order extends \Illuminate\Database\Eloquent\Model
{
public function customer()
{
return $this->belongsTo(Customer:class);
}
}
$customer1 = Customer::select()
//->where('id', '=', 1)
->with('orders')
->first();
$customer2 = $customer1->orders[0]->customer;
if ($customer1 === $customer2) {
echo 'Same'. PHP_EOL;
} else {
echo 'Not the same'. PHP_EOL;
}
$customer1 and $customer2 should be the same. But they are not.
What I want is that $customer1 and $customer2 be the same, just like Yii2 does
With the word same, I mean they should be the same instance instead of two instances with the same customer data.
Did I miss something? Any help would be grateful.
Laravel has no active record implementation. There is no master who keeps track of what objects have been fetched from the database. Each object tracks its own changes, but has no knowledge of other objects that exist in memory.
From your relation, you can see every customer can have multiple order and order must have a customer. So in your $customer1 variable, you have an eloquent model object and in $customer2 you have an id. How could you compare them?? Try to compare between ID. Laravel doesn't work that way you are expecting.
$customer1 = Customer::select()
//->where('id', '=', 1)
->with('orders')
->first();
$customer2 = $customer->orders[0]->customer;
if ($customer1->id === $customer2) {
echo 'Same'. PHP_EOL;
} else {
echo 'Not the same'. PHP_EOL;
}

Laravel oneToMany accessor usage in eloquent and datatables

On my User model I have the following:
public function isOnline()
{
return $this->hasMany('App\Accounting', 'userid')->select('rtype')->latest('ts');
}
The accounting table has activity records and I'd like this to return the latest value for field 'rtype' for a userid when used.
In my controller I am doing the following:
$builder = App\User::query()
->select(...fields I want...)
->with('isOnline')
->ofType($realm);
return $datatables->eloquent($builder)
->addColumn('info', function ($user) {
return $user->isOnline;
}
})
However I don't get the value of 'rtype' for the users in the table and no errors.
It looks like you're not defining your relationship correctly. Your isOnline method creates a HasMany relation but runs the select method and then the latest method on it, which will end up returning a Builder object.
The correct approach is to only return the HasMany object from your method and it will be treated as a relation.
public function accounts()
{
return $this->hasMany('App\Accounting', 'userid');
}
Then if you want an isOnline helper method in your App\User class you can add one like this:
public function isOnline()
{
// This gives you a collection of \App\Accounting objects
$usersAccounts = $this->accounts;
// Do something with the user's accounts, e.g. grab the last "account"
$lastAccount = $usersAccounts->last();
if ($lastAccount) {
// If we found an account, return the rtype column
return $lastAccount->rtype;
}
// Return something else
return false;
}
Then in your controller you can eager load the relationship:
$users = User::with('accounts')->get(['field_one', 'field_two]);
Then you can do whatever you want with each App\User object, such as calling the isOnline method.
Edit
After some further digging, it seems to be the select on your relationship that is causing the problem. I did a similar thing in one of my own projects and found that no results were returned for my relation. Adding latest seemed to work alright though.
So you should remove the select part at very least in your relation definition. When you only want to retrieve certain fields when eager loading your relation you should be able to specify them when using with like this:
// Should bring back Accounting instances ONLY with rtype field present
User::with('accounts:rtype');
This is the case for Laravel 5.5 at least, I am not sure about previous versions. See here for more information, under the heading labelled Eager Loading Specific Columns
Thanks Jonathon
USER MODEL
public function accounting()
{
return $this->hasMany('App\Accounting', 'userid', 'userid');
}
public function isOnline()
{
$rtype = $this->accounting()
->latest('ts')
->limit(1)
->pluck('rtype')
->first();
if ($rtype == 'Alive') {
return true;
}
return false;
}
CONTROLLER
$builder = App\User::with('accounting:rtype')->ofType($filterRealm);
return $datatables->eloquent($builder)
->addColumn('info', function (App\User $user) {
/*
THIS HAS BEEN SUCCINCTLY TRIMMED TO BE AS RELEVANT AS POSSIBLE.
ARRAY IS USED AS OTHER VALUES ARE ADDED, JUST NOT SHOWN HERE
*/
$info[];
if ($user->isOnline()) {
$info[] = 'Online';
} else {
$info[] = 'Offline';
}
return implode(' ', $info);
})->make();

How to make accessor in Laravel with relations?

I try to display all location on page like:
{{$item->country()->first()->name}}, {{$item->city()->first()->name}}, {{$item->location()->first()->name}}
As you can see these values from relations country, city, location.
How to create accessor in this case? In which model to write accessor?
I tried this:
public function setTeacherNameAttribute()
{
$this->attributes['teacher_name'] = $this->country->name;
}
let say your $item model called Item so do this in it:
protected $appends = ['address'];
public function getAddressAttribute(){
$address = '';
if (!empty($item->country())) $address .= $item->country()->first()->name;
if (!empty($item->city())) $address .= $item->city()->first()->name;
if (!empty($item->location())) $address .= $item->location()->first()->name;
return $address;
}
then you can use it like this $item->address.
Note: change address to anything else if you already have column with that name.
Whether using relations or just plain models, accessors are always accessed through the final model. In your case in the country, city and location models.
The following method creates an accessor for the name attribute:
public function getNameAttribute($value) {
// do something with value, or not
return $value;
}

how to construct a function to detect if a relation is active or expired - eloquent

I have two models: Entity and Entityrelation.
The Entities can enter relationships.
I try to construct a table with lists of present and past relations
in the Entity I have this function:
// Entity.php
public function activeMembership()
{
return $this->hasOne('App\Models\Entityrelation', 'entitychild_id')->NotCeased()->Where('relationtype_id', '=', '4');
}
The NotCeased is a scope defined in the Entityrelation model:
// Entityrelation.php
public function scopeCeased($query)
{
return $query->where('ceased', 1);
}
public function scopeNotCeased($query)
{
return $query->where('ceased', 0);
}
The ceased is a column in the relationships table.
So when I want to get a number of active memberships, I just do this :
$object = Entity::find(1);
and in my view
$object->public function activeMembership()->count();
and a simple #foreach loop produces me a list of all active memberships of the Entity with id = 1.
My question
I want to design a function, which check if a given Entity was a child in an relation with an organization with ID = $parent_id (in entityparent_id).
returns 1 when an active relationship was found.
returns 0when the found relation was expired (ceased = 1)
returns null when no relation with the organization ever existed
First off, your relationship is not properly defined. You should have this in Entity.php: (relevant doc)
public function entityRelation() {
return $this->hasOne('App\Models\Entityrelation', 'entitychild_id');
}
Once you have this, you can use $entity->entityRelation to access an entity's relation.
Once you have that, it's pretty easy to do the requested function:
public function myMethod(Entity $entity, $parent_id) {
if ($entity->entityRelation && $entity->entityRelation->id === $parent_id) {
return $entity->entityRelation->ceased ? 0 : 1;
} else {
return null;
}
}

Resources