Redbean php multiple many-to-many relations to same table - php

Here is my situation: user have list of liked objects and list of disliked.
I want to act like this:
list($cat, $dog) = R::dispense('object', 2);
$user->sharedLikedobjectsList[] = $cat;
$user->sharedDislikedobjectsList[] = $dog;
But afterall RedbeanPhp creates single tabe (object_user) with 2 rows inside.
What shall I do to have 2 different tables and accessible properties on $user bean?

use $bean->link() method to create an alias name for your foreign key table.
such as this :
$user->link("pet",array("some_prop"=>"some_value"))->sharedPet = dog;

Related

How to access table in laravel using eloquent with is not directly attached

I have the following table structure and i want to access Portal which is assigned to specific case but using patient info. For example i have the following query
$data['patients'] = Patient::with('operator')->where('case_id', $case_id)->get();
this query returns the operator assigned to the patient now hare i want the portal name assigned to the patient using case.
Portal Table
id Name
1 A
2 B
Cases
id Name case_number patient_name user_id portal_id
1 Farz 456 sania 5 1
Patient
id case_id operator_id
2 456 5
Assuming you properly created the laravel relationships among Portal, Case, Patient and Operator models, you can access in this way:
// you get Case model
$case = \App\Case::findOrFail($case_id);
// patients: there is a hasMany relationship between Case and Patient models
$data['patients'] = $case->patients;
// there is a belongsTo relationship between Case and Portal models
$portal_name = $case->portal->Name;
You have to use another relationship
$data['patients'] = Patient::with('operator', 'cases.portal')
->get();
In Patient :
public function cases(){
return $this->hasMany(Case::class);
}
In Case :
public function portal(){
return $this->belongsTo(Portal::class);
}
then you can access it with :
foreach($data['patients'] as $patient){
foreach($patient->cases as case){
$var = $case->name;
}
}
or if you just want all portal names :
$portals_names = $data['patient'][0]->pluck('cases.portal.name')
Normaly, if you did the correct relations in your models, you can only use :
$data['patients'] = Patient::with('operator')->where('case_id', $case_id)->get();
$portals = [];
foreach ($data['patients'] as $patient) {
foreach ($patient->cases as $case) {
$portals []= $case->portal;
}
}
I suppose there is a HasMany between Patient and Cases, and a BelongTo between Cases and Portal ?
If you want to lazy load the data, you can try :
$data['patients'] = Patient::with(['operator', 'cases.portal'])->where('case_id', $case_id)->get();

GroceryCrud set a n-n relation with where clause

I have three tables (simplified) which are:
And I have to display all houses for each user.
In my controller I have a function like this:
public function create_houses_table($usr_id)
{
$crud = new grocery_CRUD();
$crud->set_language("italian");
$crud->set_theme('datatables');
$crud->set_subject('Casette');
$crud->set_table('tbl_houses');
$crud->set_relation_n_n('Casette',
'tbl_users_houses',
'tbl_users',
'house_id',
'user_id',
'usr_name',
NULL,
array('user_id' => $usr_id));
...
}
and what I get is this:
Every time I select a user from the combo I need to refresh my list filtering on usr_id...but I get always all the houses.
What I'm wrong?
This is not the intended usage for set_relation_n_n (it will show all the user houses in one field inside the user row).
What you want can be better done listing from tbl_users_houses, filtering by client with $crud->where() and linking with the other tables with two simple relations.
If I understand correctly you are trying to fetch only the records for the logged in User... and u have multiple users per house, hence the n-n relation.
I also faced this problem and here's what I did.
$myprojects = $this->admin_model->get_employee_projects($this->user_id);
$myprojectids = array_column($myprojects, 'id');
//get only one column from the multi-dimensional array
$crud->where("`projects`.id IN", "(" . implode(",", $myprojectids) . ")", false);
// the false disables escaping
$crud->set_relation_n_n('assigned_employees', 'project_employees', 'employees', 'project', 'employee', 'name');
//Only so it also still shows the name of Users assigned
So basically projects here is like houses, and I am using the WHERE IN clause to filter the records based on the projects I get from my model method...

Laravel: How to get single pivot row by key id

I have a many-to-many relation set on my User and Notification Eloquent models. This way I can access the pivot table - user_notifications - as follows:
$user = User::find(1);
foreach ($user->notifications() as $n) {
echo $n->pivot->created_at;
}
This will give me all created_at field values from the pivot table, for the user of ID = 1.
What if I need only one pivot row, let's say the one with notification_id = 2? Is there a way to combine pivot with where or has? Can it be done without looping through $user->notifications()?
You can use a where clause on the relationship:
$notification = $user->notifications()->where('notification_id', 2)->first();
echo $notification->pivot->created_at;
You can also directly use find method.
$notification = $user->notifications()->find(2);
echo $notification->pivot->created_at;
I've been dealing with this, and lukasgeiter's answer is fine, until the weird case where you want to find a pivot row by id (if you set up a $table->increments('id') column on the pivot table. I do this sometimes, but a better solution is to use a dedicated model for the relationship (Defining Custom Intermediate Table Models # https://laravel.com/docs/5.6/eloquent-relationships)
What you can do in this strange case:
$notification = $user->notifications()->having('pivot_id', 2)->first();
echo $notification->pivot->created_at;
You'll have to include withPivot('id') in your relationship method in the model. i.e.
function notifications() {
return $this->belongsToMany('App\Notification')->withPivot('id');
}

JOIN query that returns list of objects of different models?

So far I have this code:
$list = $this->modelsManager
->createBuilder()
->columns(array("SeriesList.*", "User.*", "Entry.*"))
->from("SeriesList")
->join("User")
->join("Entry")
->andWhere("SeriesList.id = '$id'")
->getQuery()
->execute();
Each row in the "Entry" database is an item that has a id, id of the series list it belongs to, its series id, and what type of series it is. The type of series specifies what table the series id can be found in.
The problem is that I want SeriesList(s) to may contain different types of objects. For example, the SeriesList "Favorites" may contain 3 shows and 4 books, Show and Book being different models which interface with separate tables.
Would I have to keep joining for all the models the list might contain? Or is there a better way?
The query builder will return a resultset which could be a model itself or a combined model (if you are doing joins etc.). It will not return objects of other models.
What you can do is use the getRelated() function to access the relationships from the base model itself.
So if your starting point is Entry then you could do something like this:
$entries = Entries::find();
foreach ($entries as $entry) {
// If series type is X
if ($entry->seriesType == 'x') {
$newItem = $entry->getRelated('x');
} else if ($entry->seriesType == 'y') {
$newItem = $entry->getRelated('y');
}
}
You can define relationships in your models that will cater for that. The key here is that Phalcon's relationships will relate data from table A to table B straight up and without any "filtering". So if you want to relate Entries to Favorites if SeriesList == 'favorite' you cannot, at least automatically. You will have to do that with code similar to the one above.

Counting number of articles within a category using CakePHP?

I have a simple cakephp app with table articles that has a cat_id column to reference a id column of categories in a cats table.
What I would like to do is display all categories names, each followed with a count of the number of articles belonging to that category.
I know there is a find('count') function in cakephp, but that only working on one table/field. How do I link the two tables to get a list of category names and count of articles for each category for my view?
Thanks
COme on! Use counterCache!
In table "cats" create field article_count. In Model write
/app/models/cat.php
class Cat extends AppModel
{
var $name = 'Cat';
var $belongsTo = array('Article'=>array('counterCache'=>true));
}
That's all! every time you add/remove from articles, it writes to cats table count of articles.
don't forget to include article_count into fields list
it might be better to do this in the afterFind callback on the model but can be done in the controller aswell.
$cats - $this->Cat->find('all',array('recursive'=>-1));
foreach($cats as $key=>$cat){
$cats[$key]['ArticleCount'] = $this->Cat->Article->find('count',array(
'conditions'=>array('Article.cat_id'=>$cat['Cat']['id']))
);
}
or see if this works
$cats = $this->Cat->find('all',array('contain'=>array(
'Article'=>array('fields'=>array('COUNT(*) AS ArticleCount')
)));
obviously you will need to add the containable behavior on the category model.
You could also use the countercache feature: http://book.cakephp.org/view/816/counterCache-Cache-your-count
You also might consider checking out counterCache to cache the count within a column value.
Thanks, this worked:
$cats = $this->Article->Cat->find('all',array('recursive'=>-1));
foreach($cats as $key=>$cat){
$cats[$key]['ArticleCount'] = $this->Article->find('count',array(
'conditions'=>array('Article.cat_id'=>$cat['Cat']['id']))
);
}

Categories