need simple examples for hasone and hasmany usage [closed] - atk4

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I have watched the movies and read the documents but I can't understand the usage of hasone and hasmany in agile toolkit!
can anybody give me some simple examples for these?
Thanks.

Two models with hasOne relation:
class Model_User extends Model_Table {
public $table = 'user';
function init() {
parent::init();
$this->addField('name');
$this->addField('email');
$this->hasOne('role'); // field role_id in database
}
}
class Model_Role extends Model_Table {
public $table = 'role';
function init() {
parent::init();
$this->addField('name');
}
}
Usage of these two models:
$cr = $this->add('CRUD');
$cr->setModel('Model_User',
array('name','email','role_id'),
array('name','email','role')
);
In Grid you will see field name from role table.
In Form you will see dropdown with all roles in it. You can select one role per user.

Read Agile Toolkit low-level documentation here:
http://agiletoolkit.org/book.pdf
should help you understand models fully.

Related

Column lost their value and turned into null after using update function

I am currently implementing CRUD functions but when I try the update function, the database added new entity instead of editing the existing one.
My database consist of 2 models "Questions" and "Answers". One "question" can have multiple "answers" but one "answer" can only linked to one "question".
My test run was adding Question content and an array of Answer contents. Checking the database, both of them are linked together through a column called "question_id" in Answer table. But when I am update the body of the Question (both the content of Question and Answer inside Question body), the database doesn't know their original "question_id" anymore.
I felt like I did wrong somewhere. Any ideas?
POST Question and Answer to database
PUT Question and Answer to database
Question model
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column
private String content;
#OneToMany(mappedBy = "question")
#Cascade(CascadeType.ALL)
#Fetch(FetchMode.JOIN)
private Set<Answer> answers;
Answer model
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column
private String content;
#ManyToOne
#JsonIgnore
private Question question;
private boolean isCorrectAnswer;
QuestionService
#Transactional
public int addQuestion(Question question){
for (Answer answer: question.getAnswers()) {
answer.setQuestion(question);
}
int id = (Integer) sessionFactory.getCurrentSession().save(question);
return id;
}
#Transactional
public void updateQuestion(Question question){
sessionFactory.getCurrentSession().saveOrUpdate(question);
}
QuestionController
#RequestMapping(path = "/questions", method = RequestMethod.PUT)
public int updateQuestion(#RequestBody Question question){
questionService.updateQuestion(question);
return question.getId();
}
My advice is to separate persistent classes (used by Hibernate) and classes to serialize/deserialize JSON. Better to use a separate DTO class for each persistent class — Question -> QuestionDto And to convert between them.
To PUT Question
Use this JSON
{
"id": 1,
"answers": [
{
"id" : 100,
"content": "this is an updated answer"
},
{
"content": "this is a new answer"
}
]
}
Do this
for (Answer answer: question.getAnswers()) {
answer.setQuestion(question);
}
And use session.merge().
When entering the update method you supply Question as argument.
But this Question is an unmanaged entity because you built it in the controller outside of any transaction, so when you call saveOrUpdate() what happens is that hibernate thinks this is a new entity and save it accrodingly with a new autogenerated id.
what you need to do is retrieve the entity in the transactional block with a query, that way the entity is already managed and will be dirty checked, thus creating the correct update statement
#Transactional
public void updateQuestion(//Parameter for the query and updated field){
Query query = sessionFactory.getCurrentSession().createQuery("from Question where etc...);
Question question = query.uniqueResult();
question.setContent(//Your updated content);
sessionFactory.getCurrentSession().saveOrUpdate(question);
}
Solved by myself by fixing in QuestionService
First
#Autowire
private QuestionService questionService;
Then instead of editing only Question like this
public Question updateQuestion(Question question){
sessionFactory.getCurrentSession().saveOrUpdate(question);
return question;
}
I am using updateAnswer from AnswerService into this update so everytime I wanted to update Question or Answer or both, Answer can known their updated content and their question_id. This will solve the problem as my updated Answer doesn't know their QuestionID
public Question updateQuestion(Question question){
Set<Answer> answers = question.getAnswers();
for (Answer a : answers) {
a.setQuestion(question);
questionService.updateAnswer(a);
}
question.setAnswers(answers);
sessionFactory.getCurrentSession().saveOrUpdate(question);
return question;
}
So overall, this update function update both Question and Answer, the naming scheme does not fit so I can improve this, something like QuestionAnswerService

Cakephp table name error [duplicate]

This question already has answers here:
CakePHP specify table-name
(2 answers)
Closed 7 years ago.
I created a table named as quantities_master but when i using modal name as QuantitiesMaster it is showing some errors. what would be modal name of quantities_master table name?
Table names should be plural and model names singular in CakePHP. So you should have a table named quantities_masters and a QuantitiesMaster model.
However, if you need to have a table with a singular name you can define this in the model.
In CakePHP 2:-
class QuantitiesMaster extends AppModel {
public $useTable = 'quantities_master';
}
In CakePHP 3:-
class QuantitiesMasterTable extends Table
{
public function initialize(array $config)
{
$this->table('quantities_master');
}
}
Only ever break from CakePHP's naming conventions when you have no other choice as it makes working with CakePHP significantly harder!
If you find determining the plural and singular of words for CakePHP (i.e if English is not your first language) then the CakePHP Inflector website is really handy.
The model is looking for quantities_masters table. Add this line at the beginning of the class and it will work fine:
class QuantitiesMaster extends AppModel {
public $useTable = 'quantities_master';
}

ATK CRUD with one:many relationship

I'm a beginner and searched documentation, but can't find this how to do this:
I have two tables, admin and application. Admin can have many applications.
ADMIN:
class Model_Admin extends Model_Table {
public $entity_code='admin';
function init(){
parent::init();
$this->addField('name');
$this->addField('email');
$this->addField('password')->type('password');
$this->addField('active')->type('boolean')->system(true);
$this->addField('super')->type('boolean')->system(true);
$this->addField('created')->type('timestamp')->defaultValue($this->dsql()->expr('now()'))->system(true);
$this->addField('updated')->type('timestamp')->system(true);
$this->hasMany('Application','admin_id');
//$this->hasOne('Application');
$this->addHook('beforeSave',function($m){
$m['updated']=$m->dsql()->expr('now()');
});
}
}
APPLICATION:
class Model_Application extends Model_Table {
public $entity_code='application';
function init(){
parent::init();
$this->addField('name');
$this->addField('fbid');
$this->addField('fbsecret');
$this->addField('active')->type('boolean')->system(true);
$this->addField('created')->type('timestamp')->system(true);
$this->addField('updated')->type('timestamp')->system(true);
}
}
First question, when I generate SQL code (/generate.html) it doesn't produce anything for one to many relationship.
Second, on a page I add CRUD:
$this->add('CRUD')->setModel('Admin');
But there is no hint for any one to many. I would expect it on the add button form, but also there is nothing?
What I want is, that I can add admin, and select which applications belong to it?
in Model_Application
$this->hasOne('Admin');
on Page
$this->add('CRUD')->setModel('Application');
In Edit form of CRUD you will see dropdown with all admins and you'll be able to set admin to each application

cakePHP - model relations

I'm developing a system for a University here in Brazil. In this sytem I've got the following models:
- Country;
- State;
- City;
- University;
- Unit;
- Class;
Ok. and the relations are:
- State belongs to Country;
- City belongs to State;
- University belongs to Country (because, in my database, not every country has states registered to it and not every state has citys registered to it, so I could not demand from the user to register a University to a City);
- Unit belongsTo university;
- Class belongs to University (because not every University has Units registered to it);
Ok. I guess now I've set a good background for you guys to understand my situation. Now onto the question itself:
In the Views of my Model Class I wanna display the Country and (IF there are State City). And I may have the need to display such content in other Model views such as Unit and University.
But when I try to do that in my Class model I can only display the country_id. The foreign key in my university database table. And why is that, that is because my Class model belongs to University, so it's pretty easy to access my University's properties. However I do not wish to access the id of the Country, I want it's Name. And maybe in the future I might want other properties, who knows?
HOW DO I DO THAT? How do I access the properties of the Model Country when my Model Class has NO direct relation to it?
many thx hugs and kisses. Hope someone can help me with this one.
p.S:
I've managed a kinda loser solution: In my Class Controller I've done the following (so I can access variables of the Models Country, State and City):
In the View function I've loaded the Models for State and City (the country Model I can access by the relation Class->University->Country);
Then I used a find method to find the respective country, state and city for the Class in question I wanna display in view.ctp. The code follows:
public function view($id = null) {
$this->Class->id = $id;
$this->set('class', $this->Class->read());
$this->loadModel('State');
$this->loadModel('City');
$country = $this->Class->Universsity->Country->find('first', array('conditions' => array('Country.id' => $this->Class->data['University']['country_id']),));
$state = $this->State->find('first', array('conditions' => array('State.id' => $this->Class->data['University']['state_id']),));
$city = $this->City->find('first', array('conditions' => array('City.id' => $this->Class->data['University']['city_id']),));
$this->set('country',$country['Country']);$this->set('city',$city);
$this->set('state',$state);
}
And it kinda works...In my Wiew.ctp I get an array for Country data, and array for State data and an array for City data. And in the view I check to see if the state and city arrays are not length = 0 to display them and all...but I think there HAS to be a better way to do This.
P.P.S:
The other question is...what about the Index.ctp? How will I do that if I do not know which Class I'm working with? Will I have to have logic and find methods in the View? Isin't that just messing up the code?
Without posting your code, it's difficult to point you in the right direction. However, working on the assumption that you have your models configured correctly you should be able to do the following:
ClassController.php
public class ClassController extends AppController{
public $uses = array('Class');
public function view($id){
$class = $this->Class->find('first', array('conditions' => array('Class.id' => $id));
$this->set('class', $class);
}
}
view.ctp
<?php echo $class['Country']['name']?>
You may find however you will have to configure the recursive parameter of your class model so that CakePHP retrieves all the associated data. This can be done one of two ways:
Configure the recursive parameter within your Class model (see the documentation on how to do this). This sets the default value for recursive whenever you retrieve records from the database and you don't specify the attribute in your options.
Set the recurisve parameter within your find(...) method calls. I favor this one because it helps avoid placing a heavy load on the database when you don't need the data it retrieves.
For example, in your controller you could do the following:
public function view($id){
$class = $this->Class->find('first', array('conditions' => array('Class.id' => $id), 'recursive' => 3));
$this->set('class', $class);
}
Just a warning, don't set recursive to a value higher than you need, otherwise you may retrieve stuff that you don't particularly require. Use the debug() function to inspect what you're model is currently retrieving so you can make more of an informed decision:
debug($class);
I hope this is of some help!

CakePHP: can't get models to work [duplicate]

This question already has answers here:
Call to a member function on a non-object [duplicate]
(8 answers)
Closed 9 years ago.
Im really new to cakePHP, and I more or less understand the controllers, and views as I worked with a MVC framework before. However, the models and naming conventions in cakePHP seem to be different from what I've used before. the one's I've used; you call various functions such as select, and insert, with the fields and such you want, and then execute the query. Essentially you build your own query. I'm trying to figure out how to use models in cakePHP, and as I understand it, if I have a controller in /controllers/users_controller.php with the contents:
<?php
class UsersController extends AppController{
var $name = 'Users';
var $helpers = array ('Html','Form');
public function login(){
$this->set('msg', 'Login PAGE!!!! YAY!!!!!!!!!');
$this->set('MT', $this->Users->find('all'));
}
}
then it should automatically have the Model, Users, in models/users.php available to it right? Therefore the variable $MT can be echoed on the page.
The contents on Users.php are:
<?php
class Users extends AppModel{
var $name = 'Users';
}
The problem I'm having though seems to be:
Undefined property: UsersController::$Users [APP\controllers\users_controller.php
and thus leads to:
Call to a member function find() on a non-object in app\controllers\users_controller.php
I'm following the tutorial at http://book.cakephp.org/1.3/en/The-Manual/Tutorials-Examples/Blog.html for cakePHP 1.3 running on a WAMP server. Any advice you can give would be appreciated! Thanks a lot!
change your model name:
class Users extends AppModel{
...
to
class User extends AppModel{
...
and:
$this->set('MT', $this->Users->find('all'));
to
$this->set('MT', $this->User->find('all'));

Resources