I'm not sure if I'm using the MVC architecture correctly so go easy on me if I'm going wrong.
I have a model Account that grabs a load of valuations from a Holding model. These 2 models are linked as Account hasMany Holdings.
In my Account model I have a function that retrieves the sum of the holdings from the account and arranges it in a $date=>$value type array.
I have another, separate, model called FxRate whose table is a load of FX rates and dates. In my Account model I want to retrieve an array of fx rates by running a find on the FxRate table so I can convert the valuations array I retrieved earlier.
FxRate is not linked to either of the other models and I can't seem to find any data from it from within my Account model. What's the correct way to achieve this?
If you are in your Model file you can use this:
App::uses('FxRate', 'Model');
$FxRate = ClassRegistry::init('FxRate') // and not $FxRate = new FxRate(), see comments;
$FxRate->find('all');
in your controller instead you can use loadModel
$this->loadModel('FxRate');
$this->FxRate->find('all');
Related
I'm just getting going with Laravel, and have used Eloquent to define my Campaign table. I have a Campaign model which is currently empty.
I'm not sure how to add attributes to this model to represent the fields in the db - or even if I should. The Laravel documentation seems thin on models and searches keep leading me to accessors and mutators.
If I have a database field called platform_type in my campaigns table, how do I link the PlatformType model attribute to this field?
To clarify:
This is not a question about relationships - there is only one entity in my solution thus far.
platform_type is a field in my campaigns table because it is an attribute of a campaign - I'm asking how to represent this in my model.
The model has an internal array which stores the attributes of a given row (it's called $attributes and replicated by $original if you look for them in the source code). The reason it's replicated is so when you call save() it will only do a save if you actually changed them from the originals.
You can access said attributes via $modelInstance->getAttribute("platform_type") or $modelInstance->platform_type which will call the magic __get method that in turn calls the getAttribute
So in your case you can have:
$campaign = Campaign::find($id);
echo $campaign->platform_type;
The ORM will automatically create the relevant SQL query and fill the model instance with the attributes of the row it finds.
You need to define relationships. In the PlatformType model:
public function campaigns()
{
return $this->hasMany(Campaign::class, 'platform_type');
}
And in the Campaign model:
public function platformType()
{
return $this->belongsTo(PlatformType::class, 'platform_type');
}
You also need to rename the campaign table to campaigns. Or you should add this to the model to be able to use a custom name:
protected $table = 'campaign';
At this point, these tables will be connected and relationships will work. However, it is recommended to add foreign key constraints.
I was working on making a group functionality for my website which uses a many to many relationship between groups and users.
My User model looks like this:
public function groups(){
return $this->belongsToMany('App\Group')->withPivot('role')->withTimestamps();
}
My Groups model looks like this:
public function users(){
return $this->belongsToMany('App\User')->withPivot('role')->withTimestamps();
}
So my third column has the name of role which is a string variable and is set to a default of "member" for members of my group and I set it to "admin" for the actual user who creates a new group. But I want the admin to have the option of making multiple members admins as well which would require me to check weather the current current user who sent the request is an admin or not. If he is, then I wanna be able to take his request of making a member an admin which would require me to update the role for that particular "member" to an "admin".
In the laravel documentation it only shows you how to attach and detach data in a pivot table and else where I have only seen methods of retrieving data from the first two columns but how can I do the same for additional columns and also be able to update it using the updateExistingPivot method?
You could access the column simply using pivot e.g :
$user->pivot->role
Take a look at Retrieving Intermediate Table Columns in documentation Eloquent Relationships.
Hope this helps.
How can you update multiple models and their relations at the same time?
For example:
EditPost is a model with a editor() relation belongsTo User model.
Now lets say I have to update the editor in all the EditPost objects with original_post_id
EditPost::where('original_post_id',4)->get()
Possible Solutions
a. To do it by referring the user by ID instead of by the Model User
EditPost::where('original_post_id',4)->update(array('editor_id',3));
b. To do it by a foreach and saving each model
However
Neither of these appeals to me as they don't gel in general with the object concept of Eloquent or they would mean doing multiple updates instead of one.
I was wondering if Eloquent itself had a more elegant solution
You don't specify the other end of the association, but I assume you are looking for something like this?:
$user = User::find(3)
EditPost::where('original_post_id', 4)->editor()->associate($user)->save();
Recently started working with OOP in PHP. Following the "code to an Interface" principle, i got confused as to the type hint to use when passing a single object or multiple as argument to a method.
Currently, i have a "Student" class - represents a row in my students table, i also have a "Students" class that holds multiple student objects in an array.
To fetch the profile of one student, i pass the Students object (holding a single student object) to the profile class. I set a Students type hint in the profile class.
Now i feel this is bad code as i have lines like this
student = new Students();
and students = new Students();
question is,
am i on the right path?
if i remove the Students class and work with Student alone, based on the principle, how do i pass multiple Student objects (assuming array) to the profile class if it accepts a Student type hint?
what options do i have?
Thanks.
If by Students you mean a collection of Student objects, perhaps a better name would be StudentCollection or StudentSet.
There are two ways around the type hint problem:
Introduce a method on StudentCollection called ->getProfiles(); it would return an array of profiles for each Student instance it's managing by calling methods on Profile.
Introduce a (static) method on Profile that operates on a StudentCollection instance.
The first option has feature envy, which is why I've included a workaround.
Instead of reinventing the wheel you might want to try Doctrine or at least take a look at its architecture.
I'm not sure if I get your exact issue... But if you want to go for your own code I would first abstract the DB layer as well and have some base classes like Database, Table, Row, Field that an describe the DB stack and extend them as needed with some magic methods. So when you do Student extends Table it would automatically check for a "students" table or whatever else convention you like to implement. Alternatively you could just pass the table name as arg.
Whatever Object is returning the result set from the database would have to construct a single Row object for each row and add it to a collection of rows that I would name ResultSet and contains all the row objects and return that collection.
I have three classes to define objects: Users, Members and Projects.
The User class defines details such as id, email_address and
name.
The Member class defines details such as the id, user_id,
project_id and datetime_accepted.
The Project class defines details such as id and title - this
isn't important though.
The system has Users and Projects. A Member is a User working on a Project. In other words, the Member class defines a link between two objects.
My question is this:
I want to get a list of members belonging to a certain project, and I want to collect variables from both classes (Member and User - such as User:name and Member:datetime_accepted) in my result set.
Do I need to define a new class that has all the variables from both classes, or is there some other, more efficient structure that I can use to handle this neatly and in an object oriented manner?
You can easly cast StdObject into array by:
$result = array_merge((array)$user, (array)$member);
then you will have an array of variables you need. Add this to new function in Project class,
or consider using Member as child of User class.
When working with Active Record Models, you would generally have a method in one object to get related objects. If you wanted to simplify the SQL to one query, you're getting away from the Active Record Model. This is fine, it just changes the way you approach the problem.
What I have done in the past is one of two approaches:
To add 'virtual properties' to an AR, for example, my Login (User) class has a property "Roles" which is populated by a JOIN in its standard loading query.
To create a Report object which I extend for more complex situations. The Report subclasses have a property that is the multi-table query, and other properties which represent parameters for the WHERE clause. The class produces an array of arrays.
What I ended up doing to solve this issue was to create a Project and a User object inside the Member. The objects were created when the member was constructed. Works okay.