drupal view2 views_query_alter for JOIN - php

i'm trying to alter drupal view-2 query, basically want to add one more table. I'm able to alter the where clause of query using hook_views_query_alter() but don't know how to join one more table.
function module_views_query_alter(&$view, &$query) {
if ($view->name == 'view1_name') {
$query->where[0]['args'][] = 'SOMETEXT';
$query->where[0]['clauses'][] = "QUERY";
}
if($view->name = 'view2_name'){
$query->table_queue['content_type_sold_product'];
$query->tables['content_type_sold_product'];
}
}
Why do i want to do this - if relationship tab is available in view that is used to join the table, but in my case table which i want to join contains the field that is not a node-reference however field name and its value matches with one of the view table table.
Does anyone know how to perform JOIN in views_query_alter().

Seems there are two different ways you can do this, see these links:
Adding a JOIN statement in hook_views_query_alter()
Add Table Join, Where, and Order By to Views Query in views_query_alter()

Giving Answer to own question
fortunately i found these links
http://drupalmodules.com/module/reverse-node-reference module enhances views with reverse relationships for node reference fields.
you may also need http://drupal.org/project/noderelationships

Related

Show if group has access to certain forms

I'm trying to understand how to write a query to distinguish if a user has access to certain form or not. I know what I am asking here looks easy but when I tried to implement it, it was whole different thing.
Maybe I am doing it wrong.
Before starting I want to mention the two tables names in start:
sys_forms,
sys_forms_in_groups
Also I am putting a SQL Fiddle link at the end.
Here is what I am trying to do.
If you can see the picture, on top dropdown box (it's a select2 dropdown), user selects the group and it will return GroupID, on the base of which I want to populated the below datatable. (DataTable is just showing groups, it's a dummy, but it will show forms, will fix it if problem is solved)
Now here the problem arise:
I want datatables to show all the forms available in sys_forms table in datatables but in actions columns of datatables only those checkboxes/switches should show granted which are available in the selected group(Group can be selected for select2 dropdown as said before).
GroupID is the column of other table sys_forms_in_groups.
All I want is that all the forms should show in the datatables no matter what group I choose, but Actions column in table should display Granted if the group has access to that particular form.
forms_in_groups is for showing if group has access to that certain form or not. For example:
FormID GroupID
------------------------------
1 1
2 1
1 2
FormID 1 is available to both groupID 1 and 2, on other hand FormID 2 is avaialable only to GroupID 1.
Here is my SQL Fiddle.
Edit
The SQL Fiddle is not working, so putting screenshots here.
Table : sys_forms
Table : sys_forms_in_groups
I have tried this query, but it only returns forms for the selected group, where I want that all forms should show but they must show granted in Actions Columns on checkboxes/switchButtons
SELECT * FROM (`sys_forms`) INNER JOIN `sys_forms_in_groups`
ON `sys_forms_in_groups`.`FormID` = `sys_forms`.`FormID` WHERE `GroupID` = 1;
I think you're, incorrectly, trying to offload the issue onto MySQL.
It's not MySQL's job to render the forms and show whether a selected group has access to a specific form. That will fall onto your rendering of the page; using Select2 in this case.
You just want to retrieve all forms, then show whether the selected group has access to a specific form. That comes down to some Javascript that makes that check for you and displays it properly.
If you want to return all forms, the query would be:
SELECT * FROM (`sys_forms`) INNER JOIN `sys_forms_in_groups`
ON `sys_forms_in_groups`.`FormID` = `sys_forms`.`FormID`;
If you only want the forms that group 1 has access to, the query would be just as you have it:
SELECT * FROM (`sys_forms`) INNER JOIN `sys_forms_in_groups`
ON `sys_forms_in_groups`.`FormID` = `sys_forms`.`FormID` WHERE `GroupID` = 1;
I didn't do a lot of digging into Select2, so I can't really help you in that aspect.
What I can see from your database schema, an inner join is the correct choice here based on the data you are looking for. The only issue I can see is in the WHERE clause. Seems that it may try to look for GroupID in the sys_forms table, so try specifying.
SELECT * FROM (`sys_forms`) INNER JOIN `sys_forms_in_groups`
ON `sys_forms_in_groups`.`FormID` = `sys_forms`.`FormID` WHERE
`sys_forms_in_groups`.`GroupID` = 1;
Finally Problem Solved and working perfectly fine, but after solving that problem i found out there is an other issue i didnt think of, but thats another matter. xD.
However, It was a little rough way to solve but i got what i wanted.
Here is how i did it,
I first needed to update my select query to,
SELECT f.FormID
, f.FormName
, f.FormCIPath
, MAX(g.IsMenuLink) AS IsMenuLink
, GROUP_CONCAT(DISTINCT g.GroupID ORDER BY g.GroupID) AS GroupIDs
FROM `sys_forms` f
JOIN `sys_forms_in_groups` g
ON g.FormID = f.FormID
AND g.GroupID IN (1,2)
GROUP BY f.formID
Here you can see it will return all the forms which belongs to group 1 and group 2 but in a way that 1 and 2 will be in same column separated by comma.
Here how it shows now.
I am not a very complex query master so i am very much grateful to stackoverflow community to help me with the query. As i wanted to join both results to show in comma separated value.
After the MysQL the jquery work was not much difficult, i only sent the group ID for which i wanted the result to show in table. and there i got this result in return where i separate the GroupIDs with javascript split function and i get my groups.
Thankyou again everyone.

Performing Searches with Dynamic Filters and Dynamic Joins in Yii

I'm having issues performing a query and have not found anything that suited my situation, so here is my scenario.
I'm displaying a dataTable with information and have multiple filters that I can apply.
So far, so good.
The issue now is that I have to implement something like dynamic filters, meaning:
The user presses a button that says "Add Filter"(he can press it as
many times as he wants to add multiple filters).
When he presses that button, a div element appears with 2 elements inside.
A dropdown list and an input box.
The user can select the field he wants to search on the dropdown list
and writes the value he wants to be searched in the input.
He presses "Search" and the query is performed.
Lets say that in the dropwdown list the user chooses the option "Company" and in the search field he writes "foo bar".
In the controller, I detect that the option "Company" was selected. The thing is, "Company" is not in the main table I'm searching, it is for example, 2 relationships away. As it is also possible to export data from that table, I'm doing LEFT JOINS, but am having dificulty binding the params.
I've tried multiple things, I am currently:
//this initial query is always performed
$test_query = 'SELETC a.*
FROM tableA a
LEFT JOIN TableB b ON b.name = a.name
';
$whereTxt = "<some_other_where_conditions>";
$bindParam[':some_field'] = $_POST["field_value"] //this $_POST is here only for better understanding, I don't actualy have the untreated value here.
Now, if "company" filter was detected in the dropdownlist:
if($company_filter){
$test_query .= 'LEFT JOIN relation_table1 t1 ON a.team_id = t1.id
LEFT JOIN relation_table2 t2 ON t1.company_id = t2.id';
$whereTxt .= " AND retaion_table2.company_name LIKE :company_name";
$bindParam[':company_name'] = "% ".$_POST["company_name"]." %";
}
The issue is here
How do I wrap this all up?
I tried:
$list = $this->getDBConnection()->createCommand($test_query)->where($whereTxt, $bindParam)->queryAll();
Fails, the where parameter isn't even considered in the query execution
If tried other variations but the outcome is the same, the params are unbinded or the query fails.
Ideally, I would have:
$list = $this->getDBConnection()->createCommand()
->select("a.*")
->from('tableA a')
->leftjoin('regular_join')
->leftJoin('other_regular_join')
->where($whereTxt, $bindParam)
->queryAll();
But this way, I cannot add
->leftJoin(...)
dynamically corect? Which I really have to because of the filters the user might/might not have selected.
tl;dr
using getDBConnection()->createCommand() I need to insert LeftJoins dynamically depending on what the user chooses in the search filters, binding where parameters and arguments
I am aware that what I'm trying to achieve may not be clear, so apologies if I couldn't make myself understand.
Don't know why I was so confused.
Instead of binding the where params I just appened the where to the query itself and then binded the values after, ending up with something like:
$test_query= 'SELECT a.* FROM ....';
if($company_filter){
$test_query .= 'LEFT JOIN relation_table1 t1 ON a.team_id = t1.id
LEFT JOIN relation_table2 t2 ON t1.company_id = t2.id';
$whereTxt .= " AND relation_table2.company_name LIKE :company_name";
$bindParam[':company_name'] = "%".$_POST["company_name"]."%";
}
$list = $this->getDBConnection()->createCommand($test_query." WHERE ".$whereTxt)->bindValues($bindParam)->queryAll();
Also, kudos to dgtal#Yii forum

Doctrine2 - select from multiple tables with no direct relations

This question is about selecting data from multiple tables, joins, Doctrine2, ResultSetMapping, DQL and such stuff.
I have 4 tables:
user
contact
contact_phone
call
With relations as shown on the image: http://i.stack.imgur.com/762Jw.png
Every user can have many contacts, each contact can have many phones and each user can have many calls to/from his contacts. Just like in the real world... I've limited the number of fields in each table just for clarity.
So my problem is that I don't know how exactly to map call numbers to contact names when showing a list of calls for a specific user.
If I want to list all calls of user 1 I do:
$callRepository = $this->getDoctrine()->getRepository('MyBundle:Call');
$calls = $callRepository->findAll(array('user' => 1));
But this will give me just the list of all calls for this user and will not associate number (call.number) with names (contact.name).
I can achieve what I want with plain SQL with this query:
SELECT
c.number,
contact.name
FROM
`call` c
JOIN contact_phone cp ON
cp.number = c.number
JOIN contact ON
contact.id = cp.contact_id
WHERE
c.user_id = contact.user_id
AND c.user_id = 1
Please note that I don't want to select all calls (with SQL) and then map numbers to names with another query from the PHP layer because this way I won't be able to search the calls by name for example.
I was thinking that ResultSetMapping could help me in this case but I have no luck putting the SQL query and the ResultSetMapping together.
Please help,
Thanks!
As per my knowledge, you can acheive by using the below methods. Please go to bottom of the page. you can find Joins... try once..
http://docs.doctrine-project.org/projects/doctrine1/en/latest/en/manual/dql-doctrine-query-language.html

Codeigniter count number of articles in one category while listing categories

I have some problem while listing categories from database.
First i have a table called "Videos" where i store som videos-information like v_name, v_description and category_name.
In the second table called "Categories" where i store categories-information like c_name and c_description.
OFC i have id's in every table :)
But now i want to list the categories and in the same query count every videoitem in every category.
This is the code and i can't figure out how to do in the model now and later how to show the numbers in the view file, so pleace help me!
Thanks for your time and support :D
$this->db->select('c.*');
$this->db->from('categories as c');
$this->db->join('videos as v', 'c.c_name = v.v_category', 'right');
return $this->db->get()->result_array();
For your code to work you need two changes:
First you join type should be a "left join". Than way you still will get a count result (0) even if a category has no videos yet.
Second you need to group your results to be able to use the aggregate function count().
Try with this:
$this->db
->select('categories.c_name, COUNT(videos.id) as num_videos')
->from('categories')
->join('videos', 'categories.c_name = videos.v_category', 'left')
->group_by('categories.c_name');
Also you should reconsider your DB design. If you have id columns in both tables (wich I assume are the primary key) then you should define the relationship between the tables (foreign keys) using the id column, not the name.

Temporary Table and Left Joins not showing results as expected

I'm really hoping someone can help me with this. I have a number of product attribute types that users can select from to refine the products that are returned to them on screen. What I'm trying to do is, for each product attribute type, I want to list all attributes that relate to either the selected category or search term, then once they've made their selections, I still want to display each of the attributes that relate to the category or search term, but only display a clickable link if the product count for that particular attribute is greater than 1 and for those that have a product count of zero, I want to list them, but make them unclickable. An example of what I'm trying to achieve can be found on the ASOS website, in the left hand menu
http://www.asos.com/Women/Dresses/Cat/pgecategory.aspx?cid=8799#state=Rf961%3D3340%2C3341%40Rf-200%3D20&parentID=Rf-300&pge=0&pgeSize=20&sort=-1
Initially I tried using just joins to achieve this, but I wasn't able to do it, successfully. So I decided to create a temporary table for each attribute type which held a list of all the attributes that related to the main query and then created a refined query, with a left join. Here's my code:
CREATE TEMPORARY TABLE temp_table
SELECT su_types.id, type AS item FROM su_types
INNER JOIN su_typerefs ON su_types.id=su_typerefs.id
INNER JOIN su_pref ON su_typerefs.mykey = su_pref.mykey
WHERE wp_category_id =40 GROUP BY su_typerefs.id
$sudb->query($query);
if ($sudb->affected_rows > 0) {
SELECT temp_table.id,item,COUNT(su_typerefs.mykey) AS product_count FROM temp_table
LEFT JOIN su_typerefs ON temp_table.id=su_typerefs.id
LEFT JOIN su_pref ON su_typerefs.mykey = su_pref.mykey
LEFT JOIN su_stylerefs ON su_pref.mykey = su_stylerefs.mykey
LEFT JOIN su_productrefs ON su_pref.mykey = su_productrefs.mykey
WHERE wp_category_id =40 AND su_stylerefs.id in (91) AND su_productrefs.id in (54) AND su_typerefs.id in (159) GROUP BY su_typerefs.id
if ($itemresults = $sudb->query($query)) {
while($itemresult = $itemresults->fetch_array(MYSQLI_ASSOC)) {
$id=$itemresult['id'];
$item=$itemresult['item'];
$product_count=$itemresult['product_count'];
build_link($list_type, $item, $product_count, $id);
}
}
In the above example the first query selects all the product types that relate to a particular category, say dresses. And the second query is based on the refinements the user has made on the category, in this example this is product, product type and style. A user can also refine their search by colour, fit, fabric and design.
There are a couple of issues with this:
1) The number of results returned in the second query do not match the results of the first. Using the above as an example, I wish to list all products that relate to the chosen category, then using the second query return the product count for each of these products as I described above. So if the temporary table returns, trousers, jeans and skirts. I expected these three items to be displayed on screen based on the conditions applied in the second query, however my results may only show trousers and jeans, if there is not a match for skirts in the second query. I thought that using a left join would mean that all the results of the temporary table would be displayed.
2)Also I wonder if I'm doing this the most efficient way. I have a total of 8 attribute groups, and therefore need to do the above 8 times. If the user choses to refine the results using all 8 attribute groups then in addition to the temp table join, there will be a total of 9 joins for each type. It's taking a while to execute, is there a better way to do this? There are approximately 1/2 million products in the table, and this will probably be 5 times this, once my site goes live.
I really hope all that I have written makes sense and I'd really appreciate the stackoverflow community's help with this, if anyone can help. I apologise for the essay ;). Thanks in advance
To answer your first question; yes, a LEFT JOIN will indeed keep all data from the initial table. That, however, isn't the problem.
The reason why you lose empty categories, is most likely (I say this because I don't fully know your db structure) because of the where condition filtering out all results based on the data in the joined tables.
If for a category all items get filtered out (possibly including the NULL joined values), you will not get this category back from that query anymore. Also the GROUP BY is done on a joined column, that might also effectively wipe out your other categories.
As for the second question, you already state it's taking long; so it's probably not the way to go if you want things to work fast ;) (okay, obvious answer, low hanging fruit, etc). What you might want to do, is get a collection of keys from the filterable categories first, and use that data to select items.
This prevents that you have to join up your entire products table in a temp table (at least, that's what I think you're doing), which of course will take long with the given number of entries. Selecting a list of matching IDs from the given attributes also gives you the advance of using your indexes (more), which a temp-table probably won't have. If this is possible and feasible mainly depends on your schema's structure; but I hope it might lead you to the direction you want to go :)

Categories