I have 2 entities: User and Archive, with a many to many relation between them:
In user entity I have:
/**
* represent the script collection for a user
* #ORM\ManyToMany(targetEntity="My\ApplicationBundle\Entity\Archive", inversedBy="users")
* #ORM\JoinTable(name="collection")
**/
private $collection;
and in Archive:
/**
* represent the users having this archive in their collection
* #ORM\ManyToMany(targetEntity="My\UserBundle\Entity\User", mappedBy="collection")
**/
private $users;
this relationship generates a table called "collection" with an user_id and an archive_id field. Insert data in these table is not a problem.
now, I'd like to get all the archive for a specific user, but I don't know where to start. I tried
$this->getUser->getCollection()
but it seems not working as expected. Probably I'd need some custom repository class? Many thanks
Related
I've come up against a strange issue which I cannot seem to figure out.
I'm creating a CRM in Symfony 2 implementing Doctrine, and using an OpenCart database.
There is the ability to add an order via the CRM which persists the data given into the relevant tables, but I'm falling at the final hurdle. I'm trying to persist the order ID yet for some reason I'm getting the error:
order_id cannot be null
This is how the entity entry is set up in the file:
/**
* #var integer
*
* #ORM\Column(name="order_id", type="integer", nullable=false)
*/
private $orderId;
And I'm using this to set it:
$order_option->setOrderId($order_id);
I know for a fact that $order_id has an integer value, as I've printed it out before persisting (I even tried hard coding it into the set function) but it still ends up being null.
I am confused as to why this is happening since every other set is working, plus it's even correctly assigned the value to the $this->orderId variable as I tried debugging that too.
If anyone can maybe shed some light on this I would be grateful.
You have probably forgotten to add #ORM\Id
/**
* #var integer
*
* #ORM\Column(name="order_id", type="integer", nullable=false)
* #ORM\Id
*/
private $orderId;
Figured it out!
There was a protected variable called $product in the entity which was being joined by order_id, however this is never persisted or referenced. So, I just deleted it and now the order_id is persisted as normal.
I have this setup as my database structure which already works pretty well, but I feel like it could be better, but cannot figure out how.
Database Structure:-
Events can have multiple sub-events. Users can join these events and optionally their sub-events. With this structure I have all constraints, but the one that links the event attending with the sub event attendings => there can be sub event attendings left without having the main event attending (this shouldn't be possible as users who don't attend the main event cannot attend it's sub events).
I am currently working with Laravel so it looks like this:
User:
hasMany Event (as organizer of these events)
belongsToMany EventAttending (which events is a user joining)
belongsToMany SubEventAttending (which sub-events is a user joining)
Event:
belongsTo User
hasMany SubEvent
belongsToMany EventAttending (which users are attending this event)
SubEvent:
belongsTo Event
belongsToMany SubEventAttending (which users are attending this sub-event)
The problem arises when trying to manage the sub-event attendings of a user. How would I make this constraint between the event and sub-event attendings exist, while keeping it clean with the capabilities of Laravel / What can you give as advice for a better structuring / How would you guys do it?
Edit
To clarify, the events and sub-events store different things, have different properties. Also I need to store information for the event attendings (like did he attend in real life) and sub-event attendings, most likely differing ones.
Edit
Edward Haber has the better structure, but as my two pivot tables (the connection between User-Event and User-SubEvent) store additional diferent type of information, currently chose to remain with the initial design.
One of the biggest problems I am facing (which does exist with both structure) is querying for a User while getting the attended Events with the attended SubEvents. Trying to achive this result:
User[]:{
...,
attending_events[]:{
...,
attending_sub_events[]:{
...
}
}
}
Been thinking for hours for a clean solution, couldn't get anything else to work. Wouldn't like to write the whole SQL query manually. My current implementation with the two pivot table looks like this (result not nested, code messy):
$users = User::withCount(['attendingEvents' => function($query) use($eventId){
$query->where('event_id', $eventId);
}])
->with(['attendingSubEvents' => function($query) use($eventId){
$query->select('id')->whereHas('event', function($query) use($eventId){
$query->where('id', $eventId);
});
}]);
With this approach I get the sub-events separated from the main event. (querying only for the main attending-event count, because I only need to determine whether he is joining or not).
The pattern for this type of solution is to use a Polymorphic Relationship. This solution focuses just on connecting the User to the Event and SubEvent - the rest of the relations look correct.
<?php
class User extends Model {
public function attending() {
return $this->morphTo();
}
}
<?php
class Event extends Model {
public function attendees() {
return $this->morphMany('App\User', 'attending')
}
}
<?php
class Subevent extends Model {
public function attendees() {
return $this->morphMany('App\User', 'attending')
}
}
The users table needs these fields:
*users*
-----
id
attending_id
attending_type
This is all untested - but the basic idea. (Edited: changed name of polymorphic method to attending from attendee)
So I have a weird question.
I'm making an application in Laravel and Angular. I'm using Eloquent models.
Right now I have 2 tables, 1 users table (with the users info), and 1 events table (with the name, date, ... of an event).
These 2 are binded by a oneToMany relation (Every event belongs to an user). But now I would like people to sign up for that event. ( a switch in the front end, so they can apply for the event).
So, many users will have many events.
The catch is also, the owner of the event can manually set an maximum # users. (This is an tinyINt in my event table).
So now my question. How can I pull this off?
Options I have thought off:
1. I make a pivot table
-> Is this possible? Because the User and the event are already binded by a one to many realtion? So how can I bind them with a many to many relation again?
2. Every time a user signs op, I add his ID to an array in the events table.
-> Is this possible? I could then be able to set the maximum # users by checking the length of the array?
Thank you friends!
Using a pivot table is the correct approach here. The fact that the two tables are already bound by a different relation should not deter you.
class Events extends Eloquent
{
public function owner()
{
return $this->belongsTo(App\User::class);
}
public function subscribers()
{
return $this->belongsToMany(App\User::class, 'event_user');
}
public function canAddSubscriber()
{
if ( ! $this->max_users) return true;
return $this->max_users < $this->subscribers()->count();
}
}
As you can see, you can use the relationship to determine if a subscriber can still be added.
Circumstances
I have three models/db-tables related with 1:n each: An order has multiple commissions and a commission has multiple commission_positions. Therefore the commission_position has an FK-field containing a commission id. The commission itself has an FK-field containing the id of an order.
Order > Commission > CommissionPositions
Problem
What I need to do now is select all the CommissionPositions having a certain value in the related Order-Model. Obvious solution is to use the Query-Object of CommissionPosition which I extended with a named scope. The named scope looks like this:
class CommissionPositionQuery extends ActiveQuery
{
/**
* Named scope to filter positions of a certain alpha order id
* #param integer $id the alpha order id
* #return \common\models\query\CommissionPositionQuery
*/
public function alphaOrderId($id)
{
//TODO: with not working
$this->with(['commission.order']);
$this->andWhere(['alpha_order_id'=>$id]);
return $this;
}
}
The relation commission is defined on the Commission-Model and working. The second relation order is defined on the commission-model and working as well. The filtered field alpha_order_id is in the Order-Table. Now I execute the query like this:
$filteredPositions = CommissionPosition::find()->alphaOrderId(17)->all();
The scope is called successfully and the where-part is used, but when I check the generated SQL I see no join-statements even though I use the with-method to tell yii to fetch the relation together. The response is 'unknown column alpha_order_id' which makes sense as there is no join to the related tables. This is the generated SQL:
SELECT * FROM `commission_position` WHERE (`alpha_order_id`=17)
What am I missing? Is this a bug of Yii2?
Found the soution myself. The naming changes between Yii1 and Yii2 lead to a little confusion. To prevent others from wasting time here the details:
Yii1
In yii 1 you would join in a relation (exemplary: commission) directly like this:
$query->with = 'commission'
$query->together = true;
Yii2 / difference
When calling the with-method like showed in the question the relation was successfully added to the with-array of the ActiveQuery. However, when executing the query, the join part was missing.
Solution
Seems like the with-method is NOT the way to go. Instead I used the method called joinWith with the following signature:
public function joinWith($with, $eagerLoading = true, $joinType = 'LEFT JOIN')
Now as described in the answer I defined the relation as the first argument ('commission.order') and left the rest as is, because the default values are perfectly fine. Pay attention to the default value of the second parameter. this makes sure the relations are joined in directly!
VoilĂ ...the resulting sql contains the needed joins. One pitfall is to be considered though: Ambigious column namings is of course to be handled by ourselves! Link to the documentation of the method:
http://www.yiiframework.com/doc-2.0/yii-db-activequery.html#joinWith()-detail
If you want a JOIN use:
$this->joinWith(['commission.order']);
I have two objects, Customer and Store. I would like a user (from a user table) to be able to specify a customer or store as "preferred". I would then be able to see a list of users who prefer different stores or customers. Is this possible with a hibernate mapping?
What would the table structure look if a status of preferred could be set on either customer of store per user?
So, a User has many preferred Stores, and a Store is the preferred store of many users. This is thus a ManyToMany association between User and Store.
Just map it as explained in the documentation:
public class User {
#ManyToMany
private Set<Store> preferredStores = new HashSet<Store>(0);
}
public class Store {
// necessary only if you want the association to be bidirectional:
#ManyToMany(mappedBy = "preferredStores")
private Set<User> preferringUsers = new HashSet<User>(0);
}