conditions in contain cakephp find - php

is it good or bad practice in CakePHP to have conditions set in the contain of a find query like:
$data = $this->SomeModel->find('all', array(
'contain' => array(
'AnotherModel' => array(
'conditions' => array(
// some conditions
)
)
)
));
In which cases will putting conditions inside a contain be useful, and when should I use it or not. Sorry, this is still confusing to me.
Thank you

I'm not sure whether this is a good idea... First of all, I'm going to assume that this specific case requires you to specify conditions that unique to this case, i.e. not general enough for you to put into your SomeModel model relationship criteria to AnotherModel.
My suggestions would be that you should put those conditions in your overall find conditions, as contain specifies which linked models to return (controlling the joins under the hood). Like in SQL, you can join another table and specify which records to match in your WHERE clause.
From the manual, you can specify conditions in your contain, but they won't affect the results that don't join your model like the overall conditions will.
I'd do this:
$data = $this->SomeModel->find('all', array(
'contain' => array('AnotherModel'),
'conditions' => array(
// some conditions relating to AnotherModel
)
));

Related

DataTables ssp.class.php (server processing) for PostgreSQL, add array support?

I have a converted ssp.class.php for PostgreSQL which works fine. However, I need to add ARRAY support to it.
I am hoping someone can give me some guidance/tips on the best way to do approach this, and/or give some example code if possible. I would appreciate it a lot.
You can get the modified file here: ssp.class.pg.php
About DataTables server side processing: https://datatables.net/examples/data_sources/server_side with an example.
I'm a little late to the party, but I found this question while searching google for an answer and wanted to post what I figured out to help the next person who might stumble upon this.
Note: I am using the referenced ssp.class.pg.php
My Solution - Use Heredoc
Using heredoc, you can better define your query using array functions, inner and outer joins, subqueries etc.
In my example, I have a PostgreSQL table that contains a jsonb column named properties. I want to select the value from the last_seen key.
Using Heredoc, I define my table as a query that will return the users last seen date value as a column.
$table = <<<EOT
(
SELECT
id,
unique_id,
properties->>'last_seen' as last_seen
FROM users
WHERE token = '$token'
) temp
EOT;
Then, I can define my columns for the SSP PG class using the returned columns from my table query.
$columns = array(
array( 'db' => 'id', 'dt' => 'id' ),
array( 'db' => 'unique_id', 'dt' => 'unique_id' ),
array( 'db' => 'last_seen', 'dt' => 'last_seen' ));
Finally, I'll use the defined variables to call the simple function.
$data_result = $ssp_pg->simple($request, $conn, $table, $primaryKey, $columns);

How to search in more than one column of the database using cakephp

Good morning,
I need some help in a survey, which I am not able to do.
Imagine a web application (php), which makes use cakephp.
In this application I have a search field, one normal input.
And imagine that this application has a table in the database with 3 fields, (produtoNome), (categoria), (tags).
how can this research below, I already search for table field (produtoNome).
$this->Anuncio->find('all',array('conditions' => array('produtoNome'=> array('$regex' => (string)$pesq))));
The question is:
How can I do a search, that search the 3 fields of the table not only one?
In other words, when someone types something into the search field, it will perform this search in more than one field of the table.
I tried this:
$produtos = $this->Anuncio->find('all',
array('conditions' =>
array('OR' =>
array(
array('produtoNome'=> array('$regex' => (string)$pesq)),
array('categoria'=> array('$regex' => (string)$pesq))
)
),
)
);
but does not work. Returns nothing.
$produtos = $this->Anuncio->find('all',
array('conditions' =>
array('OR' =>
array(
'produtoNome'=> array('$regex' => (string)$pesq),
'categoria'=> array('$regex' => (string)$pesq)
)
),
)
);
Not sure, but this should do the trick.
I would love to see the query from cake.
Never seen that '$regex' syntax for cake, can't find it in documentation, can't find any reference on the internet - where did you get that from? I'm using cake quite a while now and never came about that (though I never needed regexp for queries)
[sorry, low reputation, could not put this on a comment]
So, I got to do this research.
To work, so I had to modify the 'OR' to '$or'

How to get the column value from the particular join table using YII framework?

I am having the query like this
$criteria = new CDbCriteria(array(
'distinct' => true,
'select' => array('assets_id'),
'condition' => 'assets_id in (159)',
'with' => array('tbl_asset_mappings'=>array('select'=>array('catid')), 'tbl_assets_details'=>array('select'=>array('filetype','original_filename'))),
'together' => true
));
$result=TblAssets::model()->findAll($criteria);
But I am getting all the column values from firsttable only.I didnt get the column values from second tables.why?
My aim is getting assets_id from tblasset,tbl_asset_mappings.catid,tbl_assets_details.filetype,tbl_assets_details.original_filename
How can I achieve that.
You are querying for objects, so you will get the relations as child objects as relations like $post->author->name.
You need instead to do a join not a with. In this situation is more easier to write as Join raw-query.
Maybe would be more easier if you just write your own query rather than constructing throughout Yii
You can access related object like $model->relatedModel->attribute.
Set a break point after model->findAll() and look to $model->_related property. You must have a collection of related models there.

CakePHP sort ignore case

I've got to sort a list of Reservations (they're coupled to an event by defining a belongsTo association) by the last name of the person who registered the ticket.
I do this in cakePHP:
$reservations = Set::sort($eventinfo['Reservation'],'{n}.last_name','asc');
This works, but some users input their data in all lowercase, which makes the sorting wrong:
Alfa, Ziggy, aardvark, zorro
Where it should be:
aardvark, Alfa, Ziggy, zorro
How can I fix this? I could loop over the array and make every string start with an uppercase letter using ucword(), but that looks a bit ugly. Isn't there an easy way to alter the sort algorithm so it ignores case?
I would be normalising the surnames before storing them - either all lowercase, all UPPERCASE or all Capitalised.
Is there a reason you're not performing the sorting in SQL?
I assume there's a find operation shortly before you call Set::sort, which I imagine looks something like:
$reservations = $this->Event->find('first',array(
'conditions' => array('Event.id' => $my_event_id),
'contain' => array('Reservation')
));
You can instruct Cake's ORM to sort the contained Reservations with the same syntax as a standard find operation, like so:
$reservations = $this->Event->find('first',array(
'conditions' => array('Event.id' => $my_event_id),
'contain' => array(
'Reservation' => array('order'=>'Reservation.last_name')
)
));
It looks like in the code Set::sort is using array_multisort under the hood http://php.net/manual/en/function.array-multisort.php so it is not going to give you case insensitive sorting. You could look at the code for Set::sort and make your own subclass of Set that uses something like natcasesort http://www.php.net/manual/en/function.natcasesort.php or use mysql to do the sorting first, which by default in mysql would be case insensitive sorting

Custom CakePHP order by clause for jQuery autocomplete

I have a database of locations the user can select from by typing and autocompletion. In my CakePHP controller, I do this:
$locations = $this->Location->find('all', array(
'conditions' => array('Location.name like' => '%'.$term.'%'),
'fields' => array('Location.id', 'Location.name', 'Region.name'),
'order' => array(
array('Location.name = "'.mysql_real_escape_string($term).'"'
=> 'desc'),
'Location.name'
),
'limit' => 10,
'recursive' => 1,
));
It works perfectly fine, but it feels like a hack, and I'd rather not escape SQL literals myself.
The first order by clause is needed since a perfect match might otherwise not make it to the top of the alphabetically sorted list.
I considered moving the equality-test into a virtual field, but I don't feel it's a very elegant solution when the $term is dynamic.
How do I implement this in a better way?
As far as the structure of your query is written this is fine.
In regards to having to escape SQL yourself, this is from the Cookbook:
CakePHP already protects you against
SQL Injection if you use CakePHP's ORM
methods (such as find() and save())
and proper array notation (ie.
array('field' => $value)) instead of
raw SQL. For sanitization against XSS
its generally better to save raw HTML
in database without modification and
sanitize at the time of
output/display.

Categories