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
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
)
)
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>';
}
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 );
?>
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.
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.