Lithium Model find query with <> operator - lithium

I'm trying to fetch rows excluding the one which already are in an other table :
| Content | ContentSelected
| –––––––– | ––––––––––––––––––––––––-
| id | content_id | operation_id
| 1 | 1 | 9999
| 2 | 3 | 1000
| 3
=> 2,3
Here how I tried to run this query :
Content::find('all', array(
'joins' => array(new Query(array(
'source' => 'ContentSelected',
'constraints' => array('ContentSelected.operation_id' => 9999),
'conditions' => array(
'Content.id' => array('<>' => 'ContentSelected.content_id')
));
Here the SQL query run by the adapter :
SELECT * FROM "Content" AS "Content"
JOIN "ContentSelected" ON "ContentSelected"."operation_id" = 1
WHERE ("Content"."id" <> 0);
Is there another way to performed a query excluding results, or to force the adapter to write ContentSelected.content_id instead of 0 in the where clause ?
Thanks

You can use Model::connection()->read() to run a native sql in Li3. Check this out http://www.jblotus.com/2011/10/25/executing-raw-mysql-queries-in-lithium/
Content::connection()->read($your_sql);
But before using such a solution. Try to implement your model properly using Model Relationships (http://li3.me/docs/manual/models/relationships.md) so that you don't need to use a native query and let the model does the work for you.

Related

Prefix or append a string to meta_title, meta_key, meta_description in category page

Category page meta_title, meta_key and meta_description tags come from the table ps_category_lang.
mysql> select * from ps_category_lang limit 1;
+-------------+---------+---------+-------+-------------+--------------+------------+---------------+------------------+
| id_category | id_shop | id_lang | name | description | link_rewrite | meta_title | meta_keywords | meta_description |
+-------------+---------+---------+-------+-------------+--------------+------------+---------------+------------------+
| 1 | 1 | 1 | Raíz | | raiz | | | |
+-------------+---------+---------+-------+-------------+--------------+------------+---------------+------------------+
1 row in set (0.00 sec)
Is it possible to add a prefix (or suffix) to those three values, so it uses the information from the database but it appends or prefixs a certain value?
If so, what shall be needed to be done? I already have a custom module overriding the category page with extended template and controller.
Prestashop 1.7.1
The best way is by overriding the /classes/controller/FrontController.php, specifically the method getTemplateVarPage() in the code:
$page = array(
'title' => '',
'canonical' => $this->getCanonicalURL(),
'meta' => array(
'title' => $meta_tags['meta_title'],
'description' => $meta_tags['meta_description'],
'keywords' => $meta_tags['meta_keywords'],
'robots' => 'index',
),
'page_name' => $page_name,
'body_classes' => $body_classes,
'admin_notifications' => array(),
);
Here you could validate the current page and alterate it as your needs.
for each standard controller in PrestaShop, you have a dedicated function in the Meta class, in your case, the getCategoryMetas() function that you can override and adapt to fit your needs.
You also can use the previous answer to rewrite the metas firstly computed in the Meta::getCategoryMetas() in CategoryController::getTemplateVarPage() function.
Good luck

How to parse a SQL result and convert it to Ruby hash

I want to convert a SQL query result into a Ruby hash, where only two rows are shown and the first act as key and second as value. For example, if my query got this result:
+----+--------+
| id | name |
+--- +--------+
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | d |
| 5 | e |
+----+--------+
I want to manipulate this data to get a Ruby hash like this:
h = { '1' => 'a',
'2' => 'b'.
'3' => 'c',
'4' => 'd',
'5' => 'e' }
How can I get this done?
I use ruby Sequel in most of my non-rails projects. It's an excellent ORM for SQL databases.
Here is a code sample using SQLite (in memory):
#!/usr/bin/env ruby
require 'sequel'
# create db in memory
DB = Sequel.sqlite
# create table
DB.create_table :items do
primary_key :id
String :name
end
# Create a dataset
items = DB[:items]
# Populate the table
items.insert(:name => 'john')
items.insert(:name => 'mike')
items.insert(:name => 'nick')
puts "#{items.all}"
# => [{:id=>1, :name=>"john"}, {:id=>2, :name=>"mike"}, {:id=>3, :name=>"nick"}]
# initialize hash object
h = {}
# Create the hash in the form you want
items.all.each do |entry|
h[entry[:id]]= entry[:name]
end
# p the hash
p h # => {1=>"john", 2=>"mike", 3=>"nick"}
NOTE: Sequel is extremely powerful. There might be a method to do what you what you want directly, without passing the data through the loop. However, you'll have to read the documentation to find out if you need to clean your code.
Hope this helps!
UPDATE: So here is the updated code after Jeremy Evan's (author of Sequel):
#!/usr/bin/env ruby
require 'sequel'
# create db in memory
DB = Sequel.sqlite
# create table
DB.create_table :items do
primary_key :id
String :name
end
# Create a dataset
items = DB[:items]
# Populate the table
items.insert(:name => 'john')
items.insert(:name => 'mike')
items.insert(:name => 'nick')
# Return hash of items
p items.select_hash(:id, :name) # => {1=>"john", 2=>"mike", 3=>"nick"}

Find matching tag items in table from string array using linq

I have a SQL table of tags like this:
Id | Tag
-----------------
1 | car
1 | red
1 | sport
2 | car
2 | red
2 | SUV
And I want to retrieve ONLY the ID for exact matching search strings. So, using LINQ, I'd like to query for:
"car,red"
and have it return: 1 and 2.
Then searching for "car,red,sport" would return 1 only.
I'm not sure at all how to do this using LINQ. If I do the following (using EF context and table as example):
string[] tags = {"car","red","sport"}
var query = context.CarTags.Where(a => tags.Contains(a.Tag)).Select(s=>s);
...will of course return both 1 & 2.
So, how do I do this using LINQ?
string[] tags = {"car","red","sport"}
var query = context.CarTags
.GroupBy(a => a.Id)
.Where(g => tags.All(t => g.Any(a => a.Tag == t)))
.Select(g => g.Key);
I'm not sure if it's gonna work with LINQ to Entites, but would definitely give it a try.
All methods used are listed as supported within Supported and Unsupported LINQ Methods (LINQ to Entities) list, so should work. But even if it is, I would probably check the generated SQL to make sure it's not over-complicated and not very effective.

Grouped aggregations with Yii STAT?

I have a Yii STAT Relation that's defined to provide a grouped SUM result, however when I access the relation in my View, the only value is the latest single value rather than each value.
For example, here's my relation:
'total_salaries_by_job' => array(
self::STAT,
'Employee',
'department_id',
'select' => 'job_type_id, SUM(salary)',
'group'=>"job_type_id"
)
This generates the following SQL:
SELECT
department_id AS c
, job_type_id
, SUM(salary) AS s
FROM Employee AS t
WHERE t.department_id = 1
GROUP BY
department_id
, job_type_id
Running that manually, the result set is:
c | job_type_id | s
------+----------------+---------
1 | 1 | 233000
------+----------------+---------
1 | 2 | 25000
------+----------------+---------
1 | 3 | 179000
However, in my view, if I do the following:
<pre>
<?php print_r($department->total_salaries_by_job); ?>
</pre>
The result is simply: 179000, whereas I was expecting it to be an array with 3 elements.
Is returning just 1 value the way STAT relations work or is there something else I need to be doing?
Is it possible to do what I'm attempting?
You can do what you are after, but you can't use a STAT relationship to do it. Rather, use a Normal HAS_MANY relationship and use your same select statement.

Why does MySQL return duplicate information in the returned JOIN array?

I'm wondering if I'm doing something wrong, or if this is just a quirk in how everything is processed in MySQL. Here's the setup: (I can't seem to find this exact topic anywhere else)
I have two tables order and menu.
menu has an 'id' (for the item), an 'item' and three prices ('prc1' 'prc2' 'prc3') in each row.
menu +----+----------+------+------+------+
|'id'| 'item' |'prc1'|'prc2'|'prc3'|
+----+----------+------+------+------+
| 1 | 'tshirt' | 3.00 | 4.50 | 4.00 |
| 2 | 'socks' | 1.00 | 2.50 | 2.00 |
+----+----------+------+------+------+
order also has an item id to match against the order menu, ('i_id'), and an integer I use for filtering the prices later in php ('prc_id').
order +------+--------+
|'i_id'|'prc_id'|
+--------+------+
| 1 | 1 | # i_id matches id - tshirt and informs to use prc1
| 2 | 3 | # i_id matchis id - socks and uses prc3
+--------+------+
I use JOIN to match the orders up to the items
"SELECT order.prc_id, menu.item, menu.prc1, menu.prc2, menu.prc3
FROM order
LEFT JOIN menu
ON order.i_id = menu.id"
I then get the result back, and initially to make sure everything panned out, I printed the array:
$result = mysql_query($query)
while($row = mysql_fetch_array($result))
{
print_r($row);
}
This is the array I get back (obviously dummy info for the initial tests):
Array
(
[0] => 1 [prc_id] => 1 #the value (1) for 'prc_id' is given twice
[1] => tshirt [item] => tshirt #the value (tshirt) for 'item' is given twice
[2] => 3.00 [prc1] => 3.00 #the value (3.00) for 'prc1' is given twice
[3] => 4.50 [prc2] => 4.50 #etc
[4] => 4.00 [prc3] => 4.00
[0] => 3 [prc_id] => 3
[1] => socks [item] => socks
[2] => 1.00 [prc1] => 1.00
[3] => 2.50 [prc2] => 2.50
[4] => 2.00 [prc3] => 2.00
)
So my question(finally, right? xD)... Why is duplicate data sent back in the array response?
Have I done something wrong? Am I overlooking something?
It's not a huge issue, it doesn't affect my end result, I'd just like to be as precise as possible.
Thank you for your time. :)
If think this is a PHP print_r() problem.
print_r() return a numeric representation and the second the named store row.
EDIT:
Try your query with the Database Query Tool then you will see the original result.
SELECT order.prc_id, menu.item, menu.prc1, menu.prc2, menu.prc3
FROM order
LEFT JOIN menu
ON order.i_id = menu.id
It looks like you are joining based on the item_id in order and id of menu, while you should be doing based on (if I understand correctly) the item_id of menu.
Something like:
SELECT order.prc_id, menu.item, menu.prc1, menu.prc2, menu.prc3
FROM order
LEFT JOIN menu
ON order.i_id = menu.item_id