Part of the code gets skipped - php

I'm trying to write my own little blog.
For this, I use the CodeIgniter framework.
In my blog posts, I also want to save a category and some keywords.
I need to be able to check if a category/keyword already exists, if not a new one needs to be created.
The ID of the existing/new one is saved to be used in a 'connecting' table.
I have the following database setup.
posts - id (AI), title, date, content
categories - id (AI), category
post_categories - post, category
keywords - id (AI), keyword
post_keywords - post, keyword
*AI = Auto Increment
The tables posts, post_categories and post_keywords get updated, the tables categories and keywords remain empty. The category and keyword values in the connecting tables are ofc incorrect.
When troubleshooting my code, I echo'ed every variable in every step.
For some reason, the whole if/else structures checking whether a category or keyword already exists is skipped.
/**
* Insert post into database
* Check if category already exists, if not add it
* Check if keywords already exist, if not add them
* Insert post-category and post-keyword links
* #param array $data
* #return boolean success
*/
function create($data) {
print_r($data);
try {
// posts
$this->db->insert('posts', array(
'title' => $data['title'],
'date' => $data['date'],
'content' => $data['content']
));
$postId = $this->db->insert_id();
echo '<p>Inserted new post (' . $data['title'] . ') at ' . $postId . '</p>';
// category
$category = $data['category'];
$query = $this->db->get_where('categories', array('category' => $category));
$cat = 666;
if ($this->db->count_all_results() == 1) {
foreach ($query->result() as $row) {
$cat = $row->id;
echo '<p>cat = ' . $cat . '</p>';
}
} else {
$this->db->insert('categories', array(
'category' => $category
));
$cat = $this->db->insert_id();
echo '<p>cat = ' . $cat . '</p>';
}
echo '<p>Inserted new category (' . $category . ') at ' . $cat . '</p>';
if($cat == 666) { echo ':('; }
$this->db->insert('post_categories', array(
'post' => $postId,
'category' => $cat
));
// keywords
$keywords = $data['keywords'];
foreach ($keywords as $keyword) {
$query = $this->db->get_where('keywords', array('keyword' => $keyword));
$key = 666;
if ($this->db->count_all_results() == 1) {
foreach ($query->result() as $row) {
$key = $row->id;
echo '<p>key = ' . $key . '</p>';
}
} else {
$this->db->insert('keywords', array(
'keyword' => $keyword
));
$key = $this->db->insert_id();
echo '<p>key = ' . $key . '</p>';
}
echo '<p>Inserted new keyword (' . $keyword . ') at ' . $cat . '</p>';
if($key == 666) { echo ':('; }
$this->db->insert('post_keywords', array(
'post' => $postId,
'keyword' => $key
));
}
return true;
} catch (Exception $e) {
print '<p>ERROR:</p>' . $e;
return false;
}
}
Also in my controller
echo '<p>' . ($this->m_posts->create($post) ? 'no errors :)' : 'error! :(') . '</p>';
Result
Array ( [title] => Foo Bar [date] => 2014-05-22 [content] => lorum ipsum dolore si amet [category] => Category [keywords] => Array ( [0] => Some [1] => Keywords ) )
Inserted new post (Foo Bar) at 2
Inserted new category (Category) at 666
:(
Inserted new keyword (Some) at 666
:(
Inserted new keyword (Keywords) at 666
:(
no errors :)
In my database
POSTS
stdClass Object ( [id] => 1 [title] => Title [date] => 2014-05-22 [content] => okokokokokokok )
stdClass Object ( [id] => 2 [title] => Foo Bar [date] => 2014-05-22 [content] => lorum ipsum dolore si amet )
CATEGORIES
POST_CATEGORIES
stdClass Object ( [post] => 1 [category] => 666 )
stdClass Object ( [post] => 2 [category] => 666 )
KEYWORDS
POST_KEYWORDS
stdClass Object ( [post] => 1 [keyword] => 666 )
stdClass Object ( [post] => 2 [keyword] => 666 )
stdClass Object ( [post] => 2 [keyword] => 666 )
note: I use 99 as a temp value to test if the variable was filled because I first thought the variable's value didn't leave the scope of the if/else. But echo'ing the values of the vars inside the if/else prints nothing. It seems to skip the whole if/else sections.

Adjust the code to:
In if statement num_rows of query it self
If you expect 1 record do a $query->row() directly instead of a foreach loop.
$query = $this->db->get_where('categories', array('category' => $category));
$cat = 666;
if ($query->num_rows() == 1) {
$row = $query->row();
$cat = $row->id;
echo '<p>cat = ' . $cat . '</p>';
} else {
$this->db->insert('categories', array(
'category' => $category
));
$cat = $this->db->insert_id();
echo '<p>cat = ' . $cat . '</p>';
}

Related

Sqlite3 search with PDO

I can't get SQLite LIKE search to work with PDO. This works fine with
MySQL and MariaDB but I can't get this to work with SQLite3.
I have also tried with different examples from internet.
I'm using sqlite3 version 3.35.3 and version PHP 8.0.3 on Linux 5.9.
echo '<pre>';
$createTable = <<<EOT
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
INSERT INTO users(name) VALUES
('alpha'),
('beta'),
('gamma'),
('theta');
EOT;
if (!file_exists(__DIR__ . '/test.db'))
{
echo "#CREATING DB# <br>";
$pdo = new \PDO('sqlite:' . __DIR__ . '/test.db');
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$pdo->exec($createTable);
$term = 'et';
$sql = " SELECT * FROM users WHERE name LIKE :term ";
$stmt = $pdo->prepare($sql);
$prepare = [
'term' => "'%". $term ."%'"
];
echo getPdoCompiledSqlString($sql, $prepare) . '<br>';
if($stmt)
{
$stmt->execute($prepare);
//$stmt->debugDumpParams();
debugPdo($stmt);
echo "#FETCHALL# <br>";
print_r( $stmt->fetchAll() );
}
}
else
{
echo "#DELETING DB#";
unlink(__DIR__ . '/test.db');
}
function getPdoCompiledSqlString($sql, $params){
echo "#SQL STRING# <br>";
$keys = [];
foreach ($params as $key => $value){ if (is_string($key)) {$keys[] = '/:'.$key.'/';} else {$keys[] = '/[?]/';}}
return preg_replace($keys, $params, $sql, 1, $count);
}
function debugPdo(&$stmt){
echo "#DEBUG PDO OBJ# <br>";
$stmt->debugDumpParams();
}
echo '<pre>';
You don't need to quote the parameter :
'term' => "%". $term ."%"
Instead of
'term' => "'%". $term ."%'"
Because the parameter will automatically be quoted during execute()
$term = 'et';
$sql = " SELECT * FROM users WHERE name LIKE :term ";
$stmt = $pdo->prepare($sql);
$prepare = [
'term' => "%". $term ."%" //only the search string: `%et%`
];
$stmt->execute($prepare);
print_r($stmt->fetchAll());
Output:
Array
(
[0] => Array
(
[id] => 2
[0] => 2
[name] => beta
[1] => beta
)
[1] => Array
(
[id] => 4
[0] => 4
[name] => theta
[1] => theta
)
)

ForEach loop returns the same name over and over

Whenever I run this code through the SalesForce PHP api, it fails with err:Notice: Trying to get property of non-object
$query ="SELECT accountId,Status,Id,Service_Account_DMKT__r.name,(select Activity_Type__c from Tasks) from case where Owner.Name ='" . $name . "' AND CreatedDate = THIS_MONTH AND Record_type_name__c='Performance Reviews' AND status NOT IN ('')";
$response = $mySforceConnection->query($query);
$queryResult = new QueryResult($response);
foreach($queryResult->records as $case){
//for ($queryResult->rewind(); $queryResult->pointer < $queryResult->size; $queryResult->next()) {
$callCounter = 0;
$emailCounter = 0;
$accountId = $case->current()->accountId;
$accountName=$case->current()->Service_Account_DMKT__r->Name;
$caseId= $case->current()->Id;
if($case->any['Tasks']->records) {
$counter=0;
foreach($case->any['Tasks']->records as $record) {
$taskRecord = $record->any;
if (strpos($taskRecord, 'Call - Outbound') !== false) {
$callCounter++;
} else {
$emailCounter++;
}
$counter++;
}
}
echo '<p>AccountName=' . $accountName . '</p><p>CaseId=' . $caseId . '</p>';
echo '<p>' . $callCounter . ' Calls and ' . $emailCounter . ' emails';
echo'<hr>';
$index++;
}
print_r($case);
I know it is because of these three lines. I'm not stepping through the object correctly.
$accountId = $case->current()->accountId;
$accountName=$case->current()->Service_Account_DMKT__r->Name;
$caseId= $case->current()->Id;
But I'm not sure what to use instead of current(). Below is the response object from the SF API
stdClass Object
(
[type] => Case
[Id] => Array
(
[0] => 5000e00001J7L0pAAF
[1] => 5000e00001J7L0pAAF
)
[any] => Array
(
[0] => 00130000002bqXiAAIClosed - Contact Declined5000e00001J7L0pAAF
[Service_Account_DMKT__r] => stdClass Object
(
[type] => Account
[Id] =>
[any] => brinsoncorsicanafordfd
)
[Tasks] => stdClass Object
(
[done] => 1
[queryLocator] =>
[records] => Array
(
[0] => stdClass Object
(
[type] => Task
[Id] =>
[any] =>
)
)
[size] => 1
)
)
)
I finally managed to fix it by converting the response back to another object
$query ="SELECT accountid,Status,Id,Service_Account_DMKT__r.name,(select Activity_Type__c,subject from Tasks) from case where Owner.Name ='" . $SFName . "' AND CreatedDate = THIS_MONTH AND Record_type_name__c='Performance Reviews' AND status NOT IN ('')";
$response = $mySforceConnection->query($query);
$queryResult = new QueryResult($response);
foreach($queryResult->records as $case){ //For every record within $queryResult
$callCounter = 0; //Set up our task counters
$emailCounter = 0;
$sObject = new SObject($case); //turn $case back into a SObj to easy step thru
$accountId= $sObject->AccountId; //Pull AccountId from $sObject
$accountName=$sObject->Service_Account_DMKT__r->Name;
$caseId=$sObject->Id;
$caseStatus=$sObject->Status;
if(!isset($sObject->queryResult)) { //Check if there are any tasks on the record, otherwise we'll get an error
$callCounter=0; //if there are no tasks, set counters to 0
$emailCounter=0;
}else{
$counter=0;
foreach($case->any['Tasks']->records as $record) { //for each task in the $case
$taskObject = new SObject($record); //Turn $record into taskObject so we can step through it.
$taskType = $taskObject->Activity_Type__c; //Pull the activity type out of TaskObject
if($taskType == "Call - Outbound"){ //Calling $taskType actually allows us to compare the obj to a string, where as going through this in an array format would not!
$callCounter++; //increase counter if the taskType is a call
} else {
$emailCounter++;
}
}
}
echo '<p>AccountName=' . $accountName . '</p><p>AccountID=' . $accountId . '</p><p>CaseId=' . $caseId . '</p><p>CaseStatus=' . $caseStatus . '</p>';
echo '<p>' . $callCounter . ' Calls and ' . $emailCounter . ' emails';
echo'<hr>';
}

Building a string Concat array with the same ID inside a query loop

i have a query inside a for loop that getting the product name of every array element. Now in every element of my array, i have an ID, where i want to concat all product names with the-same shipping_id.
Here i have my array with values like these:
Array name:id with values of:
Array
(
[0] => Array
(
[product_id] => 1
[shipping_id] => 1
)
[1] => Array
(
[product_id] => 2
[shipping_id] => 1
)
[2] => Array
(
[product_id] => 1
[shipping_id] => 2
)
)
now i made this code with these:
$first = true;
$temp_ship_id = "";
$product_list = "";
foreach ($ids as $product) {
$productname = $this->getproductname($product[0][product_id]);
// if($first) {
// $temp_ship_id = $product[0][shipping_id];
// $first = false;
// }
// if($product[0][shipping_id] == $temp_ship_id) {
// $product_list .= $productname.";
// } else {
// $product_list .= $productname.";
// //$product_list = "";
// $temp_ship_id = $product[0]->shipping_id;
// }
}
public function getproductname($product_id) {
$product = DB::table('products')->select('product_name')
->where(['products.product_id'=>$product_id])
->first();
return $product->product_name;
}
what am i doing is, i am getting the first shipping id and store it and i made a condition if they are thesame then i go concat the productname but, i see my logic is bad.
Please help me in other way. Something like This line of code to begin with:
foreach ($ids as $product) {
$productname = $this->getproductname($product[0][product_id]);
//code for concat goes here
}
public function getproductname($product_id) {
$product = DB::table('products')->select('product_name')
->where(['products.product_id'=>$product_id])
->first();
return $product->product_name;
}
Adjust below to your actual data, let me know if you have questions.
<?php
$concat = array();
$array = array( array( 'product_id'=>1, 'shipping_id'=>1, 'product_name' => 'a' ), array( 'product_id'=>2, 'shipping_id'=>1, 'product_name' => 'b' ), array( 'product_id'=>3, 'shipping_id'=>2, 'product_name' => 'c' ), array( 'product_id'=>4, 'shipping_id'=>1, 'product_name' => 'd' ) );
foreach( $array as $row ) {
if( isset( $concat[ $row['shipping_id'] ] ) ) {
$concat[ $row['shipping_id'] ] .= ',' . $row['product_name'];
} else {
$concat[ $row['shipping_id'] ] .= $row['product_name'];
}
}
var_dump( $concat );
?>

Appending SQL to existing associative array

Learning PHP and creating associative arrays.
Trying to create associative array that describes an activity. An activity for this example is 354 and 355.
This is my current code:
$query = $db->prepare('SELECT item_id FROM kh_program_item_info WHERE '. $where);
$query->execute();
if($query->rowCount() > 0){
while($john = $query->fetch(PDO::FETCH_OBJ)){
$key1 = $john->item_id;
$report-> $key1= array();
}
foreach ($report as $key=>$johnval) {
$where = 'item_id = ' . $key;
$query = $db->prepare('SELECT activity_desc, DATE_FORMAT(activity_date,"%d/%m/%Y") AS activityDate FROM kh_program_items WHERE '. $where);
$query->execute();
$results = $query->fetch(PDO::FETCH_OBJ);
$report->$key = $results;
echo '<pre>';
echo print_r($report);
echo '</pre>';
}
} else {
echo '<p>there are no activities</p>';
}
this will yield results.
stdClass Object
(
[354] => stdClass Object
(
[activity_desc] => <p>Send Activity</p>
[activityDate] => 08/11/2016
)
[355] => stdClass Object
(
[activity_desc] => <p>Send Activity 2</p>
[activityDate] => 11/11/2016
)
)
I am now trying to add more information for 354 and 355.
I have revisited the code and here is new code:
$query = $db->prepare('SELECT item_id FROM kh_program_item_info WHERE '. $where);
$query->execute();
if($query->rowCount() > 0){
while($john = $query->fetch(PDO::FETCH_OBJ)){
$key1 = $john->item_id;
$report-> $key1= array();
}
foreach ($report as $key=>$johnval) {
$where = 'item_id = ' . $key;
$query = $db->prepare('SELECT activity_desc, DATE_FORMAT(activity_date,"%d/%m/%Y") AS activityDate FROM kh_program_items WHERE '. $where);
$query->execute();
$results = $query->fetch(PDO::FETCH_OBJ);
$report->$key = $results;
$query = $db->prepare('SELECT info_value FROM kh_program_item_info WHERE '. $where .' AND info_type="program_category"');
$query->execute();
$info_value = $query->fetch(PDO::FETCH_OBJ);
$where = 'category_id = ' . $info_value->info_value;
$query = $db->prepare('SELECT category_name FROM kh_program_categories WHERE '. $where);
$query->execute();
$actcategories = $query->fetch(PDO::FETCH_OBJ);
$report->$key = $actcategories;
echo '<pre>';
echo print_r($report);
echo '</pre>';
}
} else {
echo '<p>there are no activities</p>';
}
this will obviously overwrite what I have created and yield the following results:
stdClass Object
(
[354] => stdClass Object
(
[category_name] => Parent Input
)
[355] => stdClass Object
(
[category_name] => Children's Menu
)
)
The problem is $myactivity->$key = $actcategories;.
How do I append to the end without overwriting information?
I need to yield this result
stdClass Object
(
[354] => stdClass Object
(
[activity_desc] => <p>Send Activity</p>
[activityDate] => 08/11/2016
[category_name] => Parent Input
)
[355] => stdClass Object
(
[activity_desc] => <p>Send Activity 2</p>
[activityDate] => 11/11/2016
[category_name] => Children's Menu
)
)
Thanks in advance.
You'll need to build your array first and then, send it to the object.
i.e. :
foreach ($report as $key=>$johnval) {
$where = 'item_id = ' . $key;
$query = $db->prepare('SELECT activity_desc, DATE_FORMAT(activity_date,"%d/%m/%Y") AS activityDate FROM kh_program_items WHERE '. $where);
$query->execute();
// build first array
$result_first_query = $query->fetch(PDO::FETCH_OBJ);
$query = $db->prepare('SELECT info_value FROM kh_program_item_info WHERE '. $where .' AND info_type="program_category"');
$query->execute();
$info_value = $query->fetch(PDO::FETCH_OBJ);
$where = 'category_id = ' . $info_value->info_value;
$query = $db->prepare('SELECT category_name FROM kh_program_categories WHERE '. $where);
$query->execute();
// build second array
$result_second_query = $query->fetch(PDO::FETCH_OBJ);
// put them together in $report->$key
$report->$key = $result_first_query + $result_second_query;
echo '<pre>';
print_r($report);
echo '</pre>';
}
Hope it helps.
I did manage to push after i used fetch_assoc.
I guess it was just format it didnt like but thank you.

how can get count field in crirteria?

I'm trying to build a query that has a group by user_id, select user_id,count(id) , condition, join.
i can get a true result by findall command but only i can not show count(id)
i left my code here
in controller
$criteria=new CDbcriteria();
$criteria->condition = 'serviceId=:serviceId';
$criteria->params = array(':serviceId'=>1);
$criteria->group = 't.user_Id';
$criteria->select = array('t.user_Id,count(psh_profile_information_services.id) AS count');
$criteria->join = 'left join psh_profile_information_services on t.id=psh_profile_information_services.profileInformationId';
$moli= ProfileInformation::model()->findAll($criteria);
$this->render('conectionpoint', array('moli'=>$moli ));
in view
foreach ($moli as $mol)
{
echo "user_Id: ".$mol->user_id." --- count:".???????? ;
}
print $mol
ProfileInformation Object ( [_new:CActiveRecord:private] => [_attributes:CActiveRecord:private] => Array ( [user_Id] => 1 [createDate] => 1393/03/23 - 15:49:26 [modifiedDate] => 1393/03/23 - 15:49:26 ) [_related:CActiveRecord:private] => Array ( ) [_c:CActiveRecord:private] => [_pk:CActiveRecord:private] => [_alias:CActiveRecord:private] => t [_errors:CModel:private] => Array ( ) [_validators:CModel:private] => [_scenario:CModel:private] => update [_e:CComponent:private] => [_m:CComponent:private] => )
In ProfileInformation class file -
class ProfileInformation extends ActiveRecord
{
$public $total_info;
[....] //Rest of the code.
In Controller Action,
change -
$criteria->select = array('t.user_Id,count(psh_profile_information_services.id) AS count');
to
$criteria->select = array('t.user_Id,count(psh_profile_information_services.id) AS total_info');
In view file -
foreach ($moli as $mol)
{
echo "user_Id: ".$mol->user_id." --- count:".$mol->total_info;
}
This should work fine.
If not, then just do simple debug -
echo "<pre>";
foreach($moli as $mol) {
echo 'Total Info: ' . $mol->total_info . "<br />";
foreach($mol as $key => $value) {
echo $key . ' ' . $value . "<br />";
}
echo "<br />";
}
exit();
and check the values.

Categories