Laravel hasActiveOneOfMany relation - php

Obviously this does not exist but I am looking for a way to implement it.
Example, I am playing a game where I have 3 teams but I can only be actively playing for one team at any time and when I switch team I essentially starting from the beginning but I would like to retain the progress if I switch team.
My tables would look something like this:
Users:
active_team_id
TeamProgress:
user_id
team_id
team_level
team_xp
TeamNames:
id
team_name
So there would only be 3 teams defined in TeamNames and while any one of these 3 are active (as set in active_team_id in the users table) then I want to be able to directly target it with something like
$user->teamProgress->update()
and update the active team directly.
Similarly I would like to do something like
$user->teamProgress->get()
and just get the team progress for that users active team while a few others may exist within team progress.
Then if I switch the active_team_id on the user table and do the same calls above I now update / get info for the second team specified in active_team_id
Is there a way to do this with a relation or am I overthinking this and better off doing this by just directly targeting the TeamProgress model using the information I already have as a user?
$teamProgress->where('user_id', $user->id)->where('team_id', $user->active_team_id)->get()

You can try this package https://github.com/topclaudy/compoships. It allows you to define relations by matching multiple columns. For example
class User extends Model
{
use \Awobaz\Compoships\Compoships;
public function activeTeamProgress()
{
return $this->hasOne(TeamProgress::class, ['id', 'active_team_id'], ['user_id', 'team_id']);
}
}

Related

Structuring Laravel Controllers

I have
users
id
username
companies
id
areas
id
area_company
id
area_id
company_id
area_company_user
id
area_company_id
user_id
company_user
id
company_id
user_id
area_user
id
area_id
user_id
where
one user has 0 to many areas AND one area can have 0 to many users
one area can have 0 to many companies AND one company can have 0 to many areas
one company can have 0 to many users AND one user can have 0 to many companies
one area_company can have 1 to many users AND one user can have 0 to many area_company
area_company_user has attributes specific to that kind of user
Also, I'm structuring the routes in the following manner
/users - all existing users
/areas - all existing areas
/companies - all existing companies
/areas/{area}/companies - all existing companies in a specific area
/users/{user}/companies - all existing companies from a specific user
/companies/{company}/areas - all existing areas the company is in
/areas/{area}/companies/{company}/users - all existing users from a company that exists in a specific area
For 1., 2. and 3. I'm creating controllers that follow the next pattern
AreaController with methods index(), create(), store(), show(), edit(), update() and destroy()
GET /areas, index() method,
GET /areas/create, create() method,
POST /areas, store() method,
GET /areas/{area}, show() method,
GET /areas/{area}/edit, edit() method,
PUT/PATCH /areas/{area}, update() method,
DELETE /areas/{area}, destroy() method.
There's now basically two cases left from that route list
Case 1: 4., 5. and 6.
Case 2: 7.
My question is, should I create new controllers for each case since I'd like to perform various actions in each? If yes, that'd mean, respectively
Case 1: AreaCompanyController, UserCompanyController and CompanyAreaController
Case 2: AreaCompanyUserController
Note: this was a helpful answer but didn't exactly address my concern.
You can see there is already something called nested resource in docs which can cover your cases 4,5,6. In docs there is PhotoCommentController which you've described that you're using it (question case 1).
For question case 2 you can for example make model for pivot table and have it that way for route and controller. For example AreaCompanyUserController if I understand well, you have here area_company pivot table with association of user. So many users can be part of same area_company association.
You can circumvent Area and Company models use with use of AreaCompany model that would be the pivot model. Knowing id of that pivot model you can easily get associating area, company and users.
class AreaCompany extends Pivot
{
/** code here */
}
Having this, you can name your resource route /area-companies and /area-companies/{$areaCompany}/users to avoid triple nesting.
I presume any of these decisions have own consequences like subdirectory planning for controllers, form request files, providers, sometimes even route files.
Probably heard and read for thousand times, but important is to stick with consistent way of it. Consider what could be lesser technical debt in some potential upgrade.
In order to simplify the debugging and maintenance process of the project it's better to define the controller for each case in case if anything goes wrong it's easy to debug and solve the problem so you will be having
AreaController , UserController , CompanyController

how to avoid and prevent the duplication between two tables in the laravel migration?

I'm developing the CMS(College Management System) website using LARAVEL PHP framework. Now we need to build up to three types of consoles(Admin, Student, Employee). I'm stuck in the admin console that admin is able to perform the selections process. I have performed the task for the following.
Foreach series has many Users.
Foreach users have one Profile.
Foreach profile has many qualifications, experiences, attendances..
Students and Employees Record saved in the user's table.
Now we need to remove students and employees written in the eclipse shape because there is a duplication code in these two tables(student and employee), then we need to create the profiles table. Now remaining tables classes and courses(I have not yet decided what type of relation).
If you need any code from this example then I will add in the comments section.
In order to prevent duplication (if students and employees will always be the same entity) is to introduce a new model in the system called Person (or something similar). Then you will create additionally a PersonType enabling you to expand the model further if you ever need something more than student and employee.
DB schema would then have a relationship:
persons ---- M:1 ---- person_types
Where person_types would have:
ID Name
1 Student
2 Employee
This way you can reuse everything.

laravel 5 OOP structure/architecture advice

I have a general question about how to implement the best practice of model structure for an application I'm building in Laravel 5.
So, at the moment I have things set up like this:
'user' model and table: id, email, password, admin level - this is really just the info for authenticating login.
'user-details' model and table: id, userID (foreign key for user table id field), name, address etc - all the other details
'lesson-type' model and table: id, teacherID (foreign key for user-details table id field), lesson-label etc - info about different types of lessons
At the moment I have a Teacher Controller in which I'm passing through to the view:
- The info from the User table
- The info from the User-details table
- A list of different lesson types for the teacher from the Lesson-type table
But I kind of feel that all this should be tied together with one separate Teacher model which would extend the User-details model (and probably which in turn should extend the User model), but wouldn't have it's own table associated with it, but all the info pertaining to either updates for the User-details or the Lesson-types table would be stored in those relevant tables. Would this be correct?
(I should also say that users may alternatively be parents rather than teachers, and so would I would have a separate Parents model for all the properties and so on associated with parents)
I would then pass only the Teacher model object into the view and thus gain access to all the teacher info such as personal details and array of lesson types.
As I'm typing, this is sounding more and more to me like the right way to go, but it would be great to get some advice.
1 - technical implementation: I guess in the Teacher model, I'd populate all the relevant teacher into class variables (Name, array of lessons etc) in the constructor?
2 - am I over complicating this structure by having both Users AND Users details tables?
3 - Does what I'm proposing make the most structural sense in Laravel?
4 - just another thought I've just had, should the teacherID in the lesson-type table actually refer to the User table rather than the User-detail table... so user-detail and lesson-type would both be direct children of the user table??
Very much obliged for any help :)
You shouldn't extend models like that unless there is a clear inheritance. From a logical standpoint, it just doesn't make any sense since you'll have to overwrite most of what is on the User model anyway. And what you don't overwrite will be incorrectly mapped to the database because they are 2 completely different tables. What you actually want to do is utilize Eloquent relationships.
For clarity, I am assuming this basic structure:
users - id
teachers - id, user_id
user_details - id, user_id
lesson_types - id, teacher_id
Those should be 4 completely different models all interconnected using the Model::belongsTo() method. So the Teacher model would be
class Teacher extends Model {
public $table = 'teachers';
public function user() {
return $this->belongsTo('App\User');
}
}
When you query for a teacher, you can do Teacher::with('user')->get(). That will return all records from the teachers table and on each instance of the Teacher model, you'll be able to call $teacher->user and get the User instance associated with that teacher. That is a full model, not just extra data, so you have access to everything on the User Model, which is generally the main reason for extending
For your list of questions:
I may be misunderstanding you, but this isn't how an ORM works. I'd suggest going back and reading through the Eloquent docs (if you're running 5.0, I suggest reading 5.1's docs since they are much, much better)
It will depend on who you ask, but I tend to think so. If the data is clearly related and there is no reason for it to be shared across record types (for example, I generally have an addresses table that all records reference instead of having 5 address fields repeated on multiple tables), I believe it should all be on one table. It just makes it more difficult to manage later on if you have it in separate tables.
There will be those who disagree and think that smaller scopes for each table are better and it will likely allow for quicker queries on extremely large datasets, but I don't think it's worth the extra trouble in the end
No, as I have explained above
The teacher_id column should reference the teachers table, assuming that lessons belong to teachers and cannot belong to just any user in the system. Using the ORM, you'll be able to do $lesson->teacher->user->userDetails to get that data
I really think you need to go back and read through the Eloquent docs. Your understanding of how Eloquent works and how it is meant to be used seems very basic and you are missing much of the finer details.
Basics
Relationships
Laracasts - Laravel Fundamentals - You would benefit from watching Lesses 7-9, 11, 14, and 21

Laravel 5.1 / Eloquent: How do I use a 3rd table to select from the second table

I have three tables: users, purchase_orders and approvals.
One purchase_order has to be approved by multiple users.
When a new purchase_order gets created, I also create 3 pending approvals belonging to that PO.
The approvals table has a field allowed_user_type that determines who can approve it.
I can't figure out, what is the Eloquent way of selecting the pending purchase orders that can be approved by a specific user, as these are determined from the approvals table.
So far I can pull the pending approvals from the approvals table for a user with the following in the User model.
public function approvals_pending()
{
return $this->hasMany('App\Approval', 'allowed_user_type', 'user_type')
->where('approved', '=', 0);
}
The question is, how do I combine this with a theoretical filter?
I mean ideally, I would love to write:
return $this->hasMany('App\PO')->whereIn('id', '=', $this->approvals_pending()->get()->po_id);
Or something like that...
Any ideas would be greatly appreciated.
OK, for anyone interested I found a solution:
It's very close to what I thought I would have to write.
The lists method basically creates a single array out of the selected field, so it can be plugged-in directly to a whereIn method like so:
return \App\PO::whereIn('id', $this->approvals_pending()->lists('po_id'));
I don't know if this is the most Eloquent way of doing this but it does work.

Yii One relation for multiple tables

I am trying to write a customized relation that uses multiple tables, and this relation neeeds to join to the other tables by using a key from the first table.
Each table has the same columns.
So, let the story begin:
I am developing a online strategy based game. (PBBG - Persistant Browser Based Game)
I had a big table (30.000.000 rows) and I have split that table in 100 smaller tables (300.000 rows in each table).
The action happens within villages.
Details about the villages are stored within the village table.
Each village is situated within a continent, so there is a k number that gives me the continent that the village belongs to.
The village table has the following columns:
id - p.k.
x - x position on map
y - y position on map
k - f.k. continent id
name
user_id f.k.
points
I have 100 continents, that's why i have 100 new smaller tables.
I also have a table where I store the details for all the buildings.
The building details were stored within the village_building table.
So, from the original table village_building i now have village_building_k1, village_building_k2, ..., village_building_k100.
A village_building_k... table has the following columns:
id - p.k.
village_id - f.k.
building_id - f.k.
Now, I am trying to write a relation that jumps from model village to model village_building_kX where X should change when needed.
If I could use the k value from model village, that would give me the name of the table that i need to join.
If k = 2, the i need to jump from village to village_building_k2 using a concat
public function tableName() {
return 'village_building_k' . self::$k;
}
public function relations() {
return array(
'relation_village_building' => array(self::HAS_MANY, 'VillageBuildingKXSlaveM', 'village_id'),
);
}
$model_village->relation_village_building->building_id
Are you sure, that you need to solve this problem on framework level? I suggest to use here something like http://en.wikipedia.org/wiki/Shard_(database_architecture)
I think you need to add some shared databases. Due to your big database you can't manage it by your framework. Just try shared database for manage databases. Also you can try mysql cluster for manage database Follow this link and
this This may be helpful for you. Remember one frameworks are some set of functions so that you can to manipulate your function with your codes and supporting environment like databases and etc.
Actually you can try to pass db name from some global parameters, for example from session.
public function tableName()
{
return 'village_building_k' . Yii::app()->session['table'];
}
Problem is to save session for your gamer long time. If you'll get alot of users, it will become a problem.
If you have few tables with same structure, probably your database architecture is wrong. If it was sharding, you need to change AR for this.
Main problem in yii and sharding is that AR in __construct() calls getMetaData() to get table schema, so you need table name in that level.
Search on forums for solutions, i personally didn't found good article on english. Here is article about horizontal sharding realisation with Yii and Redis here. It's on Russian, but you can watch atleast some code.
And 30.000.000 table is ok, if you'll work right way with it, even in mysql.

Categories