how to access a function defined in app_controller from a ctp - cakephp

I have function in app_controller.php.The function is like:
function globalSum($Var1,$Var2)
{
$Var3 = $Var1 + $Var2;
return $Var3;
}
Now I want to access this function from any CTP file to get the value after sum.when I call this function the arments will be send from the ctp file.
So,anybody can tell me how to call this function with arguments from the ctp file??
Thanks in advance..

The way you're trying to do this probably isn't the best, seeing as it's working against the MVC architecture that CakePHP uses.
In MVC, the ctp file is your view and should only act as a template, to the greatest extent possible, with any values that you need in the view should be passed to it from the controller.
You have a number of simple solutions to your problem.
One is simply to do the addition in the view:
index.ctp
<?php
echo $var1 + $var2
?>
For such a simple operation, why bother with a separate function?
If your function is more complicated, you can put it in the AppController and then set the view variable in the controller that the action belongs to. For example:
app_controller.php
<?php
function globalSum($Var1,$Var2) {
$Var3 = $Var1 + $Var2;
return $Var3;
}
?>
posts_controller.php
<?php
function index() {
$this->set('var3', $this->globalSum($var1,$var2));
}
?>
index.ctp
<?php
echo $var3;
?>
Hope that helps.

Related

How to load/execute a view template from a string in CakePHP

I've developed a CakePHP plugin that allows the site administrator to define custom reports as a list of SQL queries that are executed and the results displayed by a .ctp template.
Now I need to allow the administrator to edit the template, stored in the DB together with the report.
Therefore I need to render a template that is inside a string and not in a .ctp file and I could not find anything in the core that helps.
I considered initially the approach to write the templates in .ctp files and load them from there, but I suspect this solution is rigged with flaws re: the location of the files and related permissions.
A better solution seems to override the View class and add a method to do this.
Can anyone suggest a better approach ?
P.S. Security is not a concern here, since the administrator is basically a developer without access to the code.
In CakePHP 2.0:
The View::render() method imports the template file using
include
The include statement includes and evaluates the specified file.
The evaluated template is immediately executed in whatever scope it was included. To duplicate this functionality, you would need to use
eval()
Caution: The eval() language construct is very dangerous because it
allows execution of arbitrary PHP code. Its use thus is discouraged.
If you have carefully verified that there is no other option than to
use this construct, pay special attention not to pass any user
provided data into it without properly validating it beforehand.
(This warning is speaking to you, specifically)
...if you wish to continue... Here is a basic example of how you might achieve this:
$name = 'world';
$template = 'Hello <?php echo $name ?>... <br />';
echo $template;
// Output: Hello ...
eval(' ?>' . $template . '<?php ');
// Output: Hello world...
Which is (almost) exactly the same as:
$name = 'world';
$template = 'Hello <?php echo $name ?>... <br />';
file_put_contents('path/to/template.php', $template);
include 'path/to/template.php';
Except people won't yell at you for using eval()
In your CakePHP application:
app/View/EvaluatorView.php
class EvaluatorView extends View
{
public function renderRaw($template, $data = [])
{
if (empty($data)) {
$data = $this->viewVars;
}
extract($data, EXTR_SKIP);
ob_start();
eval(' ?>' . $template . '<?php ');
$output = ob_get_clean();
return $output;
}
}
app/Controller/ReportsController.php
class ReportsController extends AppController
{
public function report()
{
$this->set('name', 'John Galt');
$this->set('template', 'Who is <?php echo $name; ?>?');
$this->viewClass = 'Evaluator';
}
}
app/View/Reports/report.ctp
// Content ...
$this->renderRaw($template);
Alternatively, you may want to check out existing templating engines like: Mustache, Twig, and Smarty.
Hmmm.. Maybe create a variable that will store the generated code and just 'echo' this variable in ctp file.
I had similar problem (cakephp 3)
Controller method:
public function preview($id = null) {
$this->loadModel('Templates');
$tempate = $this
->Templates
->findById($id)
->first();
if(is_null($template)) {
$this->Flash->error(__('Template not found'));
return $this->redirect($this->referer());
}
$html = $template->html_content;
$this->set(compact('html'));
}
And preview.ctp is just:
<?= $html

cakephp getLastInsertId not working

Here I have used cakephp js helper to send data,After insert One data I need this last id for farther work.Here I have tried bellow code in Addcontroller
if ($this->Patient->save($this->request->data)) {
$lastid=$this->Patient->getLastInsertId();
$patient=$this->Patient->find('all',array(
'conditions'=>array('Patient.id'=>$lastid ),
'recursive' => -1
));
$this->set('patient', $patient);
}
In add.ctp I have tried bellow code but I haven't get last id here.
<?php foreach ($patient as $patient): ?>
<?php echo h($patient['Patient']['id']); ?>
<?php endforeach; ?>
Method getLastInsertId() return id of just saved records.
If you need this id in your view just after save, you must first set that variable in your controller like $this->set(compact('lastid','patient'); and then use in view <?php echo $lastid; ?>
use
if ($this->Patient->save($this->request->data)) {
$id = $this->Patient->id;
$patient=$this->Patient->find('all',array('conditions'=>array('Patient.id'=>$id),'recursive' => -1));
$this->set->('patient', $patient);
//If you are saving the record with ajax which it looks like you
//might be from your question you will need the following instead
//of $this->set->('patient', $patient); try:
return json_encode($patient);
You will then also need to update your js ajax call, you will have a json array to decode so parse it with jquery and append it back into your view.
Cake will always give you the id of record you have just saved, by simply adding $id = $this->MyModel->id; You can use the id to query for the record.
Try below code:
In controller:
$lastid=$this->Patient->getLastInsertId();
$this->set(compact('lastid','patient');
Then use $lastid in View file.
In controller:
$lastid=$this->Patient->getLastInsertId();
$patient['Patient']['last_id'] = $lastid;
then use $patient['Patient']['last_id'] in your view file.

CakePHP: beforeSave not working with saveMany?

So, for some reason, anything I do to data in the beforeSave callback, though it works on single records, does not work when using saveMany.
What gives? If I do the following:
public function beforeSave() {
$this->data['foo'] = 'bar'
die($this->data);
}
I can see that in fact $this->data does DOES get changed, but saveMany just ignores it and saves the original data instead.
Make sure you include the model name when manipulating $this->data, e.g. $this->data['Event']['foo'] = bar. Be sure the method returns true as well or the save will fail.
Edit
I whipped up a quick example and it seems to be working for me, see the code below. My suspicion is that maybe you are calling saveMany incorrectly and passing it the whole $this->request->data object but it's hard to guess without seeing your call as well.
View
<?php echo $this->Form->create('ParentTable'); ?>
Record 1: <br />
<?php echo $this->Form->input('ParentTable.0.name'); ?>
Record 2: <br />
<?php echo $this->Form->input('ParentTable.1.name'); ?>
<?php echo $this->Form->end('Submit'); ?>
Controller
public function index() {
if ($this->request->data) {
$this->ParentTable->saveMany($this->request->data['ParentTable']);
}
}
Model
public function beforeSave() {
$this->data['ParentTable']['name'] .= ' modified';
return true;
}

CakePHP question: How can i call a view of one controller from another controller?

This is posts/index.php =>
<?php foreach ($allposts as $post) {
echo '<tr class="class_row">';
echo '<td>';
echo $this->Html->link($post['Post']['title'],
array('controller'=>'posts','action'=>'view',$post['Post']['id']),
array('id'=>'id_anchor_title','class'=>'class_anchor_title') );
echo '<tr>';
echo '<td>';
}
?>
I want to call this posts/index.ctp from products/index.ctp => It will be a generic/common index.ctp for all controller. How can i do this ?
In posts/index.ctp the $allposts is used. It's set in posts/index action. But when i will call posts/index.ctp from products/index action different variable is set there. Suppose $this->set('allproducts',$allproducts); is set in products/index action. Now how can i use that allproducts variable in posts/index.ctp ?
As #Vins stated, you can use $this->render('view_name'); at the end of your controller action to render a different view (In your case it should be $this->render('/posts/index');)
In terms of using the variable you want, there are a couple things you can do. One would be to change your set function in each controller to use a common name. For example the posts controller could have $this->set('results',$allposts); and the products controller could have $this->set('results',$allproducts); Doing this, you can always reference $results in your view file. You might also want to set another variable, $pageModel. $this->set('pageModel','Product'); in your products controller for example. Then your posts/index.php file could do something like this:
<?php foreach ($results as $result) {
echo '<tr class="class_row">';
echo '<td>';
echo $this->Html->link($result[$pageModel]['title'],
array('controller'=>$this->controller,'action'=>'view',$result[$pageModel]['id']),
array('id'=>'id_anchor_title','class'=>'class_anchor_title') );
echo '<tr>';
echo '<td>';
}
?>
notice that I replaced 'controller' => 'posts' with 'controller' => $this->controller This will make your view dynamic so the links will always point to the view action of the correct controller.
I hope this helps!
We can use $this->render('view_name'); to use the another view for some other action. I'm not sure how exactly you're going to achieve your goal.
if you want to render posts/index.ctp instead of products/index.ctp, use $this->render('/posts/index');
Or you may want to put that in an element (that's the same idea of generic/common index.ctp).

Using one model to read and another to save data

I have a model named google_news.php which uses the external data, and another model saved_news.php which uses my saved_news table in database,
In my controller I declared that Im using this two models:
var $uses = array('GoogleNews', 'SavedNews');
and my index function reads data:
$this->set('news',$this->GoogleNews->find('all'));
and my view looks like this:
<?php foreach( $news as $newsItem ) : ?>
<?php echo $html->link($newsItem['GoogleNews']['title'], array('action'=>'add', $newsItem['GoogleNews']['title'])); ?>
<?php echo $newsItem['GoogleNews']['encoded']; ?>
<em>
<hr>
<?php endforeach; ?>
How to write the add function in my controller to save each data to my database?
You should assign what you need to be saved into $this->data['ModelName'] as array of fields. Take a look at saving data in the book. That will explain more about the formatting that needs to be followed.

Resources