Eloquent: Scope for getting related models? - scope

I have 3 models: User, Project, Task
Each user has many projects, each project has many tasks.
I want to do something like:
$user->projects()->tasks() to get the tasks of the projects of a user. projects() is a hasMany() relation and I believe tasks() should be a Scope, but have no idea how to implement it.

Well, suppose you have 3 models defined in this way:
User
class User extends Eloquent
{
public function projects()
{
return $this->hasMany('Project');
}
}
Project
class Project extends Eloquent
{
public function tasks()
{
return $this->hasMany('Task');
}
public function user()
{
return $this->belongsTo('User');
}
}
Task
class Task extends Eloquent
{
public function project()
{
return $this->belongsTo('Project');
}
}
I believe this would be enough to query all the user projects and tasks.
If you already have an instance of User class you can just load the required relations:
$user->load('projects.tasks');
dd($user);
Having belongsTo relations defined allows you to query all the tasks with projects and users they belong to:
Task::with('project.user')->get();
I am not sure about getting just a list of tasks. This is the first solution that comes to my mind:
$tasks = Task::whereHas('project', function($query) use ($user){
$query->whereHas('user', function($query) use ($user){
$query->where('id', $user->id);
});
})->get()
I believe there are other ways to achieve it using query builder and join() method.

Related

How to send params of current request to the constructor of the service?

Update: I have fixed it by only supplying the pattern of the path of the collection, and creating a function that can parse the provided IDs and now the functions themselves create the collections when they are called upon and it also works with Typescript:)
Updated in the repository:
https://github.com/Darkbound/nestjs-firebase/tree/main/src/firebase
In the user service:
https://github.com/Darkbound/nestjs-firebase/blob/main/src/user/user.service.ts
In the purchase transactions service: https://github.com/Darkbound/nestjs-firebase/blob/main/src/user/modules/purchase-transaction/purchase-transaction.service.ts
In the purchase transactions controller: https://github.com/Darkbound/nestjs-firebase/blob/main/src/user/modules/purchase-transaction/purchase-transaction.controller.ts#L14
Now the functionality works out of the box, the service class simply needs to extend the FirebaseCollectionService and give it the pattern of the path to the collection and thats it!
https://github.com/Darkbound/nestjs-firebase I have uploaded it into a repository, you only need to add .env with the keys for firebase admin.
And the specific example: https://github.com/Darkbound/nestjs-firebase/blob/main/src/user/modules/purchase-transaction/purchase-transaction.service.ts
I have created a class that gives me the functionality to perform CRUD operations on firebase, so that I can just directly inherit from it for any of my CRUD resources, as the logic is again usually mostly the same. Just like Nestjs generator gives me all of the routes for it.
#Injectable()
export class UserService extends NestjsFirebase<User> {
constructor(#InjectFirebaseAdmin() firebase: FirebaseAdmin) {
super(firebase, "users");
// console.log(userId);
}
}
This works great, I can reuse that for any level 1 collection I have in firebase, however if I want to get into a nested collection on firebase, well thats a problem, because the path there needs to be dynamic and super(firebase, "this is no longer just users").
Say if I want to access the transactions of a user, so users/SomeUserIdXYZ/transactions, then the path is entirely dependent on the userId and is changing, therefor, I need to recreate the instance of the service (I simply need a new instance of the class), with a new path:
super(firebase, ["users", userId, "transactions"]
However with my still limited knowledge about Nestjs I know that everything in it basically is a Singleton and there is probably no way to do this? To get a new instance of the service, for every request that I have?
The solution that I can think of is, to handle that within my route functions, so if its a findTransactions:
#Get("users/:userId/transactions")
async findTransactions(#Param("userId") userId: string) {
return this.userService.findAll(`users/${userId}/transactions`);
}
And I am pretty sure that this will work, if I add a path argument to each of the functions, but this seems like coupling the Controller with what my Path in firebase should look like, instead I need to be able to give it just the params so that it can create its own path.
This is NestjsFirebase:
#Injectable()
class NestjsFirebase<T> {
constructor(#InjectFirebaseAdmin() private readonly firebase: FirebaseAdmin, private readonly collectionPath: string) {}
async findAll(userId: string): Promise<T> {
const db = new FirebaseCollectionService<T>(this.firebase, this.collectionPath);
return await db.findAll(userId);
}
}
export class FirebaseCollectionService<T> {
protected db: CollectionReference<T>;
constructor(firebase: FirebaseAdmin, collectionPath: string) {
super(firebase.db);
this.db = this.createCollectionPath(collectionPath);
}
public async findAll(id: string) {
... some logic to find all transactions ...
}
}

How to connect two different ViewModels in Kotlin AndroidStudio

I have two different View Models with their own fragments, and I want my arrayListB in ViewModelB have the same value of my arrayListA in ViewModelA.
I am sure this may help you to do that!
Architecture Components provides ViewModel helper class for the UI controller that is responsible for preparing data for the UI. ViewModel objects are automatically retained during configuration changes so that data they hold is immediately available to the next activity or fragment instance. For example, if you need to display a list of users in your app, make sure to assign responsibility to acquire and keep the list of users to a ViewModel, instead of an activity or fragment, as illustrated by the following sample code:
class MyViewModel : ViewModel() {
private val users: MutableLiveData<List<User>> by lazy {
MutableLiveData<List<User>>().also {
loadUsers()
}
}
fun getUsers(): LiveData<List<User>> {
return users
}
private fun loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
for more information see this :
(https://developer.android.com/topic/libraries/architecture/viewmodel?msclkid=bf393d12ce9011eca291710e2d69c5af)

How to use any of i18n packages in nestjs mvc?

I found this package nest-18n but that dudes thinks that nestjs is only used for api and not mvc.
So sure ?lang=en or ?lang=de works and it changes language but question is how to use that on view?
My first thought was that this is working out of the box with __("Something to translate"). But that will not work (__ is undefined).
Since i18Service.translate method is async you can not add it to view (there is pug then but that is horrible idea). Idea of adding anything on the the view that is async does not make sense at all. So in principle they made package that can not be used outside of api's.
Other thing that i can do is to have something like
class AppController extends BaseController() {
#Get("/")
index() {
return {
someTranslation: await this.getTranslation("give me something to translate"),
// IMAGINE NOW Having 1000 OF TRANSLATION ON INDEX PAGE
}
}
}
where BaseController is:
class BaseController() {
constructor(private readonly i18n: I18nService, lang: string) {
}
async protected getTranslation(stringToTranslate: string) {
return await this.i18n(stringToTranslate, {lang});
}
}
Does anyone have idea how to use any of i18n in nestjs mvc?

Association is in database, but can't be retrieved via DAL. Will retrieve empty array of associations

I am following the advanced developer tutorial (https://docs.shopware.com/en/shopware-platform-dev-en/how-to/indepth-guide-bundle).
Currently I'm at step 7, and according to the tutorial what I've made so far should work.
But it doesn't.
In the database it shows the association, but I can't retrieve them from the repository.
You have to add the association to the Criteria.
$criteria->addAssociation("name_of_association")
Without it, the associations come as null.
Okay, turns out I switched up two parameters by accident. When I set them correctly it worked as it should.
<?php declare(strict_types=1);
namespace Swag\BundleExample\Core\Content\Product;
use Shopware\Core\Content\Product\ProductDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\EntityExtension;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\Inherited;
use Shopware\Core\Framework\DataAbstractionLayer\Field\ManyToManyAssociationField;
use Shopware\Core\Framework\DataAbstractionLayer\FieldCollection;
use Swag\BundleExample\Core\Content\Bundle\Aggregate\BundleProduct\BundleProductDefinition;
use Swag\BundleExample\Core\Content\Bundle\BundleDefinition;
class ProductExtension extends EntityExtension
{
public function extendFields(FieldCollection $collection): void
{
$collection->add(
(new ManyToManyAssociationField(
'bundles',
BundleDefinition::class,
BundleProductDefinition::class,
'product_id',
'bundle_id'
))->addFlags(new Inherited())
);
}
public function getDefinitionClass(): string
{
return ProductDefinition::class;
}
}
I'm talking about the 'product_id' and 'bundle_id'. In my case I had the 'product_id' as the last parameter.

Dependency injection php

I have built a simple dependency injection container that I pass around my classes that need it, everything works and all is good.
My question is that say I have 2 classes such as
class A {
public function __construct() {
}
}
class B {
public function __construct(A $a) {
}
}
Should I enforce the typehinting in the class itself or in the injection container such as;
$di->set('A', function() {
return new A();
});
$di->set('B', function(A $a) {
return new B($a);
});
Should I do both or either/or.
For answers why is it better to use one over the other etc?
Thanks.
I would use the first case, enforce the type hinting in the class itself.
This will make it clear for readers of the code what are the actual dependencies of the class.
If you decide to change the DI container (or hypothetically remove it) or reuse the classes in other project, it is good to have the type hinting in the class itself.
The DI container is there simply to help you manage dependencies.

Resources