I'm trying to use Security::allowedControllers and Security::allowedActions. So I have a controller which look more or less like this
class AppController extends Controller {
var $components = array('Security'); //other components
//other stuff
}
class BookController extends AppController {
function beforeFilter() {
parent::beforeFilter();
$this->Security->allowedControllers = array('Users');
$this->Security->allowedActions = array('view');
$this->Security->RequireAuth = array('search', 'results');
}
//other stuff
}
The action 'search' displays a form, which then calls 'results' to show the results of the search. I am intentionally trying to be blackholed.
For what I understand of $this->Security->allowedControllers and $this->Security->allowedActions, I should be able to get POST data only from the action 'view' of the controller 'Users'. In particular the action 'results' should redirect me to a black hole, since it obtains POST data from the action 'search' of the controller 'Books'.
But this is not the case. I can even make cross controller requests, and never get blackholed, so I guess I'm not using correctly this variables. What is the right way to trigger cross-controller requests control?
Try this:
$this->Security->allowedFields = array('Model.fieldname', ...);
You need to add the fields that are not in the model to the allowedFields like I guess your Model.search field in the form.
This is a good and short tutorial for doing Auth with CakePHP 1.3: http://tv.cakephp.org/video/jasonwydro/2011/01/29/cakephp_1_3_auth_authentication_component_tutorial_-_administrator_login
Related
I'm a beginner in Yii, so don't know, how to solve my problem in most correct way.
There are 2 controllers - SiteController and UsersController. I need to retrieve some data from DB and output it in layout. In particular, if user1 and user2 added user3 as friend, user3 will see it on main menu panel:
User have to see it regardless of controller, action of which is running (in pic above user sees /site/profile page, but a lot of other pages (in particular invitations) render by users controller).
I wrote the same actions in 2 controllers:
public function getStats () { //it duplicates in UsersController and SiteController
$recieved_invitations = Invitations::find()->where(['recipient_id'=>\Yii::$app->user->id])->all();
...
return [$recieved_invitations_count, $received_docs_count];
}
I decided, that, if count need to be in every page, I need trigger it regardless of controllers. So, I wrote in wep.php:
'on beforeAction' => function ($event) {
\Yii::$app->session->set('stats', $event->sender->controller->getStats());
}
And then in menu in layout I retrieve session vars.
Everything works fine. But getStats() action duplicates in controllers. I want to do it standalone.
//action code (in '#app/components' folder) (just from documentation):
namespace app\components;
use yii\base\Action;
class HelloWorldAction extends Action {
public function run() {
return "Hello World";
}
}
//in 'actions()' in controllers:
parent::actions();
return [
'hv' => [
'class' => 'app\components\HelloWorldAction',
]
];
//in 'web.php':
'on beforeAction' => function ($event) {
\Yii::$app->session->set('stats', $event->sender->controller->hv());
}
But exception throws: Calling unknown method: app\controllers\UsersController::hv(). Also: if I disable urlManager in config. file and comment out beforeAction handler, action is accessible via this URL:
http://localhost:8001/index.php?r=users%2Fhv
Why standalone action fails, if it triggers on beforeAction event? And, if it's normal behaviour, what can I do to avoid duplicating getStats() method?
I would actually try to move the getStats method to your User model, that way you can just access it from anywhere in your application by calling it like this:
Yii::$app->user->identity->stats;
// OR
Yii::$app->user->identity->getStats();
It's usually better to have fat models, simple controllers and views.
I am using Yii framework for my application. My application contain 4 controllers in which I want to pass value from one controller to another.
Let us consider site and admin controller. In site controller, I manage the login validation and retrieves admin id from database. But I want to send admin id to admin controller.
I try session variable, its scope only within that controller.
Please suggest the possible solution for me.
Thanks in advance
You want to use a redirect:
In the siteController file
public function actionLogin()
{
//Perform your operation
//The next line will redirect the user to
//the AdminController in the action called loggedAction
$this->redirect(array('admin/logged', array(
'id' => $admin->id,
'param2' => $value2
)));
}
in the adminController file
public function loggedAction($id, $param2)
{
//you are in the other action and params are set
}
In Zend Framework 2, I've created a class that extends Zend\Form\Form called MyForm.
In the indexAction of one Controller class, I'll initialize MyForm like this:
public function indexAction()
{
$form = new MyForm('my-name');
$viewModel = new ViewModel(array('form' => $form));
return $viewModel;
}
Then in the corresponding view, I basically just do
$form = $this->form;
$form->prepare();
echo $this->form()->openTag($this->form);
echo $this->formCollection($form);
echo $this->form()->closeTag();
This all works, but you may have noticed that the action for the form is missing.
I have tried to add the action like this in the view:
$form->setAttribute('action', $this->url(NULL, array('controller'=>'Index', 'action' => 'go')));
Then in the go action inside my IndexController I just have this for testing:
public function goAction()
{
die('huh');
}
This did not work at all, I always land at the form view (== index action) again. Why is the go action never executed?
I also know that I could either hardcode the action attribute and let a segment route handle the processing, or I could even define an own route for that.
In what cases form actions should get their own route?
In what cases form actions should be handled using a segment route?
In what cases form actions should be handled like in my example?
If there are no hard rules for this: What intention do the different approaches communicate?
Is it also possible to add form actions in the controller instead of the view?
Continuing on from the comments: That's not how the URL helper works - if you omit the first parameter, the current route is used instead. That's probably why you're not getting the form action you expect.
Personally, I always specify the route name when using the URL helper - makes things clearer.
I have created a fully functional CakePHP web application. Now, i wanna get it to the next level and make my app more "opened". Thus i want to create an RESTful API. In the CakePHP docs,i found this link (http://book.cakephp.org/2.0/en/development/rest.html) which describes the way to make your app RESTful. I added in the routes.php the the two lines needed,as noted at the top of the link,and now i want to test it.
I have an UsersController.php controller,where there is a function add(),which adds new users to databases. But when i try to browse under mydomain.com/users.json (even with HTTP POST),this returns me the webpage,and not a json formatted page,as i was expecting .
Now i think that i have done something wrong or i have not understood something correctly. What's actually happening,can you help me a bit around here?
Thank you in advace!
You need to parse JSON extensions. So in your routes.php file add:
Router::parseExtensions('json');
So a URL like http://example.com/news/index you can now access like http://example.com/news/index.json.
To actually return JSON though, you need to amend your controller methods. You need to set a _serialize key in your action, so your news controller could look like this:
<?php
class NewsController extends AppController {
public function index() {
$news = $this->paginate('News');
$this->set('news', $news);
$this->set('_serialize', array('news'));
}
}
That’s the basics. For POST requests, you’ll want to use the RequestHandler component. Add it to your controller:
<?php
class NewsController extends AppController {
public $components = array(
'RequestHandler',
...
);
And then you can check if an incoming request used the .json file extension:
public function add() {
if ($this->RequestHandler->extension == 'json') {
// JSON request
} else {
// do things as normal
}
}
I'm trying to make a cms like app using Yii. The functionality is going to be something like:
http://www.example.com/article/some-article-name
What I am trying to do is have everything go the method actionIndex() in the ArticleController.php, and have that one method determine how to handle the action. So my question is how can I route all actions to one method in a controller in Yii?
In your case, I think it'll be better to use either a filter or a beforeAction method.
Filter way:
Filter is a piece of code that is configured to be executed before and/or after a controller action executes.
Sample:
class SomeController extends Controller {
// ... other code ...
public function filters() {
return array(
// .. other filters ...
'mysimple', // our filter will be applied to all actions in this controller
// ... other filters ...
);
}
public function filterMysimple($filterChain) { // this is the filter code
// ... do stuff ...
$filterChain->run(); // this bit is important to let the action run
}
// ... other code ...
}
beforeAction way:
This method is invoked right before an action is to be executed (after all possible filters.) You may override this method to do last-minute preparation for the action.
Sample:
class SomeController extends Controller {
// ... other code ...
protected function beforeAction($action) {
if (parent::beforeAction($action)){
// do stuff
return true; // this line is important to let the action continue
}
return false;
}
// ... other code ...
}
As a side note, you can access the current action within a controller this way also : $this->action , to get the value of id: $this->action->id:
if($this->action->id == 'view') { // say you want to detect actionView
$this->layout = 'path/to/layout'; // say you want to set a different layout for actionView
}
Add this in the beginning of urlManager rules in the config:
'article/*' => 'article',
Your rules will have to be similar to the following :-
'rules' => array(
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => 'article/index',
),
This will pass all requests to the actionIndex function in the ArticleControllerPHP Class if the Controller and/or Action does not exist.
I'm guessing you just wanna throw in a bunch of static pages in your "view" folder and have them selected and rendered automatically without adding an action for each of them in your controller.
The above suggested filters() and beforeAction() and even __construct() do not work for this purpose (filters and beforeaction do not fire up at all if the action does not exist, and __construct is very messy because if you put your functionality in __construct - at that point Yii doesnt even know which controller/action/view it should call)
however, there is a simple workaround which involves URL manager
in your config, in URL manager's rules, add one of the following lines (depending on your path settings)
'articles/<action:\w+>' => 'articles/index/action/<action>',
OR
'articles/<action:\w+>' => 'articles/index?action=<action>',
and then, in your articles controller just put up this (or similar) index action
public function actionIndex() {
$name = Yii::app()->request->getParam('action');
$this->render($name);
}
then you can call pages like /articles/myarticle or /articles/yourarticle without putting up any function in your controller. All you would need to do is just add a file named myarticle.php or yourarticle.php in your views/articles folder, and type your html content inside those files.