I am new to use cakephp2,
i use element + requestAction to show a news block on some page of my site, like below:
news.ctp
<?php
$news = $this->requestAction('controller'=>'News','action'=>'load');
foreach($news as $itm){
echo $itm['title];
//...
}
NewsController.php
<?php
//...
public function load(){
//...
return $data;
}
It's worked well ,my problem is
how to disable direct access like: http://domain/News/load
and if it is a good way to make a contents block?
thanks!
In your controller you can try like this to prevent direct access.
public function load(){
if (empty($this->request->params['requested'])) {
$this->redirect($this->referer());
}
return $data;
}
If requestAction is used without caching requestAction can lead to poor performance. It is rarely appropriate to use in a controller or model. check here
For more info you can check the documentation here
Related
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
I am having an issue setting variables in the controller and showing it at the view.
my codes are as follow:
In my view (pages/anything.ctp):
<?php echo $anything; ?>
In my controller (pagesController.php):
public function anything() {
$a = "asdasdas";
$this->set('anything', $a);
}
I am new to Cake, and I've done quite a number of search in google and stack. Still no luck.
I'd be grateful if anybody could help, or if anyone already asked this question before please provide a link that would be best.
First read the following article Controller actions in CakePHP CookBook
When you use controller methods with requestAction(), you will often want to return data that isn’t a string. If you have controller methods that are used for normal web requests + requestAction, you should check the request type before returning:
class RecipesController extends AppController {
public function popular() {
$popular = $this->Recipe->popular();
if (!empty($this->request->params['requested'])) {
return $popular;
}
$this->set('popular', $popular);
}
}
The above controller action is an example of how a method can be used with requestAction() and normal requests. Returning array data to a non-requestAction request will cause errors and should be avoided. See the section on requestAction() for more tips on using requestAction()
Try this:
public function anything() {
$a = "asdasdas";
$this->set(compact('a'));
}
<?php echo $a; ?>
I thought this would be a relatively common thing to do, but I can't find examples anywhere, and the Cookbook's section on find() was not clear in the slightest on the subject. Maybe it's just something that's so simple Cake assumes you can just do it on your own.
All I'm looking to do here is retrieve a User's name (not the currently logged-in user…a different one) in Cake based on their ID passed to my by an array in the view.
Here's what I've got in the controller:
public function user_lookup($userID){
$this->User->flatten = false;
$this->User->recursive = 1;
$user = $this->User->find('first', array('conditions' => $userID));
//what now?
}
At this point, I don't even know if I'm on the right track…I assume this will return an array with the User's data, but how do I handle those results? How do I know what the array's gonna look like? Do I just return($cakeArray['first'].' '.$cakeArray['last'])? I dunno…
Help?
You need to use set to take the returned data, and make it accessible as a variable in your views. set is the main way you send data from your controller to your view.
public function user_lookup($userID){
$this->User->flatten = false;
$this->User->recursive = 1;
// added - minor improvement
if(!$this->User->exists($userID)) {
$this->redirect(array('action'=>'some_place'));
// the requested user doesn't exist; redirect or throw a 404 etc.
}
// we use $this->set() to store the data returned.
// It will be accessible in your view in a variable called `user`
// (or what ever you pass as the first parameter)
$this->set('user', $this->User->find('first', array('conditions' => $userID)));
}
// user_lookup.ctp - output the `user`
<?php echo $user['User']['username']; // eg ?>
<?php debug($user); // see what's acutally been returned ?>
more in the manual (this is fundamental cake stuff so might be worth having a good read)
I searched a lot but I couldn't find on How to use the find('all') in Views as used in Rails, but here I'm getting the error "Undefined property: View::$Menu [APP\Lib\Cake\View\View.php, line 804]"
'Menu' is the model which I'm using to fetch data from the menus table.
I'm using the below code in views:
$this->set('test',$this->Menu->find('all'));
print_r($test);
Inside your Menu model create a method, something like getMenu(). In this method do your find() and get the results you want. Modify the results as you need and like to within the getMenu() method and return the data.
If you need that menu on every page in AppController::beforeFilter() or beforeRender() simply do
$this->set('menu', ClassRegistry::init('Menu')->getMenu());
If you do not need it everywhere you might go better with using requestAction getting the data using this method from the Menus controller that will call getMenu() from the model and return the data. Setting it where you need it would be still better, if you use requestAction you also want to cache it very likely.
TRY TO NOT RETRIEVE DATA WITHIN VIEW FILE. VIOLATION OF MVC RULE
try this in view file:
$menu = ClassRegistry::init('Menu');
pr($menu->find('all'));
In AppHelper ,
Make a below function
function getMenu()
{
App::import('Model', 'Menu');
$this->Menu= &new Menu();
$test = array();
$test = $this->Menu->find('all');
return $test;
}
Use above function in view like :
<?php
$menu = $html->getMenu();
print_r($menu);
?>
Cakephp not allow this .
First create the reference(object) of your model using ClassRegistry::init('Model');
And then call find function from using object
$obj = ClassRegistry::init('Menu');
$test = $obj->find('all');
echo ""; print_r($test); `
This will work.
Ok i have this controller:
class ExampleController extends AppController {
var $name = 'Example';
public function test_me () {
$this->Example->Create();
$this->Example->set( 'variable_from_db_1' => 'random_value_1',
'variable_from_db_2' => 'random_value_2' );
//here, how can i access to variable_from_db_1 and 2 in $this->Example?
//???? i've tried $this->data and $this->Example->data but nothing to do
}
}
Do you have some hints for me?
you can explore the data with:
debug( $this->Example );
the data is it's own array:
$this->Example->data['variable_from_db_1'];
I don't think you can do that.
You can assign your model data to a $this->data array like this:
$this->data['variable_from_db_1'] = $value;
$this->set('variable_from_db_1', $value);
So know you can access $this->data within the controller.
I think if you want to save data to your actual Model, you might have to implement the getter / setter method in your model...
In the related view you can access it like this:
echo $variable_from_db_1.'<br />';
echo $variable_from_db_2.'<br />';
In the controller call
debug($this->data);
I think you cannot do this in controller, normally set calls are moved to the end area of actions and all the operations on the such variables must be performed before 'set'ing it for later access in views.