HTML Button calling controller/action - yii

I am trying to create html button in Yii on button click I want to call a UserController.php and Actioncreate .
I am doing like this ,
echo CHtml::button('Signup', array('button' => array('Users/create'))); ?>
But it's giving me following error
htmlspecialchars() expects parameter 1 to be string, array given
This is stack trace
D:\wamp\www\yii\framework\web\helpers\CHtml.php(85)
73 */
74 public static $liveEvents = true;
75
76 /**
77 * Encodes special characters into HTML entities.
78 * The {#link CApplication::charset application charset} will be used for encoding.
79 * #param string $text data to be encoded
80 * #return string the encoded data
81 * #see http://www.php.net/manual/en/function.htmlspecialchars.php
82 */
83 public static function encode($text)
84 {
85 return htmlspecialchars($text,ENT_QUOTES,Yii::app()->charset);
86 }
87
88 /**
89 * Decodes special HTML entities back to the corresponding characters.
90 * This is the opposite of {#link encode()}.
91 * #param string $text data to be decoded
92 * #return string the decoded data
93 * #see http://www.php.net/manual/en/function.htmlspecialchars-decode.php
94 * #since 1.1.8
95 */
96 public static function decode($text)
97 {
Stack Trace
#0
+
D:\wamp\www\yii\framework\web\helpers\CHtml.php(85): htmlspecialchars(array("Users/create"), 3, "UTF-8")
#1
+
D:\wamp\www\yii\framework\web\helpers\CHtml.php(2216): CHtml::encode(array("Users/create"))
#2
+
D:\wamp\www\yii\framework\web\helpers\CHtml.php(140): CHtml::renderAttributes(array("button" => array("Users/create"), "name" => "yt1", "type" => "button", "value" => "Signup"))
#3
+
D:\wamp\www\yii\framework\web\helpers\CHtml.php(436): CHtml::tag("input", array("button" => array("Users/create"), "name" => "yt1", "type" => "button", "value" => "Signup"))
#4
–
D:\wamp\www\nurseweb\protected\views\site\login.php(50): CHtml::button("Signup", array("button" => array("Users/create")))
45 <?php echo $form->error($model,'rememberMe'); ?>
46 </div>
47
48 <div class="row buttons">
49 <?php echo CHtml::submitButton('Login');
50 echo CHtml::button('Signup', array('button' => array('Users/create'))); ?>
51 <?php $this->endWidget(); ?>
52 </div><!-- form -->
#5
+
D:\wamp\www\yii\framework\web\CBaseController.php(127): require("D:\wamp\www\nurseweb\protected\views\site\login.php")
#6
+
D:\wamp\www\yii\framework\web\CBaseController.php(96): CBaseController->renderInternal("D:\wamp\www\nurseweb\protected\views\site\login.php", array("model" => LoginForm), true)
#7
+
D:\wamp\www\yii\framework\web\CController.php(870): CBaseController->renderFile("D:\wamp\www\nurseweb\protected\views\site\login.php", array("model" => LoginForm), true)
#8
+
D:\wamp\www\yii\framework\web\CController.php(783): CController->renderPartial("login", array("model" => LoginForm), true)
#9
–
D:\wamp\www\nurseweb\protected\controllers\SiteController.php(98): CController->render("login", array("model" => LoginForm))
093 // validate user input and redirect to the previous page if valid
094 if($model->validate() && $model->login())
095 $this->redirect(Yii::app()->user->returnUrl);
096 }
097 // display the login form
098 $this->render('login',array('model'=>$model));
099 }
100
101 /**
102 * Logs out the current user and redirect to homepage.
103 */
#10
+
D:\wamp\www\yii\framework\web\actions\CInlineAction.php(50): SiteController->actionLogin()
#11
+
D:\wamp\www\yii\framework\web\CController.php(309): CInlineAction->runWithParams(array("r" => "site/login"))
#12
+
D:\wamp\www\yii\framework\web\CController.php(287): CController->runAction(CInlineAction)
#13
+
D:\wamp\www\yii\framework\web\CController.php(266): CController->runActionWithFilters(CInlineAction, array())
#14
+
D:\wamp\www\yii\framework\web\CWebApplication.php(283): CController->run("login")
#15
+
D:\wamp\www\yii\framework\web\CWebApplication.php(142): CWebApplication->runController("site/login")
#16
+
D:\wamp\www\yii\framework\base\CApplication.php(162): CWebApplication->processRequest()
#17
–
D:\wamp\www\nurseweb\index.php(13): CApplication->run()
08 defined('YII_DEBUG') or define('YII_DEBUG',true);
09 // specify how many levels of call stack should be shown in each log message
10 defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);
11
12 require_once($yii);
13 Yii::createWebApplication($config)->run();
Can anyone tell me what the meaning of this error is and also guided me for the solution?

The CHtml button() method is literally just a button, the second parameter it accepts should be an array of key/value pairs, rather than an array of arrays (like you have in your example) see CHtml::button() for more info. A way to use this method would be for example;
echo CHtml::button('myButton',array(
'class' => 'buttonClass',
'id' => 'buttonId',
));
This would output something like:
<input class="buttonClass" id="buttonId" name="yt1" type="button" value="myButton">
If you want a button to submit a form, you can use CHtml::submitButton() which will submit the form it is contained within.
If you want a button to actually redirect the user to a separate page without submitting anything then I think the best solution would be use an image with an anchor link, or use jQuery to redirect the user once the button has been pressed.
If that's the case, here's a question with a couple of answers that might help you out: How to make a button redirect to another page using jQuery or just Javascript

Related

Cakephp 3: view.ctp sum two variables

I have a view that shows an associated array of Revenues. I have made a collection in the controller to isolate two variables that I need to add together and display as currency.
public function view($id = null)
{
$annualOperatingBudget = $this->AnnualOperatingBudgets->get($id, [
'contain' => ['Azinstitutions', 'BudgetExpenses', 'BudgetExpenses.ExpenseTitles', 'BudgetRevenues', 'BudgetRevenues.RevenueTitles']
]);
$collection = new Collection($annualOperatingBudget->budget_revenues);
$revenuesGroup1 = $collection->match(['revenue_title.revenue_group' => 1 ]);
$revenuesGroup2 = $collection->match(['revenue_title.revenue_group' => 2 ]);
$tuitionAndFees = $collection->match(['revenue_title.revenue_title' => 'Tuition and Fees']);
$lessScholarshipAllowance = $collection->match(['revenue_title.revenue_title' => '- less Scholarship Allowance']);
$this->set(compact('annualOperatingBudget', $annualOperatingBudget,'revenuesGroup1', 'revenuesGroup2', 'tuitionAndFees', 'lessScholarshipAllowance'));
}
I am able to see the variables with the debug kit:
annualOperatingBudget (array)
revenuesGroup1 (array)
revenuesGroup2 (array)
tuitionAndFees (array)
4 (App\Model\Entity\BudgetRevenue)
id 5
annual_operating_budget_id 1
revenue 1278
revenue_title_id 5
revenue_title (array)
lessScholarshipAllowance (array)
5 (App\Model\Entity\BudgetRevenue)
id 6
annual_operating_budget_id 1
revenue -257
revenue_title_id 6
revenue_title (array)
I would like to add the two 'revenue' s together
I tried:
<?= $this->Number->currency(
($tuitionAndFees->revenue) + ($lessScholarShipAllowance->revenue),
'USD', ['places' => 1])
?>
But I get several errors:
Notice (8): Undefined property: Cake\Collection\Iterator\FilterIterator::$revenue [ROOT\plugins\Twit\src\Template\AnnualOperatingBudgets\view.ctp, line 49]
Notice (8): Undefined variable: lessScholarShipAllowance [ROOT\plugins\Twit\src\Template\AnnualOperatingBudgets\view.ctp, line 49]
Notice (8): Trying to get property of non-object [ROOT\plugins\Twit\src\Template\AnnualOperatingBudgets\view.ctp, line 49]
You have to iterate the $tuitionAndFees and the $lessScholarShipAllowance before trying to get the revenue property. Something like this:
foreach($tuitionAndFees as $tuitionAndFee){
echo $tuitionAndFee->revenue
}
If all you need in the view is the total of all tuition and fees, you can use
$tuitionAndFees = $collection
->match(['revenue_title.revenue_title' => 'Tuition and Fees'])
->sumOf('revenue');
This will return just the sum of the matched items. Do something similar for $lessScholarShipAllowance, and then in your view, simply
$this->Number->currency($tuitionAndFees + $lessScholarShipAllowance,
'USD', ['places' => 1])

phql changed when executing using modelsManager

I'm new to Phalcon and would like to create a PHP web-service on my WAMP server. I have a table called "coreswings" in MySQL database and it represents the cores and wings of a large building. There are five fields: abbr, name, type, busyFrom, busyTo.
Following the tutorial on http://docs.phalconphp.com/en/latest/reference/tutorial-rest.html , I can route my requests to my desired functions, but the phql, "SELECT * FROM coreswings", doesn't work and returns me fatal errors.
index.php
<?php
/*###########################################################################
########## Set up connection to be used by model CoresWings, start ##########
###########################################################################*/
// use Loader() to autoload the model
$loader = new \Phalcon\Loader();
$loader->registerDirs(array(__DIR__.'/models/'))->register();
$di = new \Phalcon\DI\FactoryDefault();
// set up the database service
$di->set('db', function(){
return new \Phalcon\Db\Adapter\Pdo\Mysql(array(
"host" => "localhost",
"username" => "user",
"password" => "user_pw",
"dbname" => "map"
));
});
// create and bind the DI to the application
$app = new \Phalcon\Mvc\Micro($di);
/*#########################################################################
########## Set up connection to be used by model CoresWings, end ##########
#########################################################################*/
/*#########################################################
########## create routes according to api, start ##########
#########################################################*/
// get all cores and wings
$app->get('/coresWings', function() use ($app){
$phql = "SELECT * FROM coreswings";
$coresWings = $app->modelsManager->executeQuery($phql);
$data = array();
foreach($coresWings as $coreWing){
$data[] = array(
'abbr' => $coreWing->abbr,
'name' => $coreWing->name,
'type' => $coreWing->type,
'busyFrom' => $coreWing->busyFrom,
'busyTo' => $coreWing->busyTo,
);
}
echo json_encode($data);
});
// testing purpose
$app->get('/testing', function(){
$data = array(
'function' => 'tesing',
'data' => '001'
);
echo json_encode($data);
});
/*#######################################################
########## create routes according to api, end ##########
#######################################################*/
$app->handle();
?>
When I access the URL http://localhost/FYP/001/api/coresWings, the following errors are shown:
( ! ) Fatal error: Uncaught exception 'Phalcon\Mvc\Model\Exception' with message 'Table "cores_wings"
doesn't exist on database when dumping meta-data for CoresWings' in
D:\Program Files\wamp\www\FYP\001\api\index.php on line 39
( ! ) Phalcon\Mvc\Model\Exception: Table "cores_wings" doesn't exist on database when dumping meta-data for CoresWings in D:\Program Files\wamp\www\FYP\001\api\index.php on line 39
Of course I don't have a table called "cores_wings", but my phql is "SELECT * FROM coreswings". Please tell me if I have done anything wrong. Thanks so much.
#
mysql> describe coreswings;
+----------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------------------+------+-----+---------+-------+
| abbr | varchar(63) | NO | PRI | NULL | |
| name | varchar(1024) | YES | | NULL | |
| type | enum('core','wing') | NO | | NULL | |
| busyFrom | time | YES | | NULL | |
| busyTo | time | YES | | NULL | |
+----------+---------------------+------+-----+---------+-------+
Model: CoresWings.php
use Phalcon\Mvc\Model,
Phalcon\Mvc\Model\Message,
Phalcon\Mvc\Model\Validator\InclusionIn,
Phalcon\Mvc\Model\Validator\Uniqueness;
class CoresWings extends Model{
public function validation(){
// building type must be "core" or "wing"
$this->validate(new InclusionIn(
array(
"field" => "type",
"domain" => array("core", "wing")
)
));
// building abbreviation must be unique
$this->validate(new Uniqueness(
array(
"field" => "abbr",
"message" => "Abbreviation of a building must be unique"
)
));
// check if any messages have been produced
if($this->validationHasFailed()==true){
return false;
}
}
}
?>
If you want minimal configuration then you should follow some PhalconPHP's conventions.
One of them is that it for CamelCaseModel PhalconPHP uses camel_case table.
If you want to set different tabel for model then you should set it's source:
class CoresWings extends Model{
public function initialize() {
$this->setSource('coreswings');
}
}
You can use Phalcon\Mvc\Model::getSource() method. It is table name map with manual.

How to put contrasting information into a CGridView column based on a condition?

I'm looking into showing/hiding specific column data on a CGridView widget for the Wii Framework.
I have a CButtonColumn which contains 3 buttons. However, on certain conditions, I want to display something different for a particular row.
I have 3 different conditions which determin what gets displayed for particular row.
The following illustrates what I want to do:
| 1 | Title A | [hide][view][update] <-- if (condition == 'a')
| 2 | Title B | [hide][view][update] <-- if (condition == 'a')
| 3 | Title C | display text or link or button <-- if (condition == 'b')
| 4 | Title D | display alternative buttons <-- if (condition == 'c')
What is my best approach to take here?
I can't use 'visible'=> $model->processingStatus != "processed" on the column because this will remove the whole column. I need to target each row insatead.
Should I use the 'visible' parameter on each individual button? I have tried this using the commented out code below but it breaks the page.
FYI: I have successfully tried the 'visible' parameter on the CButtonColumn itself, but its not what I need. Plus not sure which row's status it is reading.
Or should I add a function to the controller? Have it do the if/else statements and return back what is to be displayed. How would this work?
Here is my code:
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'my-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
array(
'name'=>'myid',
'header'=>'ID',
),
'Title',
array(
'class'=>'CButtonColumn',
'visible'=> $model->status != "done",
'template'=>'{hide}{view}{update}',
'buttons'=>array(
'hide'=>array(
'label'=>'Hide', //Text label of the button.
'imageUrl'=>Yii::app()->request->baseUrl . '/img/icons/bulb-off.png' //Image URL of the button.
//'click'=>'function(){alert("Toggle Hide!");}', //A JS function to be invoked when the button is clicked.
//'options'=>array(), //HTML options for the button tag.
//'url'=>'javascript:void(0)', //A PHP expression for generating the URL of the button.
//'visible'=> $model->status == "done", //A PHP expression for determining whether the button is visible.
),
'view'=>array(
//Text label of the button.
'label'=>'View',
//Image URL of the button.
'imageUrl'=>Yii::app()->request->baseUrl . '/img/icons/view-record.png'
),
'update'=>array(
'label'=>'Update/Edit',
'imageUrl'=>Yii::app()->request->baseUrl . '/img/icons/edit-pencil.png',
'url'=>'Yii::app()->createUrl("metadataandchapters/create?bookid=" . $data->bookid)',
)
)
)
)
)); ?>
Hope I am making good enough sense here!
You should use visible button option, but it should be a PHP expression string, e.g. :
'visible'=> '$data->status == "done"',
http://www.yiiframework.com/doc/api/1.1/CButtonColumn#buttons-detail
Extend CButtonColumn with your own class, then you should be able to change this function to whatever you need to render or hide buttons or do any changes you want.
/**
* Renders a link button.
* #param string $id the ID of the button
* #param array $button the button configuration which may contain 'label', 'url', 'data-icon', 'imageUrl' and 'options' elements.
* #param integer $row the row number (zero-based)
* #param mixed $data the data object associated with the row
*/
protected function renderButton($id, $button, $row, $data)
More details about the function http://www.yiiframework.com/doc/api/1.1/CButtonColumn#renderButton-detail

How to use Yii CArrayDataProvider

I am new to php and Yii and need some help regarding showing array in the webpage.
In the controller I open my e-mail inbox and iterate through the e-mails in inbox and build array with each e-mail address as key having values
if (array_key_exists($fromemail,$senders))
{ $senders[$fromemail]['rcount']++; }
else {
$senders[$fromemail]['e-mail'] = $fromemail;
$senders[$fromemail]['Name'] = $fromname;
$senders[$fromemail]['rcount'] = 1;
}
$model->top_senders = $senders;
$this->render('Step2',array('model'=>$model,));
Then in the view file of Step2 I want to show the data in CGridview
if (isset($model->top_senders))
{
$gridDataProvider = new CArrayDataProvider($model->top_senders);
$gridDataProvider->setData($model->top_senders);
$gridColumns = array(
array('name'=>'e-mail', 'header'=>'E-mail','value' =>'$data->e-mail'),
array('name'=>'rcount', 'header'=>'# of mails','value'=>'$data->rcount'),);
$this->widget('bootstrap.widgets.TbGridView',array('dataProvider' => $gridDataProvider,'template' => "{items}",'columns'=>$gridColumns));
}
But I will get error during rendering of the table: PHP notice Undefined offset: 0
/**
125 * Renders a data cell.
126 * #param integer $row the row number (zero-based)
127 */
128 public function renderDataCell($row)
129 {
130 $data=$this->grid->dataProvider->data[$row];
What I am doing wrong? Can anyone help me?
You should't add data to provider as follows:
$gridDataProvider->setData($model->top_senders);
It added during initialization. You must be sure that the array has a key id, otherwise you need to specify it manually (it must be unique) as follows:
$gridDataProvider = new CArrayDataProvider($model->top_senders, array(
'id'=>'Name',
));
You will also need to make sure that the array $model->top_senders has the following structure:
array(
'0'=>array(...user data here),
'1'=>array(...user data here),
...
);
If you var_dump($gridDataProvider->data) you'd notice there's no value for the 0th index in the array. This happens when you run some filter function on the array. Assuming there are 5 values in the filtered array, the filtered array would look something like this when var_dump'd.
array(5) {
[1] => Object (Mailer) {…},
[2] => Object (Mailer) {…},
[4] => Object (Mailer) {…},
[8] => Object (Mailer) {…},
[9] => Object (Mailer) {…},
}
A filter operation on an array can leave the array looking like the above.
When the CGridView is trying to feed the view with data, it does it sequentially—this, I find, is a shortcoming in Yii and should be raised as an issue.
In order to fix this, use PHP's array_values() like so…
$properly_indexed_array = array_values($filtered_array);
This will copy the values of the filtered array into a new array. This is not the optimal solution in terms of memory. So far, I do not see any means in PHP other than this though.
You may then go ahead and set this as the data for your data provider like so…
$gridDataProvider->setData($properly_indexed_array);

Does session upload progress work with nginx and php-fpm?

I'm running nginx 1.2.3 / php-fpm 5.4.6 and trying to use the Session upload progress feature. During an upload $_SESSION never contains any upload data whatsoever. At first I assumed coding errors, but even the most simple/basic upload progress tests failed to produce anything within $_SESSION.
I now suspect that the file is being POSTed directly to nginx, which completely handles the upload from beginning to end, THEN nginx passes the upload on to php-fpm so quickly that there is no real "progress" to report. Am I correct in this assessment? If so, how can I get around this?
phpconfig confirms that the session.upload settings are all set correctly.
Below is the current test code, borrowed from this blog.
<?php
/* File upload progress in PHP 5.4 */
/* needs a 5.4+ version */
$version = explode( '.', phpversion() );
if ( ($version[0] * 10000 + $version[1] * 100 + $version[2]) < 50400 )
die( 'PHP 5.4.0 or higher is required' );
if ( !intval(ini_get('session.upload_progress.enabled')) )
die( 'session.upload_progress.enabled is not enabled' );
session_start();
if ( isset( $_GET['progress'] ) ) {
$progress_key = strtolower(ini_get("session.upload_progress.prefix").'demo');
if ( !isset( $_SESSION[$progress_key] ) ) exit( "uploading..." );
$upload_progress = $_SESSION[$progress_key];
/* get percentage */
$progress = round( ($upload_progress['bytes_processed'] / $upload_progress['content_length']) * 100, 2 );
exit( "Upload progress: $progress%" );
}
?>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<?php if ( isset($_GET['iframe']) ): /* thank you Webkit... */ ?>
<form action="" method="POST" enctype="multipart/form-data">
<input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="demo">
<input type="file" name="uploaded_file">
<input type="submit" value="Upload">
</form>
<script type="text/javascript">
window.location.hash = ""; /* reset */
jQuery("form").bind("submit", function() { window.location.hash = "uploading"; });
</script>
<?php else: ?>
<iframe src="?iframe" id="upload_form"></iframe>
<script type="text/javascript">
jQuery(document).ready(init);
function init() {
/* start listening on submit */
update_file_upload_progress();
}
function update_file_upload_progress() {
if ( window.frames.upload_form.location.hash != "#uploading" ) {
setTimeout( update_file_upload_progress, 100 ); /* has upload started yet? */
return;
}
$.get( /* lather */
"?progress",
function(data) {
/* rinse */
jQuery("#file_upload_progress").html(data);
/* repeat */
setTimeout( update_file_upload_progress, 500 );
}
).error(function(jqXHR, error) { alert(error); });
}
</script>
<div id="file_upload_progress"></div>
<?php endif; ?>
A note in the documentation page on php.net says :
s.zarges 19-Jun-2012 09:32
Note, this feature doesn't work, when your webserver is runnig PHP via FastCGI. There will be no progress informations in the session array.
Unfortunately PHP gets the data only after the upload is completed and can't show any progress.