I have legacy code which stores temporary data in the context. I would like to store this in the DB using the following model:
class Model_MyModel extends Model_Table {
function init(){
parent::init();
$this->addField('myString');
}
}
I can access the data from within the legacy Controller thus:
class Controller_LegacyController extends Controller {
$myString = $this->api->recall("legacyString");
}
But I can't see how to tie everything together (all the examples use a Form to link to the DB)
Thanks for your help,
Greg.
I find your question and code a bit confusing, but I'll try to help.
You don't need controller to be able to use your model. When calling $form->setModel() it automatically pick the right controller for you.
$page->add('MVCForm')->setModel('MyModel');
When you want to send data back into data-base, you should call $form->update(). There is a View you can use, which will do that for you called: FormAndSave
$page->add('FormAndSave')->setModel('MyModel'); // will also save data back to database.
If you load data from database, you need to call loadData() on the model. Your final code might look like this (stickyGET ensures that it pass get argument inside form submit handler):
$this->api->stickyGET('id');
$page->add('FormAndSave')->setModel('MyModel')->loadData($_GET['id']);
method recall() deals with sessions, so it seems as if you are reading data from the session. If you intend that and you want to see value of your session variable in the form, then this will do it:
$form->set('myfield',$this->api->recall('legacyString'));
I hope this will give you some hints on how to continue. Look through more samples, there are lots of them on http://agiletoolkit.org
Related
This is a design question.
I'm trying to build a booking system in cakephp3.
I've never done something like this with cake before.
I thought the best way might be to -- as the post title suggests -- build up an entity over several forms/actions.
Something like choose location -> enter customer details -> enter special requirements -> review full details and pay
So each of those stages becomes an action within my booking controller. The view for each action submits its content to the next action in the chain, and i use patch entity with the request data, and send the result to the new action's view.
I've started to wonder if this is a good way to do it. One significant problem is that the data from each of the previous actions has to be stored in hidden fields so that it can be resubmitted with the new data from the current action.
I want the data from previous actions to be visible in a read only fashion so I've used the entity that i pass to the view to fill an HTML table. That's nice and it works fine but having to also store that same data in hidden fields is not a very nice way to do it.
I hope this is making sense!
Anyway, I thought I'd post on here for some design guidance as i feel like there is probably a better way to do this. I have considered creating temporary records in the database and just passing the id but i was hoping I wouldn't have to.
Any advice here would be very much appreciated.
Cheers.
I would just store the entity in the DB and then proceed with your other views, getting data from the DB. Pseudo:
public function chooseLocation() {
$ent = new Entitiy();
patchEntity($ent,$this->request->data);
if save entity {
redirect to enterCustomerDetails($ent[id]);
}
}
public function enterCustomerDetails($id) {
$ent = $this->Modelname->get($id);
// patch, save, redirect again ...
}
I'm trying to create a component (front end) that uses multiple tables. I found 1 or 2 post that partially answer to the question but none really does. The point seems always simple and evident for the one who knows how to do it but it is never really explained (or I missed the right post).
In my component, the user enters data in one view that need to be stored in two tables:
the standard Joomla User table i.e. # __users
an additional table to store data that are not included in Joomla i.e. # __users_complements
I'm a beginner, so maybe I'm wrong, but I understood that the standard functions of joomla can only save results of a form in one table .
In my case, I guess that I have to override the standard functions in my model: com_component / model / my_model.php.
1) I'm confused because I do not really understand which function must be overrided: save ()? store ()? other?
2) Let's say I override the save() function, should I rewrite all the code to save data (explode the data array and create all the update queries) or should I create 2 standard table objects.
In this case, (2 objects) it seems weird to send each time the whole data array to the parent function as I know that a part is for table 1 and the other part for the table 2. I should be able to split before don't I?
3) Should I create 2 models and manage those models from my controller when I get back data from the form and call the save function of the model?
Could you help me to clarify how to do this saving in multiple tables?
An example with code will be very much appreciated.
Thank you
I finally made it. As I spent many hours on this and found that a lot of people where looking for an answer, here is how I did.
I suppose you know how to create a component, using the standard MVC structure:
Component entry point
Component controller
Eventually component router
Component view
Component model
Component controller
In model components\my_component\models\my_model.php create your own save function
public function save($data)
{
// Initialise variables.
$userId = (!empty($data['id'])) ? $data['id'] : (int)$this->getState('user.id');
$user = JFactory::getUser();
$table_one = $this->getTable('TableOne', 'MyComponentTable', array());
$table_two = $this->getTable('TableTwo', 'MyComponentTable', array());
// Bind the data.
if (!$table_one->bind($data))
{
$this->setError(JText::sprintf('USERS PROFILE BIND FAILED', $user->getError()));
return false;
}
if (!$table_two->bind($data))
{
$this->setError(JText::sprintf('USERS PROFILE BIND FAILED', $user->getError()));
return false;
}
// Store the data.
if (!$table_one->save($data))
{
$this->setError($user->getError());
return false;
}
if (!$table_two->save($data))
{
$this->setError($user->getError());
return false;
}
return $user->id;
}
Of course, you need the getTable function called in the save function
public function getTable($type = 'TableOne', $prefix = 'MyComponentTable', $config = array())
{
// call the administrator\components\com_mycomponent\tables\__tablename__.php
$this->addTablePath(JPATH_COMPONENT_ADMINISTRATOR . '/tables');
return JTable::getInstance($type, $prefix, $config);
}
And it works! So simple!
Of course, as I said in my question the whole $data is sent to the parent save() function to with data that are not necessary for table_one or table_two. It works this way with the standard joomla structure (no hack or direct query in the code).
Hope it helps.
There may be those out there who disagree with the way that the following method disrupts the MVC structure just a bit, but I've found it to be the simplest for me.
Typically, you have a model that fits one of the tables. In your example with pushing data to the users table as well as one in your component, I would add the following to the model for the table in your component:
public function save($data) {
if (!parent::save($data)) {
return false;
}
// add necessary code to save to the users table, since there isn't a standard way to do this that I'm aware of
// sometimes I will grab another model even
require_once(JPATH_BASE . '/administrator/components/com_users/models/user.php');
$other_model = $this->getInstance('user', 'UsersModel');
$other_model->save($data);
return true;
}
The first part of this function should save the data to the components table just like normal. But you can tack what you need on to the rest of the component to make whatever you like happen.
I would almost guarantee that there is a better way to chain models (and I've seen some of the changes happening in the Joomla Platform core that will lead to better ways in the future), but this should get you going for now.
In addition, for prompt 3, I would handle in the controller if you need to sometimes save just one table and sometimes save both. I've found that the save functions are pretty safe to run even when parts aren't loaded, so I usually just let it run.
I'm trying to create a menu in cake php where I can also know how many articles are inside the section, should I use a manual query, or does exist some existing method to do it?
My site menu:
- Works (12)
- Photos (35)
- Stuff (7)
- Contacts
My problem is also I didn't get how I can access to data like this for every view, this should be a main menu, so I should use this in every view but If i put it in default.ctp, every model deosn't exist, because I cannot access it from a view.
Does exist some page which talks about this?
Since those are separate models that are not related to each other, you'll need to do a manual count.
$this->Model->find('count');
EDIT
Ok, so looks like you are talking about different models.
If this is used in a menu, that means it will be shown in all pages.
You have two ways of doing this.
You can do it by having an AppController for you application. Basically, you can put this code in the beforeRender method so it runs everytime your a request is rendered
function beforeRender() {
App::import('Model', array('Work', 'Photo', 'Stuff'));
$work = new Work();
$workCount = $work->find('count');
//do the same for the other
$this->set('workCount', $workCount);
}
Have a look at this for more details on callbacks : http://book.cakephp.org/view/977/Controller-Methods#Callbacks-984
Secondly, you can do this via a helper. You can put the same code (that is inside the bforeRender) into a helper, and you can call the helper method.
You can look here for more info on creating a helper : http://book.cakephp.org/view/1097/Creating-Helpers
The CounterCache behavior will help you out:
http://book.cakephp.org/view/1033/counterCache-Cache-your-count
i have a form for adding people object ,i want to add as many people without saving people in database,after clicking add people form submit button,the same form should appear without saving the form data to database,instead it should save to the session.please explain in detail if possible with the help of a example to do this, i have not found any tutorial which explains cakephp session in detail.
Vinay,
check out the official examples.
But you should definitly start with the easy tutorials here and dissect these. You will learn form handling and later can put it together with the sessions.
Sessions are simple. You include the component, write something to the session and read it from the session later. That's it. You can store in it almost anything you want, including arrays.
class FooController extends AppController {
public $components = array('Session');
public function foo() {
$this->Session->write('some.key', 'some value');
}
public function bar() {
$baz = $this->Session->read('some.key');
}
}
See http://book.cakephp.org/view/1311/Methods
I want to store the form entries into a table that will store what my users searched for, then actually execute the code on the form results.
I tried doing:
$this->Search->create();
$this->Search->save($this->data);
But I don't think it liked me using a model that doesn't belong to that controller (my guess this doesn't follow convention and fully utilize CakePHP).
The other idea I had was to create a new searches_controller, then run $this->data through the above code and redirect back to the Trips controller but it seems like that's not the optimal way of doing it either.
Any thoughts on how best to do this?
In procedural PHP, I would just do an INSERT query before.
Thanks for the help!
I think that having Model which doesn't belong to the specific controller is not so bad idea.
Actually you can put this logic in the beforeFilter() of the Trips model like that:
class Trip extends AppModel {
//....
function beforeFind(){
if($this->data){
$search = ClassRegistry::init('Search'); //adding instance of Search model
$search->save($this->data); //save the data
//Do extra things if needed
}
}
//....
}
This way you don't have "alien" model in your controllers, and utilise the recommendation "Fat Models, Skinny controllers" :)