Yii2, few tables with uncomfortable generic field names for 1 Model - activerecord

I'm building REST++ service with Yii2, which should be able to deal with 2 table schemes, (databases storing ~the~same~ data):
a_new_one, which is perfect to be handled with ActiveRecord;
the_old_one, which has 1 generic table 'Object' with columns like 'field1', 'field2', etc, and few additional tables.
I want my request methods and controllers to be all the same for both schemes (would be very great, really). That means, that I need to have THE SAME MODELS for both cases.
The troubles all relate to the_old_one database:
Let's say data of model User is stored in tables Object and UserProfile. If I make 2 ActiveRecord classes for both tables, will it be possible to make hasOne() relations to them in 3d class User (not sure about inheritance here), so it can be manipulated like this:
$user = User::find()->someFilters()->someOrderingAndPagination()->one();
$user->Name = $your_new_name;
$user->Age = $why_not_90;
$user->save();
// and so on.
Because I really don't want to be forced to write it like this:
$user = User::find()->notSureAboutRelations()
->filters()->ordering()->pagination()->one();
$user->object->field7 = $your_new_name;
$user->userProfile->Age = $why_not_90;
$user->save();
I learned, Doctrine has easy model mapping ($user->Name can be mapped to db's Object.field7), but it's still impossible to map to 2 different tables within 1 Entity. Or am I incorrect ? If so, would it be a good idea to use Doctrine within Yii2 ?

So finished with idea to have the same controllers and models. Only URLs remain the same.
The old db Model data could be gained this way:
$user = User::find()
->select([
'Object.field7 as Name',
'UserProfile.Age as Age',
// ...
])->from('Object')
->join('UserProfile', ['UserProfile.ObjectId = Object.Id'])
->andWhere('User.Id' => $id);
And it's an ugly mess up when saving this models. Cos you need to assign a lot of fields in BEFORE_INSERT, BEFORE_UPDATE events.

Related

ManyToMany with and whereIn

I have a ManyToMany relationship between AdInterest and AdInterestGroup models, with a belongsToMany() method in each model so I can use dynamic properties:
AdInterest->groups
AdInterestGroup->interests
I can find all the "interests" in a single group like this:
$interests = AdInterestGroup::find(1)->interests->pluck('foo');
What I need is a merged, deduplicated array of the related 'foo' field from multiple groups.
I imagine I can deduplicate with ->unique(), but first, as you'd expect, this:
AdInterestGroup::whereIn('id',[1,2])->interests->get();
throws:
Property [interests] does not exist on the Eloquent builder instance.
The advice seems to be to use eager loading via with():
AdInterestGroup::with('interests')->whereIn('id',[1,2])->get();
Firstly, as you'd expect that's giving me an array of two values though (one for each ID).
Also, if I try and pluck('foo') again, it's looking in the wrong database table: from the AdInterestGroup table, rather than the relationship (AdInterest).
Is there a nice, neat Collection method / pipeline I can use to combine the data and get access to the relationship fields?
Use pluck() and flatten():
$groups = AdInterestGroup::with('interests')->whereIn('id', [1, 2])->get();
$interests = $groups->pluck('interests')->flatten();
$foos = $interests->pluck('foo')->unique();

Eloquent 5.4 - HasMany Object Mass Update Timestamps

really need your help here. ( I don't know what I want is possible on Eloquent )
Lets pretend this Relationship: One user can have many Childs
Note: Ignore problems in the code, this is just an example.
Now lets add some code into it.
// Return HasMany Object Instance from Eloquent.
$hasMany = $user->childs()
// Perform Mass Update.
$hasMany->update(['born_at' => Carbon::now])
So far nothing wrong with it, the first line returns an HasMany Object ( Documentation )
The problem is that Mass Updating touches my Model's timestamps ( created_at, updated_at ) and specially for this update I don't want it to do that.
Disabling it on the Model is not an option for me I do use the timestamp touch normally but I don't want to use in this case.
Neither I want to iterate over the Collection ( $user->childs ) because I have many rows to update and its an overhead to generate one query for each Model to update.
What I expect for an answer to this question: Simple, I just want an way to turn off the timestamps to do the mass updating or something like that.
( Normally on a single Model you can disable it like this: $model->timestamps = false, but this will not work here because hasMany instance does not have this attribute. )
You could set the property default of the model to false. So in you're model class you will have:
public $timestamps = false;
But this will always disable the timestamps until je use:
$model->timestamps = true;
In case someone finds this through Google:
One possible solution is to Fallback to the base QueryBuilder:
(new Child)
->newQuery()
->toBase()
->where('parent_id', $model->id)
->update([
'born_at' => Carbon::now,
]);
Of course, one could just use here something like DB::table(...)...

Saving a model with multiple foreign keys in Laravel 4

I understand that in order to save a foreign key, one should use the related model and the associate() function, but is it really worth the trouble of going through this
$user = new User([
'name' => Input::get('name'),
'email' => Input::get('email')
]);
$language = Language::find(Input::get('language_id');
$gender = Gender::find(Input::get('gender_id');
$city = City::find(Input::get('city_id');
$user->language()->associate($language);
$user->gender()->associate($gender);
$user->city()->associate($city);
$user->save();
when one can simply do this?
User::create(Input::all());
I feel like I'm missing something here, maybe there's an even simpler and cleaner way to handle foreign keys in controllers (and views)?
You can use push() method instead which would allow you to push to related models.
This link should answer your query.
Eloquent push() and save() difference
I really don't see anything wrong at all with doing User::create(Input::all());.
Obviously you'd want some validation, but it's doing the same thing.
I think the associate() method is more useful for the inverse of your situation.
For example, say you had a form which a user could fill out to add their city to your app, and upon doing so, they should automatically be assigned to that city.
$city = City::create(Input::all()); would only achieve the first half of your requirements because the user has not yet been attached as city does not have a user_id column.
You'd then need to do something like $city->user()->associate(User::find(Auth::user()->id));

Laravel Eloquent and combing data to send to View

I'm trying to figure out a way to combine data from two tables into a single variable that I can then send to my view. I'm using Authority as my authentication bundle and so I have the following tables set up: users, roles, role_user. I want to get the following data into a single variable.
From the users table:
id, name, email
From the roles table:
name
The following returns all the user data in the users table:
$users = User::all();
But, I want to make a chain that can get the related data stored in the roles table? I want all users and all of each users roles together.
And while I can find examples that help get related data for a single record I haven't been able to find any reference to retrieving entire tables with related data.
Thanks.
$users = User::with('roles')->get()
Eager loading is what you are looking for, read the docs :)
Im not 100% sure what you are after, I think you should make relations with Eloquents methods. But if you are looking for a way to just merge the data returned by two models you could do the following:
$users = User::all();
$roles = Roles::all();
$array = array_merge($users->toArray(), $roles->toArray());
return Response::json($array);
You could make the model calls so that they return exactly what you are after and then merge them together. If you want one Model to return something specific just make a function for it.
You need to use something like that:
$user = User::get();
$roles = Roles::get();
$user .= (object) $roles; //because of that both them are object array and we have to combine them as object array...
than you can pass the data to View
return View:make('templatefile')//or Redirect to_route whatever
->with('user', $user);
But the best way is belongs_to in your case. Please read the documentation:
http://laravel.com/docs/database/eloquent#relationships

Doctrine toarray does not convert relations

I followed doctrine documnetation to get started. Here is the documentation.
My code is
$User = Doctrine_Core::getTable("User")->find(1);
when I access relations by $User->Phonenumbers, it works. When I convert User object to array by using toArray() method, it does not convert relations to array. It simply display $User data.
Am I missing something?
By using the find method you've only retrieved the User data which is why the return of toArray is limited to that data. You need to specify the additional data to load, and the best place to do this is usually in the original query. From the example you linked to, add the select portion:
$q = Doctrine_Query::create()
->select('u.*, e.*, p.*') // Example only, select what you need, not *
->from('User u')
->leftJoin('u.Email e')
->leftJoin('u.Phonenumbers p')
->where('u.id = ?', 1);
Then when toArray'ing the results from that, you should see the associated email and phonenumber data as well.
I also noticed an anomaly with this where if you call the relationship first then call the ToArray, the relationship somehow gets included. what i mean is that, taking your own eg,
$User = Doctrine_Core::getTable("User")->find(1);
$num= $User->Phonenumbers->office; // assumed a field 'office' in your phone num table
$userArray = $user->toArray(true);
In the above case, $userArray somehow contains the whole relationship. if we remove the $num assignment it doesn't.
am guessing this is due to doctrine only fetching the one record first, and it's only when you try to access foreign key values that it fetches the other related tables

Resources