i have a joomla component for making appointments and i have checkboxes for starting dates of the appointments...my problem is that i can only make one appointment at a time,i want to be able to check multiple boxes so the values for those boxes can be saved in mysql,when i check multiple checkboxes only the last checked is saved in database...
here is the code from joomla component that i think that has to be adjusted so help guys if you can...
this is the code for checkbox...
$timetableHTML .= '<td class="timeSlot timeFree" ><input type="checkbox" name="appointment[]" value="'.$startKey.'" onclick="changeTimes(\''.$calendar->min_duration.'\',\''.$startKey.'\',\''.$endKey.'\')"/></td>';
and this is the save function in controller of the component...
function save() {
global $app;
JRequest::checkToken() or jexit( 'Invalid Token' );
$db =& JFactory::getDBO();
$row =& JTable::getInstance('appointments', 'Table');
$post = JRequest::get( 'post',4 );
if (!$row->bind( $post )) { JError::raiseError(500, $row->getError() ); }
for ($i=1;$i<=10;$i++) {
if (is_array($row->{'field'.$i})) $row->{'field'.$i} = implode('|',$row->{'field'.$i}); $row->{'field'.$i} = strip_tags($row->{'field'.$i});
}
if (!$row->check()) { JError::raiseError(500, $row->getError() ); }
if (!$row->store()) { JError::raiseError(500, $row->getError() ); }
$row->checkin();
if ($this->config->emails){
$this->notifyOwner(array($row->id));
$this->notifyAppointee(array($row->id));
}
$url = JRoute::_('index.php?option=com_jxtcappbook'.(JRequest::getInt( 'pop', 0) ? '&view=complete&tmpl=component' : ''));
$this->setRedirect($url ,JText::_( 'Termin je zakazan!'.$pop ));
}
i googled a bit and i think i need to set jrequest::get with array,am i right?
Assuming Joomla >1.6. Since you use JRequest a fair amount:
$appointments = JRequest::getVar('appointments', null, 'post', 'array');
or better yet since this will be deprecated post 3.0 you can use JInput:
$jinput = JFactory::getApplication()->input;
$appointments = $jinput->post->get('appointments', 'null', 'ARRAY');
Sanitize input and add to DB:
foreach (array_keys($appointments ) as $element) {
$myappointments[] = $db->quote($element);
}
// construct query using implode and use comma separator
$myappointments = implode(',', $myappointments );
$db =& JFactory::getDBO();
$query = $db->getQuery(true);
$query = sprintf('UPDATE $db->quoteName(#__mytable) SET $db->quote(...) WHERE $db->quote(...) IN (%s)', $myappointments );
$db->setQuery($query);
$db->query();
You get the idea...
EDIT (based on your comment):
I still don't know what you are trying to achieve. So it is hard for me to provide direction. I'll take another stab at it. I'm guessing you want to take the values that are checked from the form and put that into the database.
//this pulls out the values in an array of all the things that have been "checked" (selected in the checkbox)
$jinput = JFactory::getApplication()->input;
$appointments = $jinput->post->get('appointments', 'null', 'ARRAY');
//**This is not code you need** I just want to illustrate what you are getting.
//This is looping through the values of the checkboxes to see what you have
for($i=0; $i < count($appointments); $i++){
echo "Selected " . $appointments[$i];
}
The code I provided before shows you how to take the values and store into a DB. I can't give instructions on the DB because I don't know the DB structure.
Related
I dont know why after clicking the "Add Button", the items that needs to insert into the database is NULL.
so here's my controller
public function addItem(){
$data = array(
"item_ID"=>$_POST['item_ID'],
"itemName"=>$_POST['itemName'],
"itemDescription"=>$_POST['itemDescription'],
"itemLink"=>$_POST['itemLink']
);
$orgID = $this->model->get_org();
$this->model->insertItem($data,$orgID);
}
and here's my model
public function insertItem($data,$orgID){
$this->db->insert('Items',$data);
$getID=$this->db->insert_id();
foreach($orgID as $temp):
$Organization_ID = $_POST[$temp->OrganizationID];
endforeach;
$SkillReq=$this->input->post('0');
$Skill_ReqID=$this->input->post();
$insertdata = array();
for($i=0; $i=count($orgID); $i++){
$insertdata[]=array(
'Skill_ReqID'=>$Skill_ReqID[$i],
'OrganizationID'=>$Organization_ID[$i],
'item_ID'=>$getID[$i],
'SkillReq'=>$SkillReq[$i]
);
}
$this->db->insert_batch('skillreqdept',$insertdata);
}
it actually inserts the rows that had been counted in orgID but there is no data, only the Auto Incremented skill_reqID has in it.
I thing the issue is with Skill_ReqID'=>null[$i], I dont know what is null variable.
Please try the following:
public function insertItem($data,$orgID){
$this->db->insert('Items',$data);
$getID=$this->db->insert_id();
foreach($orgID as $temp):
$Organization_ID = $_POST[$temp->OrganizationID];
endforeach;
$SkillReq=$this->input->post('0');
$insertdata = array();
for($i=0; $i=count($orgID); $i++){
$items=array(
'OrganizationID'=>$Organization_ID[$i],
'itemID'=>$getID[$i],
'SkillReq'=>$SkillReq[$i]
);
array_push($insertdata, $items);
}
$this->db->insert_batch('skillreqdept',$insertdata);
}
Ya, it should be empty. Check your array "
public function addItem(){
$data = array(
'item_ID"=>$_POST['item_ID'], <== wrong wrapping
'itemName"=>$_POST['itemName'],
'itemDescription"=>$_POST['itemDescription'],
'itemLink"=>$_POST['itemLink']
);
$orgID = $this->model->get_org();
$this->model->insertItem($data,$orgID);
}
If you're using proper IDE, it will highlight such a minor issues like this
As well insertdata is any predefined PHP tag/function ??
As well what is this null[$i] assign. I never heard of it.
Before do insert use print_r to check data is in the correct format or not. print_r($insertdata); die;
function updateUser($userData, $statsID) {
$fields = '';
$config = 0;
while(list($key,$val)= each($userData)) {
if($config++ != 0){
$fields .= ' , ';
}
$col = $key;
$val = $val;
$fields .= "$col='$val'";
}
//echo $fields;
global $dbhandle;
$query = mysqli_query($dbhandle, "UPDATE data SET $fields WHERE statsID = '$statsID'");
echo var_export($query); <--returns NULL
In this code, I pass in an array as noted below:
$sendData = array('name'=>$name,'race'=>$race,'rank'=>$rank,'highestRank'=>$highestRank,'commander'=>$commander,'atkSld'=>$atkSld,'atkMerc'=>$atkMerc,'defSld'=>$defSld,'defMerc'=>$defMerc,'untSld'=>$untSld,'untMerc'=>$untMerc,'spies'=>$spies,'sentries'=>$sentries,'morale'=>$morale,'tff'=>$tff,'strike'=>$strike,'strikeRank'=>$strikeRank,'defense'=>$defense,'defenseRank'=>$defenseRank,'spy'=>$spy, 'spyRank'=>$spyRank, 'sentry'=>$sentry, 'sentryRank'=>$sentryRank, 'fort'=>$fort,'siege'=>$siege,'economy'=>$economy,'tech'=>$tech,'conscription'=>$conscription,'gold'=>$gold,'tbg'=>$tbg,'gameTurns'=>$gameTurns,'covertLvl'=>$covertLvl);
I have confirmed all the data is set and correct. The statsID passes in correctly and when I echo field, it gives me exactly what is required to fulfill my query and in the correct format (key='value' , key ='value' , key ='value etc)
EDIT: Problem solved, I have updated my code to reflect the solution. For some reason I had to call global $dbhandle prior to the query string. If someone could tell me why that would be great!
I am new to yii. I've created a custom in button in CGridView that has a class of CButtonColumn. I'm just wondering how can I pass parameters that I can add to my php function in my model.
This is my custom button in the table
array(
'class'=>'CButtonColumn',
'template'=>'{approve}, {update},{delete}',
'buttons'=>array(
'approve' => array(
'label'=>'Approve',
'options'=>array(),
'click'=>$model->approveRegistrants("$user_id, $category", array("id"=>$data->user_id , "category"=>$data->category),
)
)
)
and this is my function is
public function approveRegistrants($user_id, $category){
$db = new PDO('mysql:host=localhost; dbname=secret; charset=utf8', 'Andy', '*****');
$getCounter = "SELECT registrants FROM counter order by registrants desc limit 1;";
$bool = false;
$show = '0';
do{
$result = $db->query($getCounter);
// $registrants = $db->query($getCounter);
// $result->setFetchMode(PDO::FETCH_ASSOC);
// $registrants = '1';
foreach ($result as $value){
$registrants = $value['registrants'];
echo 'hello'.$registrants.'</br>';
}
// $registrants = $result['registrants'];
// print_r($registrants);
$max_registrants = '3400';
if($max_registrants > $registrants){
// pdo that will use $updateCounterByOne
$updateCounterByOne = "UPDATE counter set registrants = registrants + 1 WHERE registrants = ". $registrants .";";
$updateCounter = $db->prepare($updateCounterByOne);
$updateCounter->execute();
// return affected rows
$returnAffectedRows = $updateCounter->rowCount();
$bool = true;
// break;
}
else{
echo "No more slot Available";
// break;
}
}while($returnAffectedRows == '0');
if($bool = true){
//sql syntax
$selectApprovedUser = "SELECT user_id FROM registrants WHERE user_id = '". $user_id ."';";
//pdo that will use $selectApprovedUser
$updateApprovedUser = "UPDATE registrants set approved = 'YES' where user_id = ". $selectApprovedUser .";";
$updateApproved = $db->prepare($updateApprovedUser);
$updateApproved->execute();
//pdo that will use $insertApprovedUser
$insertApprovedUser = "INSERT INTO approved_registrants (user_id, category, approved_date) VALUES ('".$user_id."', '".$category."', 'curdate()');";
$insertApproved = $db->prepare($insertApprovedUser);
$insertApproved->execute();
//execute trial
$selectSomething = "SELECT registrants from counter where tandem = '0'";
$doSelect = $db->prepare($selectSomething);
$doSelect->execute();
$hello = $doSelect->fetchAll();
echo $hello[0]['registrants'];
}
}
your issue is that you are bypassing the controller fully here.
buttons column is configured with the following parameters
'buttonID' => array(
'label'=>'...', // text label of the button
'url'=>'...', // a PHP expression for generating the URL of the button
'imageUrl'=>'...', // image URL of the button. If not set or false, a text link is used
'options'=>array(...), // HTML options for the button tag
'click'=>'...', // a JS function to be invoked when the button is clicked
'visible'=>'...', // a PHP expression for determining whether the button is visible
)
See CButtonColumn for details.
As you can see click has to be a js function that will be called on clicking the button. You can rewrite your button like this
array(
'class'=>'CButtonColumn',
'template'=>'{approve}, {update},{delete}',
'buttons'=>array(
'approve' => array(
'label'=>'Approve',
'options'=>array(),
// Alternative -1 Url Method -> will cause page to change to approve/id
'url'=>'array("approve","id"=>$data->id)',
// Alternative -2 Js method -> use 1,2 not both
'click'=>'js:approve()',
)
)
)
in your CGridView configuration you add
array(
....
'id'=>'gridViewID', //Unique ID for grid view
'rowHtmlOptionsExpression'=> 'array("id"=>$data->id)',
)
so that each row has the unique ID, ( you can do the same to a button, but it slightly more difficult as $data is not available there)
in your js function you can do this.
<script type="text/javascript">
function approve(){
id = $(this).parent().parent().attr("id");
<?php echo CHtml::ajax(array( // You also can directly write your ajax
'url'=>array('approve'),
'type'=>'GET',
'dataType'=>'json',
'data'=>array('id'=>'js:id'),
'success'=>'js:function(json){
$.fn.yiiGridView.update("gridViewID",{});
// this will refresh the view, you do some other logic here like a confirmation box etc
}'
));?>
}
</script>
Finally your approve action
class YourController extend CController {
......
public function actionApprove(){
id = Yii::app()->request->getQuery('id');
$dataModel = MyModel::model()->findByPk($id); // This is the model has the $user_id, and $category
....
$OtherModel->approve($dataModel->user_id,$dataModel->category) // if approve is in the same model you can self reference the values of category and user_id directly no need to pass as parameters.
// Do some logic based on returned value of $otherModel->approve()
// return the values from the approve() function and echo from here if required back to the view, directly echoing output makes it difficult to debug which function and where values are coming from .
Yii::app()->end();
}
I am having difficulty conceptualizing a recursive function for appending replies to comments, replies to replies, replies to replies to replies, etc.
This is my comments table:
Which SHOULD look something like this when rendered:
As it stands I can render each comment associated with the article_id (excluding those that are NOT NULL, of course):
$comments = $commentClass->fetch_article_comments($article_id);
foreach($comments as $comment) {
$comment_id = $comment['comment_id'];
$member_id = $comment['member_id'];
$comment_text = $comment['comment_text'];
$comment_timestamp = timeAgo($comment['comment_timestamp']); //get time ago
//render comment using above variables
}
Now I'm assuming I need to add a recursive function at the end of the above foreach statement, but I have yet to come up with anything remotely successful in appending the comments replies and the replies to each reply.
Can anyone help me accomplish this or perhaps point me in the right direction. I am not entirely familiar with recursive functions. I have done some scanning of the internet and on stackoverflow looking for something that helps, but haven't found anything helpful yet.
I did come across this post which recommended using a hierarchical database system, but I think I would prefer to use a php recursive function for this.
Thanks.
edit
By using the below answers I am only returning the results first comment and then it iterates and displays that one comment indefinitely. I can't figure out why?
My php:
function display_comments($article_id, $parent_id=0, $level=0) {
global $comment;
global $member;
global $signed_in;
global $username;
$comments = $comment->fetch_article_comments($article_id, $parent_id);
foreach($comments as $data) {
$comment_id = $data['comment_id'];
$c_member_id = $data['member_id'];
$comment_text = $data['comment_text'];
$comment_timestamp = timeAgo($data['comment_timestamp']); //get time ago
$member_data = $member->fetch_member_data($c_member_id);
$c_member_username = $member_data['member_username'];
$c_member_avatar = $member_data['member_avatar'];
//render HTML here
$parent = $data['comment_parent'];
display_comments($article_id, $parent, $level+1);
}//end foreach
}//end display_comments()
and my PDO query:
public function fetch_article_comments($article_id, $parent_id) { //$page = (int)(!isset($_GET['page'])) ? 0 : $_GET['page'];
if ($parent_id > 0) {
$parent_id = "= $parent_id";
} else {
$parent_id = "IS NULL";
}
$query = $this->db->prepare("SELECT * FROM `comments2` WHERE `article_id` = $article_id AND `comment_parent` $parent_id ORDER BY `comment_timestamp` DESC");
try{
$query->execute();
$comments = $query->fetchAll(); //returns an array
$query->closeCursor();
return $comments;
} catch(PDOException $e){
die($e->getMessage());
}
}
The core of the problem is this:
$comments = $commentClass->fetch_article_comments($article_id);
I assume, this function somwhere creates and runs SQL, that is similar to SELECT ... WHERE comments.article_id=$article_id. This is not sufficient - you need something like
$comments = $commentClass->fetch_article_comments($article_id, $parent_id);
that translates into SQL similar to SELECT ... WHERE comments.article_id=$article_id AND comments.comment_parent ($parent_id>0)?"=$parent_id":"IS NULL"
Now you can write your PHP function:
function display_comments ($article_id, $parent_id=0, $level=0) {
$comments = $commentClass->fetch_article_comments($article_id, $parent_id);
foreach($comments as $comment) {
$comment_id = $comment['comment_id'];
$member_id = $comment['member_id'];
$comment_text = $comment['comment_text'];
$comment_timestamp = timeAgo($comment['comment_timestamp']); //get time ago
//render comment using above variables
//Use $level to render the intendation level
//Recurse
display_comments ($article_id, $comment_id, $level+1);
}
}
And finally call it with display_comments ($article_id);
You could do something like:
function getCommentsForParent($parent="") {
echo "<div class=\"comment\">";
$db = get("select your db logics where parent = $parent");
foreach ($db as $comment) {
echo "print your comment in a box and make a div around the hole comments"
getCommentsForParent($comment['parent_id']);
}
echo "</div>";
}
invoke function with getCommentsForParent()
With your code it should be something like:
function getCommentForParent($parent="") {
global $commentsClass, $article_id;
$comments = $commentClass->fetch_article_comments($article_id,$parent);
foreach($comments as $comment) {
$comment_id = $comment['comment_id'];
$member_id = $comment['member_id'];
$comment_text = $comment['comment_text'];
$comment_timestamp = timeAgo($comment['comment_timestamp']); //get time ago
getCommentForParent($comment['parent']);
}
}
Look closely, ive adjusted your fetch article_comments. It now has a listener for $parent. Make sure that when your $parent = "", the class will only select the comments with empty parent.
invoke with getCommentsForParent()
It will automatically loop through the parent. Ofcourse this is highly conceptual but given your code you should get the hang of it.
I have an image upload that adds the filename to a table called attachments. If the id already exists then I want it to update and if not then create a new record. At the moment it creates a new record so I have multiple records forthe one id. The id's are from a table called Addon's.
I am not sure how to do this in cakephp.
if (!empty($this->data)) {
$this->layout = null;
//if(empty($this->data['AddOn']['id'])){unset($this->data['AddOn']);}
// restructure data for uploader plugin // NEED TO GET RID OF THIS ? MOVE IT
$tmp_file = $this->data['Attachment'][0]['file'];
$tmp_file['extension'] = array_reverse(explode('.', $tmp_file['name']));
$tmp_file['extension'] = $tmp_file['extension'][0];
$tmp_file['title'] = strtolower(substr($tmp_file['name'],0,(0-strlen('.'.$tmp_file['extension']))));
$this->data['Attachment'][0]['alternative'] = ucwords(str_replace('_',' ', $tmp_file['title']));
$previous = $this->AddOn->Attachment->find('first', array('conditions'=> array('model'=>'AddOn', 'foreign_key'=>$id)));
if( !empty( $previous ) ) {
$this->AddOn->Attachment->id = $previous[ 'Attachment' ][ 'id' ];
}
if ($this->AddOn->save($this->data, array('validate' => 'first'))) {
$id = $this->AddOn->Attachment->getLastInsertID();
$att = $this->AddOn->Attachment->query("SELECT * from attachments WHERE id = ".$id);
$this->set('attachment',$att[0]['attachments']);
} else {
$tmp_file['name'] = 'INVALID FILE TYPE';
}
//debug($this->data);
$this->set('file', $tmp_file);
$this->RequestHandler->renderAs($this, 'ajax');
$this->render('../elements/ajax');
}
save() and saveAll() automatically update an existing row if the id has been set. You can do something like:
$previous = $this->AddOn->Attachment->find( /* whatever conditions you need */ );
if( !empty( $previous ) ) {
$this->AddOn->Attachment->id = $previous[ 'Attachment' ][ 'id' ];
}
Now the old record will be updated if it exists.
As a side note, the code after a successful saveAll() doesn't make much sense: first you're saving data to the database, then immediately retrieving it again. You can just keep using $this->data that already has the same content.
And another side note: you should use query() only as a last resort when you can't use Cake's other methods. query("SELECT * from attachments WHERE id = ".$id) is a trivial case that can be rewritten as $this->Model->id = $id; $this->Model->read(); or using a simple $this->Model->find() query.