How do I properly nest queries in cakephp with where clauses? - php

I'm trying to get an order from the orders table that contains a product url from the product table. I tried using this subquery but cakephp keeps reading the url value s20_ultra as :c0
$temp = $this->Orders->getAssociation('Product')->find()->where(['product.url' => 's20_ultra']);
$result = $this->Orders->find()->where(["productId IN" => $temp]);
echo $result;
Appending firstOrFail() to the end of the first query temp and commenting out the second query result as a test works just fine but when I append it to both I get Cannot convert value of type %s to integer exception.
This would be the normal query of what I'm trying to accomplish:
select * from `order` where productId in (select product.id from product where url = 's20_ultra')

Based on what you've said, I think that the following should work. This assumes that the associations are correctly set up in both directions between Orders and Product. (Note, that's a non-standard naming scheme, it would normally be Products.)
$product = $this->Orders->getAssociation('Product')
->findByUrl('s20_ultra')
->contain(['Orders'])
->firstOrFail();
debug($product->orders);

Related

How to order data twice. But make the firts orderBy ineffective

I'm trying to get last 100 posts from database and than order them by likecount or another property and output only 5 of them, that way I will discover most liked 5 posts or viewed, or reported out of last 100 posts. What I tried so far is like below:
$lastHundredPost = Post::orderBy('id', 'desc')->take(100);
$post = $lastHundredPost->orderBy('likecount', 'desc')->take(2)->get();
this does not disable first orderBy property.
Laravel 5.4
If you want to get result from the first query, use collections:
$lastHundredPost = Post::orderBy('id', 'desc')->take(100)->get();
$post = $lastHundredPost->sortByDesc('likecount')->take(2);
My first idea is to execute sql query and get 100 row, and then use sortBymethod of your collection.
$lastHundredPost = Post::orderBy('id', 'desc')->take(100)->get();
$lastHundredPost->sortBy('likecount')->take(2);
Another idea is to use orderByRaw:
$posts = Post::orderByRaw('likecount DESC, id DESC')->take(2)->get();

Execute category search Sphinx php

Good time of day!
There is such config Sphinx
source txtcontent : ru_config
{
sql_query = SELECT `id` as `txt_id`, 1 as index_id, `type_id`,`content_type_id`, `title`, `annonce`, `content` FROM `TxtContent` WHERE `status` = 1 AND `content_type_id` != 14
sql_attr_uint = index_id
sql_attr_uint = type_id
}
The entire table is indexed, and is stored in one large search index.
When it comes to find what is in it then all works OK
But today the task was to search for categories
The categories described in the field and have a type_id of type int
How in php using SphinxAPI to perform such a search?
Standard search looks like this.
$sphinxClient = new SphinxClient();
$sphinxClient->SetServer("127.0.0.1", 3312 );
$sphinxClient->SetLimits( 0, 700,700 );
$sphinxClient->SetSortMode(SPH_SORT_RELEVANCE);
$sphinxClient->SetArrayResult( true );
$result = $sphinxClient->Query( $this->query, 'txtcontent provider item');
I tried to add
$sphinxClient->SetFilter('type_id','1');
To search only where type_id = 1 but it didn't help.
Actually how can I search for a specific category? option to find everything in php to let go of the result excess is not considered (otherwise, the search will then be saturada existing limit) how to do it "properly" via the API without placing each topic in a separate search index?
setFilter takes an Array of values. And they need to be numeric (type_id is a numeric attribute)
$sphinxClient->SetFilter('type_id',array(1));
The sphinxapi class actully uses assertions to detect invalid data like this, which I guess you have disabled (otherwise would of seen them!).

Moodle no value in table but the query result count returns 1

I am using Moodle 2.9.1. I have a query to fetch the last record from the table:
My query as follows:
$qstndetails = $DB->get_record_sql('SELECT * FROM {epoll_questions} WHERE status=? AND courseid=? ORDER BY id DESC LIMIT 0,1',array(2,$curseId));
I am taking the count as
echo count($qstndetails);
I am getting the count as 1 in the case of result is there.
But in the case of result is not there also I am getting count as 1.
I had tried print_r($qstndetails) but nothing showing. But the count show as 1.
The expecting count is 0 when there is no result.
Why I am getting like this?
When developing, always have debugging switched on. This would probably have displayed an error message for the first code. Go to site admin -> development -> debugging, then debug messages = developer and switch on display debug messages.
Also LIMIT isn't an SQL standard. Moodle works with several databases so try to keep the SQL generic.
Also I would suggest using named parameters rather than ?. It makes the code easier to read but they can also be used in any order.
and finally, you can use IGNORE_MULTIPLE to get the first record.
So the code should be something like this:
$sql = "SELECT *
FROM {epoll_questions}
WHERE status = :status
AND courseid = :courseid
ORDER BY id DESC";
$params = array('status' => 2, 'courseid' => $curseid);
$qstndetails = $DB->get_record_sql($sql, $params, IGNORE_MULTIPLE);
Need to change the query to
$qstndetails = $DB->get_records_sql('SELECT * FROM {epoll_questions} WHERE status=? AND courseid=? ORDER BY id DESC LIMIT 0,1',array(2,$curseId));
Now working!!

Codeigniter, join of two tables with a WHERE clause

I've this code:
public function getAllAccess(){
$this->db->select('accesscode');
$this->db->where(array('chain_code' => '123');
$this->db->order_by('dateandtime', 'desc');
$this->db->limit($this->config->item('access_limit'));
return $this->db->get('accesstable')->result();
}
I need to join it with another table (codenamed table), I've to tell it this. Not really a literal query but what I want to achieve:
SELECT * accesscode, dateandtime FROM access table WHERE chain_code = '123' AND codenames.accselect_lista != 0
So basically accesstable has a column code which is a number, let us say 33, this number is also present in the codenames table; in this last table there is a field accselect_lista.
So I have to select only the accselect_lista != 0 and from there get the corrisponding accesstable rows where codenames are the ones selected in the codenames.
Looking for this?
SELECT *
FROM access_table a INNER JOIN codenames c ON
a.chain_code = c.chain_code
WHERE a.chain_code = '123' AND
c.accselect_lista != 0
It will bring up all columns from both tables for the specified criteria. The table and column names need to be exact, obviously.
Good start! But I think you might be getting a few techniques mixed up here.
Firstly, there are two main ways to run multiple where queries. You can use an associative array (like you've started to do there).
$this->db->where(array('accesstable.chain_code' => '123', 'codenames.accselect_lista !=' => 0));
Note that I've appended the table name to each column. Also notice that you can add alternative operators if you include them in the same block as the column name.
Alternatively you can give each their own line. I prefer this method because I think its a bit easier to read. Both will accomplish the same thing.
$this->db->where('accesstable.chain_code', '123');
$this->db->where('codenames.accselect_lista !=', 0);
Active record will format the query with 'and' etc on its own.
The easiest way to add the join is to use from with join.
$this->db->from('accesstable');
$this->db->join('codenames', 'codenames.accselect_lista = accesstable.code');
When using from, you don't need to include the table name in get, so to run the query you can now just use something like:
$query = $this->db->get();
return $query->result();
Check out Codeigniter's Active Record documentation if you haven't already, it goes into a lot more detail with lots of examples.

Having difficulties sorting data from mysql query using php

This code is used to get a specific list of ID's from one table, then use those ID's to get the information from another table. Once I get all the information from the 2nd table, I am attempting to sort the data alphabetically based on a field in the 2nd table.
Example, I am getting the name based on a correlating ID and then want to display the entire result in alphabetical order by name (artist_name).
Here is the code I have. When I execute this without the sort(), it works fine but is not in alphabetical order. When I add the sort() in the 2nd while statement, the page looks the same but the name and other data do not display. The source code in the browser shows that the results are being accounted for but the sort must be preventing the variables or information from being displayed for some reason.
I haven't used a sort function before and I tried looking at some examples but couldn't really find something specific to my situation. Any and all help would be greatly appreciated. I have already looked at the PHP manual for sort so no need to send me a link to it ;-)
<?php $counter = 0;
$artistInfo = mysql_query("SELECT DISTINCT event_url_tbl.artist_id FROM event_url_tbl WHERE (SELECT cat_id FROM artist_tbl WHERE artist_tbl.artist_id = event_url_tbl.artist_id) = 1");
while ($aID = mysql_fetch_array($artistInfo))
{
$getArtistInfo = mysql_query("SELECT * FROM artist_tbl WHERE artist_id = '" . $aID['artist_id'] . "'");
while($artist = mysql_fetch_array($getArtistInfo))
{
sort($artist);?>
<a class="navlink" href="<?=HOST?><?=$artist['page_slug']?>/index.html">
<?=$artist['artist_name']?>
</a><br />
<?php }
}
?>
Your best bet, as a commenter mentioned, is to use an ORDER BY clause in SQL.
SELECT *
FROM artist_tbl
WHERE artist_id = XXX
ORDER BY artist_name ASC
The other commenter who suggested using PDO or mysqli is also correct, but that's a different issue.
To answer your specific question about sorting, according to the manual,
Blockquote Note: This function assigns new keys to the elements in array. It will remove any existing keys that may have been assigned, rather than just reordering the keys.
This means all of your array keys ('page_slug', 'artist_name', etc) are wiped out. So when you try to refer to them later, there is no data there.
Were you to use this method, you would want to use asort to sort an associative array.
However, you don't want to use sort here. What you're sorting is the variables for one row of data (one individual artists), not all of your artists. So if you think of each artist row as an index card full of data (name, id#, page slug, etc) all you're doing is moving those items around on the card. You're not reorganizing your card catalog.
Using an order by clause in the SQL statement (and rewriting in PDO) is your best bet.
Here is how I would rewrite it. I have to take some guesses at the SQL because I'm not 100% sure of your database structure and what you're specifically trying to accomplish, but I think this would work.
$query_str = "
SELECT
artist.name,
artist.page_slug
FROM
artist_tbl AS artist
INNER JOIN event_tbl AS event
ON event.artist_id = artist.artist_id
WHERE
artist.cat_id = 1
ORDER BY
artist.name ASC";
$db_obj = new PDO (/*Connection stuff*/);
$artists_sql = $db_obj->prepare ($query_str);
$artists_sql->execute ();
while ($artist = $artists_sql->fetch (PDO::FETCH_ASSOC)) {
$return_str .= "<a class='navlink' href='{HOST}
{$artist['page_slug']}/index.html'>
{$artist['artist_name']}</a><br/>";
}
echo $return_str;
In all honesty, I would probably create an artist class with a display_link method and use PDO's fetchObject method to instantiate the artists, but that's getting ahead of ourselves here.
For now I stuck with procedural code. I don't usually like to mix my HTML and PHP so I assign everything to a return string and echo it out at the end. But this is close to what you had, using one SQL query (in PDO - seriously worth starting to use if you're creating new code) that should give you a list of artists sorted by name and their associated page_slugs.
You could do all of this in one query:
SELECT * FROM event_url_tbl AS event
INNER JOIN artist_tbl AS artist ON event.artist_id = artist.id
ORDER BY artist.name DESC;
This cuts out a lot of the complexity/foreaches in your script. You'll end up with
Label1 (Label 1 details..) Artist1 (Artist1 details..)
Label1 (Label 1 details..) Artist2 (Artist1 details..)
Label2 (Label 2 details..) Artist3 (Artist1 details..)
Always good to bear in mind "one query is better than many". Not a concrete rule, just if it's possible to do, try to do it. Each query has overheads, and queries in loops are a warning sign.
Hopefully that helps

Categories