How to use INSTR with Kohana ORM? - kohana

I need to make changes to some old system made with framework kohana (ver. 3.1.1.1), an input where the user must write at least part of the name and the system must output the results.
Usually I work with PHP where I can do it easily with:
INSTR(my_table, 'some value') > 0 OR INSTR(my_other_table, 'some value') > 0
I saw some kohana orm syntaxis like:
$temp = ORM::factory('table_name')->where('column1','=',$value1)->and_where('column2','=',$value2)->find();
But I dont know the syntaxis to achieve my INSTR query using the kohana orm.
Can anybody help me?
Thank you all.

$temp = ORM::factory('table_name')->where('column1','=',$value1)->and_where('column2','=',$value2)->find()
is a bad practice, create model methods with queries.
use DB::expr():
$expression = DB::expr('COUNT(users.id)');
$query = DB::update('users')->set(array('login_count' => DB::expr('login_count + 1')))->where('id', '=', $id);
$users = ORM::factory('user')->where(DB::expr("BINARY `hash`"), '=', $hash)->find();

Related

Filter resources by template variable value with MODx Wayfinder

I have a site that uses Wayfinder to display the latest 3 entries from an Articles blog. Now, I want to only consider those blog entries that are tagged Highlights.
My original Wayfinder call looks like this, nothing spectacular:
[[!Wayfinder? &startId=`296` &level=`1`
&outerTpl=`emptyTpl`
&innerTpl=``
&rowTpl=`thumbnails_formatter`
&ignoreHidden=`1`
&sortBy=`menuindex`
&sortOrder=`DESC`
&limit=`3`
&cacheResults=`0`
]]
as Articles tags are managed via the articlestags TV, I thought that a &where might do the trick, but with no luck yet:
&where=`[{"articlestags:LIKE":"%Highlights%"}]`
does not yield anything. As a sanity check, I tried [{"pagetitle:LIKE":"%something%"}], which worked. Obviously, the problem is that articlestags is not a column of modx_site_content, but I'm not sure about how to put the subquery.
SELECT contentid
FROM modx_site_tmplvar_contentvalues
WHERE tmplvarid=17
AND value LIKE '%Highlights%'
Gave me the right IDs on the sql prompt, but adding it to the Wayfinder call like this gave an empty result again:
&where=`["id IN (SELECT contentid FROM modx_site_tmplvar_contentvalues WHERE tmplvarid=17 AND value LIKE '%Highlights%')"]`
Any ideas on how to achieve this? I'd like to stay with Wayfinder for consistency, but other solutions are welcome as well.
You can just use pdomenu (part of pdoTools) instead Wayfinder
[[!PdoMenu?
&startId=`296`
&level=`1`
&outerTpl=`emptyTpl`
&innerTpl=``
&rowTpl=`thumbnails_formatter`
&ignoreHidden=`1`
&sortBy=`menuindex`
&sortOrder=`DESC`
&limit=`3`
&cacheResults=`0`
&includeTVs=`articlestags`
&where=`[{"TVarticlestags.value:LIKE":"%filter%"}]`
]]
Take a peek at some of the config files [core/components/wayfinder/configs ] - I have not tried it, but it looks as if you can run your select query right in the config & pass the tmplvarid array to the $where variable.
A little playing around led me to a solution: I needed to include the class name (not table name) when referring to the ID:
&where=`["modResource.id IN (SELECT contentid FROM modx_site_tmplvar_contentvalues WHERE tmplvarid=17 AND value LIKE '%Highlights%')"]`
a small test showed that even a simple
&where=`["id = 123"]`
does not work without modResource..
A look at wayfinder.class.php shows the following line, which seems to be the "culprit":
$c->select($this->modx->getSelectColumns('modResource','modResource'));
This method aliases the selected columns - relevant code is in xpdoobject.class.php. The first parameter is the class name, the second a table alias. The effect is that the query selects id AS modResource.id, and so on.
EDIT: final version of my query:
&where=`["modResource.id IN (
SELECT val.contentid
FROM modx_site_tmplvars AS tv
JOIN modx_site_tmplvar_contentvalues AS val
ON tv.id = val.tmplvarid
WHERE tv.name = 'articlestags' AND (
val.value = 'Highlights'
OR val.value LIKE 'Highlights,%'
OR val.value LIKE '%,Highlights'
OR val.value LIKE '%,Highlights,%'
)
)"]`
I don't claim this query is particularly efficient (I seem to recall that OR conditions are bad). Also, MODx won't work with this one if the newlines aren't stripped out. Still, I prefer to publish the query in its well-formatted form.
I used snippet as a parameter for the includeDocs of wayfinder, In my case it was useful because I was need different resources in menu depend on user browser (mobile or desktop)
[[!Wayfinder?
&startId=`4`
&level=`1`
&includeDocs=`[[!menu_docs?&startId=`4`]]`
&outerTpl=`home_menu_outer`
&rowTpl=`menu_row`
]]
and then menu_docs snippet
<?php
if (empty ($startId))
return;
if (!isMobileDevice())
return;
$query = $modx->newQuery('modResource');
$query->innerJoin('modTemplateVarResource','TemplateVarResources');
$query->where(array(
'TemplateVarResources.tmplvarid' => 3,
'TemplateVarResources.value:LIKE' => 'yes',
'modResource.parent' => $startId,
'modResource.deleted' => 0,
'modResource.published' => 1,
'modResource.hidemenu' => 0
));
$resources = $modx->getCollection('modResource', $query);
$ouput = array();
foreach ($resources as $resource)
$output[] = $resource->get('id');
return implode (',', $output);

Kohana 3 cross-table update using Query builder

What is the proper way to construct a cross-table update in Kohana 3 using the DB query builder?
Currently I am just using a DB::expr but I know the query builder is smarter than that.
// update record
$rows_updated = DB::update(DB::expr('user_list_permissions INNER JOIN users ON user_list_permissions.user_id = users.id'))
->set($params)
->where('user_list_permissions.id', '=', $user_list_permission_id)
->where('users.account_id', '=', $this->account_id)
->execute();
And yes of course I tried using the "join" method like when building SELECT queries, but I receive an error:
ErrorException [ 1 ]: Call to undefined method Database_Query_Builder_Update::join()
So you are using the expression to do the join, it is possible to use the built in 'join' function on the 'on' function to achieve this behavior.
So in your example it would look something like:
$rows_updated = DB::update('user_list_permissions')
->join('users','INNER')
->on('user_list_permissions.user_id','=','users.id')
->set($params)
->where('user_list_permissions.id', '=', $user_list_permission_id)
->where('users.account_id', '=', $this->account_id)
->execute();
There isn't much on it but the docs do have a little bit at http://kohanaframework.org/3.2/guide/database/query/builder#joins
It's an old post but just to keep the record of my experiences in Kohana.
If you are using MySQL, it lets you to make the cross-table update avoiding the use of join as follow:
UPDATE table1, table2
SET table1.some_field = 'some_value'
WHERE table1.foreign_key = table2.primary_key AND table2.other_field = 'other_value'
Note that condition table1.foreign_key = table2.primary_key is the same you used in ON clause with JOIN. So you can write a cross-table update in Kohana follow that pattern avoiding the JOIN:
$rows_updated = DB::update(DB::expr('user_list_permissions, users'))
->set($params)
->where('user_list_permissions.user_id', '=', DB::expr('users.id'))
->where('user_list_permissions.id', '=', $user_list_permission_id)
->where('users.account_id', '=', $this->account_id)
->execute();

expressionengine database class orderby and sort

How do we sort using the database class in expressionengine. orderby and sort are given an error and do not seem to work. I can't seem to find anything in the documantation about sorting results. This is what i have.
$results = $this->EE->db->query("
SELECT plan_name
FROM exp__plans
WHERE member_id='1002' AND orderby="id" sort="desc" LIMIT 1
");
$x = $results->row('plan_name')
;
There are issues with your query.
try:
$results = $this->EE->db->query("
SELECT plan_name
FROM exp_plans
WHERE member_id = '1002'
ORDER BY id DESC LIMIT 1
");
I would recommend trying to run your query directly against the database if you're having trouble with it. 90% of the time it will be an issue with your SQL.
Also, you are writing this in a add-on... right? if you're trying to get this to work within a template I would recommend checking out the query module.
You can also use Active Record in order to create your query:
$this->EE->db->select('plan_name')
->from('plans')
->where('member_id', '1002')
->order_by("id", "desc")
->limit(1)
->get();
All the doc is on the Codeigniter website.

Kohana 3.2 ORM Does not contain model info

I'm working with Kohana 3.2 and have the following code in my controller.
$Blog_Post = new Model_Blogpost();
$Blog_Post->where('id', '=', 1);
$Blog_Post->find();
$content = $Blog_Post->content;
I Currently have 3 records in my db with id's 1, 2, and 3.
$Blog_Post->content, or any other field return null. and I'm not sure why.
Use ORM::factory('blogpost', $id) or new Model_Blogpost($id) if you need an object with PK == $id.
Check your model after loading.
if $Blog_Post->loaded()
{
// it works!
}
else
{
// record not found
}
If record not found, you can see last DB query with $Blog_Post->last_query()
UPD. From comments. Your model will not work with this modifications. Note that ORM data stored in $_object property, and $Blog_Post->content is just a shortcut for $Blog_Post->_object['content'] via __get() method. Of course, if you define public $content property, $Blog_Post->content will return NULL value instead of using DB data.
There is no reason for defining model fields as properties. If you need IDE hints, just use PHPDOC.
At the firm I work for we were looking into upgrading to 3.2 very recently. However, in our evaluation I don't recall seeing a difference in ORM handling methods.
Yours above looks like it should be something like this:
$Blog_Post = ORM::factory('blogpost')->where('id', '=', 1)->find();
$content = $Blog_Post->content;
Assuming your table is called blogposts, of course. I may be wrong about that and if I am, can you link to the documentation that shows this kind of model interaction?

Subsonic Delete multiple records

I have a table which has a two fields, userid and degreeid. A user can have multiple degreeds in this table. When a user select their degree I want to delete any degree id already in the database but un-selected by user. How should do it? I try to use something like this with no luck.
repo.DeleteMany(x=>x.MeetingAttendeeUserID==userID && x.EducationDegreeID userDegreeList)
Thanks,
Lewis
Could you do something like this?
repo.DeleteMany(x =>
x.MeetingAttendeeUserId == userID &&
x.EducationDegreeID != selectedDegreeId
);
Edit: Or this.
repo.DeleteMany(x =>
x.MeetingAttendeeUserId == userID &&
userDegreeList.Contains(x.EducationDegreeID))
);
I have tried
SubSonicRepository<ReportDatum> repo = new SubSonicRepository<ReportDatum>(db);
repo.DeleteMany(x => x.ReportID == Convert.ToInt32(reportID));
and it does nothing, not even an error.
Addendum for someone that comes across this:
don't convert in the delete call, convert your variables beforehand.
int deleteKey = Convert.ToInt32(reportID)
SubSonicRepository<ReportDatum> repo = new SubSonicRepository<ReportDatum>(db);
repo.DeleteMany(x => x.ReportID == deleteKey);
and it fired fine.
I would recommend if you dont know Lamda expression. Create your own stored procedure and call use it.
This will not restrict you using lamda expression if you don't have time to learn it.
Ultimately you wanted to done your job.

Resources