Looking for the most efficient way to do the following:
Details:
1 controller:
Reports
2 views:
create_report
view_report
create_report has a form where information is collected that will be used in the view_report view.
I know the data entered in the form is available within the create_report view via the $this->session->data element.
Looking for Help on This:
What I need to do is send that same info ($this->session->data) from the create_report view to the view_report view (through the controller, I assume).
What I have so far:
Just a link:
echo $this->Html->link('View Report', array('controller' => 'reports', 'action' => 'view_report'));
But this only takes the user to the view_report view. It doesn't send the info in $this->session->data to that view.
I am thinking it has something to do with the Js helper, but I wasn't able to find any posts dealing directly with this situation for CakePHP 2.x.
You could bypass data processing by controller action create_report and send them directly to report view and do validation there if needed. Just alter form creation in create_report.ctp view.
$this->Form->create('Report', array('action' => 'view_report'));
Data will be submited directly to view_report action and available in $this->request->data
If you have data stored in the session as you say, then you can access it directly from your view_report view, or any other view for that matter. To do this you can use the Session Helper.
$this->Session->read('whatever');
To use this approach, make sure you have the Session Helper loaded. More information on it here.
Or you could pass your session data to the view by using $this->set in your controller as you would any other data.
If you want, for debugging sake, to see the contents of your current session, you can dump the session from your view ...
var_dump($this->Session);
this way can be used as well, in this case you can send to any controller's any action
$this->Form->create('Report', array('url' => '/my_contoller/my_action'));
Related
I've been working on the skinny controller fat model way. Before, I used this in my controller:
$this
->find('all')
->contain(['Declarator'])
->where(['user_id' => $this->Auth->user('id')])
->order(['Declarations.created' => 'DESC']);
However, $this->Auth->user('id'), doesn't work in a model.
What other way is there to get the id from the authenticated user in a model?
What other way is there to get the id from the authenticated user in a model?
Simply pass it to a model method:
public function someModelMethod($userId, array $postData) {
// Do something here, move your code from the controller here
return $something;
}
public function someControllerAction() {
$this->set('data', $this->Model->someModelMethod(
$this->Auth->user('id'),
$this->request->data
);
}
Cake doesn't have a layer that would take the business logic so most of the time it's put in the model layer. Cake also doesn't use dependency injection so passing whole instances around like the auth object is sometimes cumbersome. Also I don't think the auth object itself should intersect with the model layer. We want to avoid tight coupling. To simplify this (also for testing) it is much easier to just pass the required values to the methods.
Mayby it's not a good idea, but in cake's model You can get users id using $_SESSION['Auth']['User']['id']
Or just use Cake\Routing\Router; at the top of your Table class and then, You can get access to session using:
Router::getRequest()->getSession()->read('Auth.User.id');
In CakePHP 2.x it's done as stated below. I'm quite sure that, even though it's not in the docs, it may be done the same way.
// Use anywhere
AuthComponent::user('id')
// From inside a controller
$this->Auth->user('id');
Source: http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#accessing-the-logged-in-user
Docs for version 3.x: http://book.cakephp.org/3.0/en/controllers/components/authentication.html#accessing-the-logged-in-user
I have views that are called from different views. The customers edit view can be called from the customers list, the customers search, from within an order and so on. Some of this views are simple views other contains forms to add, edit or delete data. After the user has done what he had to to on that form he should be redirected to the calling form or to another form.
Using $this->referer() wouldn't work as some navigations have to go like this:
list order --> edit order --> delete order --> list order.
I would be fine with defining the redirection for every call so I've tried to use query strings and add ?redirectTarget=<wherever> to every link or redirection. For that I've made a controller function
in AppController.php
public function getRedirectTarget() {
if ($this->request->query('redirectTarget')) {
return $this->request->query('redirectTarget');
} else {
return array(
'controller' => 'pages',
'action' => 'home'
);
}
}
This works for forms as I can use getRedirectTarget() in my controllers but I cannot access that function from within a view to build a link. (At leas I sholdn't do that Can you call a controller function from a view in CakePHP? ) In the example from the top I have to pass the information from the order list to the edit view to build a link and to the underlying controller for the form action.
Now I have different aproaches in my mind but with none of them I'm realy happy. I'm not shure which way to go.
Is there something in CakePhp I haven't found yet?
using $this->requestAction?
changing everything to forms and buttons and doing all redirections in the controllers?
Is there a way to create a variable for every view?
As this seems to me like a comon requirement and I'm pretty new to CakePHP I'm asking for your advice.
Using requestAction should be the best way.
In the views, you can have something like
$redirect = $this->requestAction('/mycontroller/requestAction');
$url = $this->Html->link('Continue', $redirect));
I have a controller called users_controller and one action called getdata().getdata.ctp is the view corresponding to that action. in that view i added a elemet called route.ctp which contains a from data.my problem is i want to retrive all the vaues from form element in the getdata() method and save it in another model Route.How we can do this?
for this i write the form action in the element route.ctp
<?php echo $this->Form->create('User', array('url' => array('action' => 'getdata'))); ?>
And in the users_controllers getdata() action , i write
function getdata()
{
$this->commuter(); // it call a function commuter() in this same controller for displaying some data in the view.
$this->layout='custm';
$this->loadModel('Defineroute');
if (!empty($this->data) )
{
$this->Defineroute->create(); //Defineroute is a model. in this model i want save the form date. for that i created one table "defineroutes"
$this->Defineroute->save($this->data);
}
}
Just a few observations:
Observation 1
The model that the form associates the data with is User and not Defineroute. If the fields are the same for both models, you would have to de-reference the User model in the $this->data property.
So instead of doing:
$this->Defineroute->save($this->data);
Do:
$this->Defineroute->save($this->data['User']);
Update
If you debug your post data by doing a pr($this->data), you should see the following:
array('User' => array(/*Your User fields*/))
That's why if you do $this->data['User'] you will get just the fields for your Defineroute model.
Observation 2
You don't really need to be calling $this->Defineroute->create(); because you're only creating one record per request so there is really no need to reset the active record in the model.
Observation 3
Calls to another controller function like $this->commuter(); are fine as long as they are utility functions and not actions. The reason for this is that you create dependencies between your controller actions, and if you change one in the future, you may break the other. If the function sets view variables from one model, consider shifting the code into the model itself.
I have a shopping cart site and on successful purchase I need to send a mail with all product details in the order as attachment. I have used fat model skinny controller approach and all my functions are in model. I have a controller action which will give the order details by passing order id along with view. Using dompdf I can convert this html to pdf and can create a file. So for creating attachment I can use the same function by passing some parameter. My mail sending code is in model. From here I need to call the controller action and need to get the pdf file name that just created. I know calling controller action from model is against MVC architecture. But how can I achieve this functionality ?
'fat' models is a good thing to do, however, try not to put things in a Model that should not be in a Model. In MVC, Models should handle all things related to data.
Fat models
The 'fat' Model concept is to reduce the amount of code in your Controller, by moving data related code to the Model. for example:
In stead of this; (in your Controller):
public function view($id)
{
$this->request->data = $this->SomeModel->find('first', array(
'fields' => array(
// list of fields to retrieve
),
'conditions' => array(
// conditions
),
// etc.
);
}
Move the find instructions to a method inside your model and use this:
public function view($id)
{
$this->request->data = $this->SomeModel->someMethod($id);
}
Other locations to put your code
Code that is not related to data, can also be moved outside your Controller (to make it 'skinny'). CakePHP offers other locations to move your code to, for example inside a Component
Then inside your Controller;
this:
public function view($id)
{
$this->request->data = $this->SomeModel->someMethod($id);
// use functionality of a component
$this->SomeComponent->doSomething();
}
Triggering functionality via Events
To keep code and logic outside your controller, CakePHP 2.x now offers an 'Event' system. This allows you to execute code if a certain event happens. You can pass additional information through the events (the event will become a 'communication channel' that passes through your application).
Sending e-mails for certain events is a good example. The CakePHP also uses sending mails to illustrate the Event system in CakePHP; this is probably what you are looking for:
Dispatching Events - send emails
Make your model method return the data so you have it in the controller and pass it to the other model function together with your pdf related data.
Is there anyway for me to create dynamic custom routes? The goal is to allow users to specify any URL they want to route to any controllers/view/ structure.
If user want to create something as below:
/a_quick_brown_fox => foxes/view/42
/jumps_over => actions/view/42
/lazy_dog => dogs/view/42
And many others in the future without the need to edit routes.php I am unsure of a possible solution.
I wish to allow user to input something like below
Custom URL => [ ]
Controller => [ ]
ID for View => [ ]
I will store it in a table to allow for unique URL checking, and what not. To allow scalability for new controllers I am okay with having prefix to slugs such as /l/<slug>
I would then wish to insert some code that will retrieve the custom URL from table and allow the routing. Is it at all possible? Has anyone ever done it?
I'm not sure whether you can define it directly into the routing system as you propose, however you could do something like this.
First define all your applications controller/actions explicitly so that your users won't overwrite them.
Then define a catch all route that will route to a controller of your choosing
//default routes
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
//other
//custom route
Router::connect('/*', array('controller' => 'routes', 'action' => 'custom'));
Your routes_controller/custom_action will receive whatever parameters the url contains, simply do a lookup on your DB from there and redirect to the correct route defined in your database.
function custom() {
//get values via $this->params
}
The easiest way to do this is to have the routes controller do the saving of new routes and to cache saved routes. Each time a new route is added flush the cache and save it again.
Then create a custom Route class that will pull the cache entries out and process them in the routes.php
You can create custom route class, but I don't think you have access to POST data in it (you can access GET data and Cache, if that's enough). Probably the easiest way is redirect in the controller.