Hard-coded query
$stock = DB::select("SELECT * FROM reports_finra WHERE symbol = ? ", array('CWCO')); // works and returns valid result set
Array (
[0] => Array ( [query] => SELECT * FROM symbols [bindings] => Array ( ) [time] => 37.4 )
[1] => Array ( [query] => SELECT * FROM reports_finra WHERE symbol = ? [bindings] => Array ( [0] => CWCO ) [time] => 27.07 )
)
# result set when var_dump($stock) ( [1]'s query )
array(11) {
[0]=> object(stdClass)#5939 (7) { ["date"]=> int(20140116) ["symbol"]=> string(4) "CWCO" ["id"]=> int(1498) }
[1]=> object(stdClass)#5940 (7) { ["date"]=> int(20140117) ["symbol"]=> string(4) "CWCO" ["id"]=> int(8515) }
[2]=> object(stdClass)#5941 (7) { ["date"]=> int(20140121) ["symbol"]=> string(4) "CWCO" ["id"]=> int(15526) }
...
}
Dynamically binded variable being passed to query
$symbol = $symbol->symbol;
echo $symbol;
echo '<br />';
$stock = DB::select("SELECT * FROM reports_finra WHERE symbol = ? ", array($symbol));
$query = DB::getQueryLog();
print_r($query);
echo '<br />';
var_dump($stock); exit;
Results
CWCO // the result from echoing $symbol
Array ( // getQueryLog()
[0] => Array ( [query] => SELECT * FROM symbols [bindings] => Array ( ) [time] => 36.06 )
[1] => Array ( [query] => SELECT * FROM reports_finra WHERE symbol = ? [bindings] => Array ( [0] => CWCO ) [time] => 27.55 ) )
array(0) { } // var_dump($stock);
As you can see, when I pass the value of symbol into the query as a hard-coded value, I get the desired result set. However, when I pass the value in dynamically, the query returns an empty result set.
I have been going back and forth with this for quite a while now and am out of ideas on how to further troubleshoot this. Even more perplexing is the fact that these exact queries work in my dev environment but not when I pushed to prod.
Through troubleshooting, prior to realizing that when I pass in the raw, hard-coded value, that I was getting a valid result set, I ensured that there were only minor PHP / MySQL version differences between dev and prod ENVs. I triple checked that the user had the proper DB permissions. And, I tailed out my log files. None of these actually help shed any light onto what is actually going wrong here though.
As I just recently started to get back into development and have only been playing with L4 for a week or two, I'm hoping someone with more experience will see what it is that is causing this (I have an odd feeling that it is going to be an ID10T error..).
I look forward to any advice and insight you may have to offer.
-- Edit --
As the query is returning an (empty) result back (and not throwing an error), the query appears to be "working" as far as MySQL is concerned. However, it is not returning the result set for whatever reason. I am not sure if this has to do with PDO, Eloquent, or something else entirely. It's a basic SELECT * query on a non-related table; it shouldn't be this much hassle.
And, I'm quite perplexed why the other select statements work without an issue, but this one is not. Granted, I am querying a table that is not related to the model (there is no DB/L4 relationships defined; this is a once-off Select statement in order to do some essential math).
Unfortunately, I can't proceed until I get this worked out...
I stated in the question that I thought this might be an ID10T error, and it was.
After doing a var_dump($symbols) on it again, and paying a little closer attention, I realized that there was a trailing space behind each of the $symbols which didn't match anything in the table. Aha! So, the query was executing successfully and returning the correct results all along; go figure. ;)
Interesting thing to note, I should have done a trim on the $symbols before inserting them into the DB table using Laravel's http://laravel.com/docs/eloquent#accessors-and-mutators as pointed out by the awesome AndreasLutro in #laravel.
Related
I'm getting data from multiple API requests and storing each in a separate MySQL table. For each request I have an associated table, with field names matching the JSON API response. Since I'm not using all of fields from the API, I'm finding the fields in the MySQL table and using that to create the prepared statement with PDO, then feeding the results array into that for execution. Here's the function that accepts the statement and the results array:
function insert_array($sql,$args)
{
$this->connect();
$q = $this->con->prepare($sql);
foreach($args as $record) {
$q ->execute($record);
echo "<pre>";var_dump($record);echo "</pre>";
$arr = $q->errorInfo();
print_r($arr);
}
$this->disconnect();
return $q;
}
The last three lines in the foreach loop are just for debugging.
This worked fine for my first request, but no records are inserted, and I receive HY093, for others.
For the one that works, the prepared statement ($sql) comes out as
INSERT INTO fs_dynamicagents (agent_id, firstname, lastname) VALUES (:agent_id, :firstname, :lastname) ON DUPLICATE KEY UPDATE firstname=:firstname, lastname=:lastname
I'm finding unique fields first, so that's why agent_id isn't in the update statement. This inserts successfully, even though I'm not using all the fields. Here's the output of the var_dump and errorInfo:
array(4) {
["agent_id"]=>
string(3) "002"
["firstname"]=>
string(9) "Bill"
["lastname"]=>
string(5) "Murray"
["password"]=>
string(4) "1212"
}
Array ( [0] => 00000 [1] => [2] => )
Now here's an example of one that doesn't work:
INSERT INTO fs_queue (name, record) VALUES (:name, :record) ON DUPLICATE KEY UPDATE record=:record
And part of the first API record:
array(79) {
["name"]=>
string(7) "Choice1"
["fc_name"]=>
string(7) "Choice1"
["friendlyname"]=>
string(7) "Choice1"
["record"]=>
string(1) "1"
["agent_announcement_file"]=>
string(0) ""
["play_agent_announcement_file"]=>
string(1) "0"
["incoming_call_script"]=>
string(0) ""
["caller_agent_match"]=>
string(1) "0"
["survey_id"]=>
NULL
}
Array ( [0] => HY093 [1] => [2] => )
You can see I haven't included all 79 of the fields, but I've tried to include at least the fields with "name" in the label, and an empty string and a null value. Nothing but "name" and "record" should be bound, so I don't see those as a problem.
Every instance I've found online for this error code was due to a type (or case sensitivity). I've tried defining "record" as an int and a varchar.
Well, I had hoped that the process of typing this out would expose the problem to me, but no such luck. If a night's sleep doesn't help, I'd love to hear thoughts.
Edit: Something else I have tried is removing the ON DUPLICATE UPDATE section (and emptied the table so there will not be any duplicates) so that each parameter is only bound once. It sounds like that was a bug a few years ago that has been fixes, but even without that I receive the same error.
Edit2: Hmm, even stranger, removing the ON DUPLICATE UPDATE causes some of my previously working statements to fail with the same error. Not all of them, and of course those that don't fail for that reason will fail if it runs into a duplicate.
Edit3: Something else I have tried is removing the binding-by-key for the update statement, and changing this to
INSERT INTO fs_queue (name, record) VALUES (:name, :record) ON DUPLICATE KEY UPDATE record= VALUES(record)
I didn't think that would fix it, because it succeeds the first way on other tables, and this does in fact still fail.
Edit4: I was able to make one of these work by adding fields to the MySQL table so that all the columns from the input array were being used. However, I don't think that's what really solved the problem, because I have others succeeding without all columns being used, even in the middle of the array.
Ok, I figured it out. First, I was not setting ATTR_EMULATE_PREPARES at all, which means it would default to the database preparation engine unless the PDO engine was required. Since MySQL cannot re-use placeholders, it was using the PDO engine. Setting that to false would force the MySQL engine, and all requests would fail.
So the PDO engine can re-use placeholders, but however that happens it's not very good at finding the values. Even trying to find 2 out of 3 columns it would sometimes fail. So rather than let PDO sort it out, I'm throwing out everything I don't need before I send it to be inserted.
I'm using a function to delete columns that I found here.
<?php
function delete_col(&$array, $key) {
return array_walk($array, function (&$v) use ($key) {
unset($v[$key]);
});
}
$table_fields = array("id","fruit");
$insert_data = array(
array(
"id" => "1",
"fruit" => "Apple",
"color" => "Red"
),array(
"id" => "2",
"fruit" => "Apple",
"color" => "Green"
),array(
"id" => "3",
"fruit" => "Pear",
"color" => "Green"
)
);
foreach($insert_data[0] as $key=>$value) {
if(!in_array($key, $table_fields)) {
delete_col($insert_data, $key);
}
}
echo "<pre>";
print_r($insert_data);
echo "</pre>";
?>
This assumes that the first record will have an entry for every column. I do have some where that's not true, but so far it hasn't caused problems, but I will probably end up rewriting this to go through each row.
I am struggling with weird behavior of fetchAll(). I am executing a stored proc using PDO which returns the set of songs.
Here is my PHP code
$sql = "call getHymn(?)";
$param = array($id);
$result = $this->db->getData($sql,$param);
here is the getData function
public function getData($sql,$param=[])
{
try
{
$stmt = $this->connection->prepare($sql);
$stmt->execute($param);
echo '<pre>';
print_r($stmt->fetchAll());
/*return($stmt->fetchAll());*/
}
catch (PDOException $e)
{
throw new Exception($e->getMessage());
}
}
When I execute stored proc in MySQL it returns me 3 rows as expected. But when I execute it through PDO and use fetchall() then I get extra null outside the array..could not find any help anywhere, not even in PHP documentation. My fetchAll() output looks like below
Array
(
[0] => Array
(
[id] => 4
[refrain] =>
[stanzaId] => 1
[stanzaText] => Amazing grace! How sweet the sound
that saved a wretch like me!
I once was lost, but now am found;
was blind, but now I see.
)
[1] => Array
(
[id] => 4
[refrain] =>
[stanzaId] => 2
[stanzaText] => 'Twas grace that taught my heart to fear,
and grace my fears relieved;
how precious did that grace appear
the hour I first believed.
)
[2] => Array
(
[id] => 4
[refrain] =>
[stanzaId] => 3
[stanzaText] => Through many dangers, toils, and snares,
I have already come;
'tis grace hath brought me safe thus far,
and grace will lead me home
)
)
null
And here is my stored proc which is quite simple and straight forward
CREATE DEFINER=`root`#`localhost` PROCEDURE `getHymn`(IN `hid` INT)
READS SQL DATA
BEGIN
select
a.id, a.refrain, b.stanzaId, b.stanzaText
from
hymns a, hymnstanza b
where a.id = hid and a.id = b.hymnid;
END
Can anybody help me understand what is going on?
Okay, friends. I found the bug now and #decez you were absolutely correct that there was some extra echo statement which was causing null to appear after the array is printed. Feeling quite relaxed as after almost 12 hours I was able to move on successfully. THANK YOU ALL especially #decez.
Just to elaborate what mistake I had done, I was double JSONifying the output of fetchAll().
I'll note that this is a very special case, hence the question to begin with. Under normal circumstances, such a function would be simple:
I have an array named $post_id, which contains 5 values
(Each numerical)
In order to print each value in the array, I use the following loop:
.
for ($i = 0; $i < $num; $i++)
{
echo $post_id[$i] . ' ';
}
...Which prints the following: 49, 48, 47, 46, 43
3. In my database, I have a table that looks like this:
post_categories
_____________________
post_id | category
__________|__________
43 | puppies
43 | trucks
46 | sports
46 | rio
46 | dolphins
49 | fifa
4. So, using the data in the array $post_id, I'd like to loop a database query to retrieve each value in the category column from the post_categories table, and place them into uniquely named arrays based on the "post id", so that something like...
echo $post_id_49[0] . ' ', $post_id_46[1];
...Would print "fifa rio", assuming you use the above table.
An example of such a query:
//Note - This is "false" markup, you'll find out why below
for ($i = 0; $i < $num; $i++)
{
$query = "SELECT category FROM post_categories WHERE post_id = $post_id[$i]";
fakeMarkup_executeQuery($query);
}
Why is this a "special" case? For the same reason the above query is "false".
To elaborate, I'm working inside of a software package that doesn't allow for "normal" queries so to say, it uses it's own query markup so that the same code can work with multiple database types, leaving it up to the user to specify their database type which leaves the program to interpret the query according to the type of database. It does, however, allow the query to be stored in the same "form" that all queries are, like "$result = *query here*" (With the only difference being that it executes itself).
For that reason, functions such as mysql_fetch_array (Or any MySQL/MySQLi function akin to that) cannot, and will not work. The software does not provide any form of built in alternatives either, effectively leaving the user to invent their own methods to achieve the same results. I know, pretty lame.
So, this is where I'm stuck. As you'd expect, all and any information you find on the Internet assumes you can use these MySQL & MySQLi functions. What I need, is an alternative method to grab one array from the results of a looped query per loop. I simply cannot come to any conclusion that actually works.
tl;dr I need to be able to (1) loop a query, (2) get the output from each loop as it's own array with it's own name, and (3), do so without the use of functions like mysql_fetch_array. The query itself does not actually matter, so don't focus on that. I know what do with the query.
I understand this is horrifically confusing, long, and complicated. I've been trudging through this mess for days - Close to the point of "cheating" and storing the data I'm trying to get here as raw code in the database. Bad practice, but sure as heck a lot easier on my aching mind.
I salute any brave soul who attempts to unravel this mess, good luck. If this is genuinely impossible, let me know so that I can send the software devs an angry letter. All I can guess is that they never considered that a case like mine would come up. Maybe this is much more simple then I make it to be, but regardless, I personally cannot come to an logical conclusion.
Additional note: I had to rewrite this twice due to some un explained error eliminating it. For the sake of my own sanity, I'm going to take a break after posting, so I may not be able to answer any follow up questions right away. Refer to the tl;dr for the simplest explanation of my need.
Sure you can do this , here ( assuming $post_ids is an array of post_id that you stated you had in the OP ), can I then assume that I could get category in a similar array with a similar query?
I don't see why you couldn't simply do this.
$post_id = array(49, 48, 47, 46, 43);
$result = array();
foreach($post_id as $id)
{
//without knowing the data returned i cant write exact code, what is returned?
$query = "SELECT category FROM post_categories WHERE post_id = $id";
$cats = fakeMarkup_executeQuery($query);
if(!empty($cats)) {
if(!isset($result[$id])){
$result[$id] = array();
}
foreach( $cats as $cat ){
$result[$id][] => $cat;
}
}
}
Output should be.
Array
(
[49] => Array
(
[0] => fifa
)
[46] => Array
(
[0] => sports
[1] => rio
[2] => dolphins
)
[43] => Array
(
[0] => puppies
[1] => trucks
)
)
Ok, assuming you can run a function (we'll call it find select) that accepts your query / ID and returns an array (list of rows) of associative arrays of column names to values (row), try this...
$post_categories = [];
foreach ($post_id as $id) {
$rows = select("SOME QUERY WHERE post_id = $id");
/*
for example, for $id = 46
$rows = [
['category' => 'sports'],
['category' => 'rio'],
['category' => 'dolphins']
];
*/
if ($rows) { // check for empty / no records found
$post_categories[$id] = array_map(function($row) {
return $row['category'];
}, $rows);
}
}
This will result in something like the following array...
Array
(
[49] => Array
(
[0] => fifa
)
[46] => Array
(
[0] => sports
[1] => rio
[2] => dolphins
)
[43] => Array
(
[0] => puppies
[1] => trucks
)
)
Just today I noticed a strange behavior in an object model that was previously working just fine (I have checked everything possible and nothing about its configuration has changed, so I am suspecting a change to PHP version and wondering if anyone else has experience anything similar)
Until recently, I could set the keys of object properties that were arrays manually. The specific implememation of this in one of my models was contained in a gallery class that looked like this:
public function __construct($gid){
parent::__construct($gid);
$this->Photos = $this->getPhotos();
$this->AlbumCover = $this->getCover();
}
public function getPhotos(){
$sql = 'SELECT GalleryPhotoID FROM GalleryPhoto WHERE GalleryID = ?';
$params = array($this->GalleryID);
$allids = DatabaseHandler::GetAll($sql, $params);
$output = array();
foreach($allids as $id){
$gp = new GalleryPhoto($id['GalleryPhotoID']);
$output[$gp->GalleryPhotoID] = $gp;
}
return $output;
}
Irrelevant parts omitted.
Basically, I could set the array keys of the Gallery's Photos object to the individual photo's id in the database. This just made it easier to code for individual iteration and made the whole thing run smoother.
Now, no matter what I set that key to, automatic integers are generated when the foreach runs. I even tried typing a literal string in there, which theoretically should replace every iteration, but I still got incremented, automatic integers for the keys of the property Photos.
[Photos] => Array
(
[0] => GalleryPhoto Object
(
[GalleryID] => 9
[Caption] =>
[Orientation] => 0
[AlbumCover] =>
[DateAdded] => 2011-01-03 16:58:51
[GalleryPhotoID] => 63
[Thumbnail] =>
[Image] =>
[src] => http://..com/galleryImage/getImage/63
)
[1] => GalleryPhoto Object
(
[GalleryID] => 9
[Caption] =>
[Orientation] => 0
[AlbumCover] =>
[DateAdded] => 2011-01-03 16:58:51
[GalleryPhotoID] => 64
[Thumbnail] =>
[Image] =>
[src] => http://..com/galleryImage/getImage/64
)
)
Has the abillity to manually set keys within an object property that is an array been removed in some minor release and I am unaware of it? I have googled all over, looked through the PHP manual site and found no answer. Has anyone experienced anything similar? Is there a better approach I should consider? I only really went with this because it made it so much easier to implement a next/previous system via ajax requests back to the next logical id (keeping in mind that ids can be deleted between!)
Thanks!
I don't see anything wrong with what you have, and I've never experienced the behavior you describe. However, a quick solution could be to replace the assignment line with something like this:
$output[$id['GalleryPhotoID']] = $gp;
You could also echo $gp->GalleryPhotoID; to ensure that the GalleryPhotoID property can actually be accessed that way.
Lastly, you said you replaced the above line with something akin to:
$output['foobar'] = $gp;
and it still created a new entry, with integer keys, for each entry? If that's the case, then I think there may be something in the code you omitted that's causing the problem.
Facepalm all the way. The effluvium of New Year's must still be in my brain, else I would have noticed that the function I added to fetch the album cover thumbnail shuffled the array if there wasn't a photo with the AlbumCover property set!
private function getCover(){
foreach($this->Photos as $ind=>$p){
if($p->AlbumCover){
return $this->Photos[$ind];
}
}
shuffle($this->Photos); //this is the problem
return current($this->Photos);
}
I amended this to just make a local copy of the variable and shuffle that instead if no cover is set.
private function getCover(){
foreach($this->Photos as $ind=>$p){
if($p->AlbumCover){
return $this->Photos[$ind];
}
}
$Photos = $this->Photos;
shuffle($Photos);
return current($Photos);
}
I accepted and upvoted both the answer and the comment posted since your caveats lead me to my error. Thanks guys!
I registered an object an I'm trying to get the following below:
stdClass Object (
[test] => test
[users] => stdClass Object (
[createSave_email_subject] => - New
User Account
[createSave_email_pass] => The user
was created, and an email was sent to
them!
) )
Smarty Code:
Works:
{language->test}
Doesn't Work:
{language->users->createSave_email_subject}
{language[users]->createSave_email_subject}
{language.users->createSave_email_subject}
{language->users.createSave_email_subject}
{language->users[createSave_email_subject]}
I built a test case for this using this code:
$test = json_decode('{"test":"test","users":{"createSave_email_subject":"new user account","createSave_email_pass":"The user was created, and an email was sent to them!"}}');
$smarty->assign('testing',$test);
$test is this when var_dumped
object(stdClass)#8 (2) {
["test"]=>
string(4) "test"
["users"]=>
object(stdClass)#7 (2) {
["createSave_email_subject"]=>
string(16) "new user account"
["createSave_email_pass"]=>
string(52) "The user was created, and an email was sent to them!"
}
}
In the tpl I placed
{$testing->users->createSave_email_subject}
And it worked without issue. This was using Smarty 2.6.23
You're missing the dollar signs, you should be using
{$language->test}
Not sure if that's the problem though, as I didn't think smarty would output anything with the syntax you gave. Your test case isn't very reliable either, it's safer to use something like
array('test' => 'worked');
where the key and value are different. With your test, smarty could be printing the key and you wouldn't know the difference.
Use debug_print_var to help identify your problem. e.g.
$language: {$language|#debug_print_var}
users: {$language->users|#debug_print_var}
cse_subject: {$language->users->createSave_email_subject|#debug_print_var}