I have a form in my Yii2 project and I need to allow for multiple models to be created using it. Overall I have a single Group and multiple Person ActiveRecords that will be created using the form, and each Person record will belong to the Group.
For example I have this class that is the form:
<?php namespace app\models\forms;
class GroupForm extends yii\base\Model {
public $name;
public $description;
public $date;
public $people = [];
....
}
And visually it will be something similar to this:
I want to be able to use the plus and minus buttons to add additional people to the form. I have the JS in place to actually handle the HTML cloning and such, but I am not sure about how to create the first Person.
I know that I will need the name to be something like Person[0][first_name] but when I instantiate the GroupForm there are no people objects created yet (saved or in memory) so I can't do something like <?php echo $form->field($model->people[0], 'first_name')->textInput(); ?>.
Once the form was submitted I planned on then iterating over all of the 'People' fields in the POST data and loading that into new People objects.
Is it possible to do this with the ActiveForm or is the answer to just not use the ActiveForm and create the inputs using the Html class in Yii and then using JS to change the person index?
Basically what I understood from your post is you need to use dynamic form in your Yii2 project. In your case the form should be containing the group information plus multiple persons to be created along with it. In Yii2 this functionality can be implemented through the usage of wbraganca/yii2-dynamicform form widget.There is very good documentation to how to use the widget with an example scenario.The widget documentation can be found at
https://github.com/wbraganca/yii2-dynamicform
More information and working demos at
http://wbraganca.com/yii2extensions/dynamicform-demo1/create
Hope this helps
Related
This is a question about how to create a better application with awesome Laravel. I want to create a CRUD application with multiple forms with user's permissions.
Details:
View. I have 3 forms, for example lets call it cat, turtle and dog. The most important is that they have different number of fields.
Here are forms
Controller. After user filled in the form and pressed save button the controller in the game. All of us know that the thinner controller is the better it is. But I use construction like this:
switch($type)
{
case '1':
//form validation -> move to model
//if all have passed that insert into database
//Show user a message
break;
case '2':
//form validation -> move to model
//if all have passed that insert into database
//Show user a message
break;
//.....
default:
//show message
break;
}
Where variable type equals form's type which has been filled in by a user. But as you can see now the controller is pretty big, and I don't like it. What the best way to do this?
Model.
I have 4 table, dogs_data, turtle_data, cat_data where I store all data from forms and pets_data where I store different metadata about pets above. How does it work? After validation passed insert data into one of these tables and get ID of this insertion. Then create the record in pets_data and insert the ID as pet_id and also insert table_type which will be required to get information from database. I think that it is very weird way to work with database. Here is table's visualisation.
Another problem is - show data. For example user has no permissions to edit data or delete records, but admin can remove, updated and see a lot of data from database. Should I create another controller like AdminController and write there another method which display information only for admin?
My application now:
WebSiteController - display website
AdminController - admin page, there is a method which generate special page to view pets.
UserController - users control panel, there is also method which generate page to view pets, but special for user.
And I think to create something like this
AuthController - special for login\registration\activation\etc
PetsController - create\delete\update\etc and also view in two variation: for user and admin. And idea is to create a method getShowPets($pet_id) (important it is only id from pets_data, not the pets_id) then get permission of the user and generate page.
And so on, I want to re-write my application use DRY rule
So I will very happy if you can give me some good tips about this project.
It looks like you are setting up a polymorphic relation, in which case, I would make everything separate meaning you'd have a model for Cat, Dog, Turtle, and PetData. You'd have controllers for CatController, DogController, and TurtleController. And you'd have a Cat form, a Dog form and a Turtle form, each that also contain inputs for the data you require for your pet_info table.
To create the polymorphic relation, your pet_data table will require some changes. Just change the table column to pet_type. Laravel expects a certain name for this column and for its contents to be the name of a model rather than the name of your table.
Setting up the models for these is very easy, I'll do the PetData and the Dog one to get started.
class Dog extends Eloquent
{
protected $table = 'dogs_data';
protected $timestamps = false;
public function petData()
{
return $this->morphMany('PetData', 'pet');
}
}
class PetData extends Eloquent
{
protected $timestamps = false;
public function pet()
{
return $this->morphTo();
}
}
Can read more about this here... http://laravel.com/docs/eloquent#polymorphic-relations
The idea of having separate models/controllers for everything might seem like a lot of work, but it goes a long way when trying to maintain or add additional animals to your app because you should rarely have to modify production code, taking away the possibility of introducing more bugs when trying to add enhancements to your website.
Now it becomes very easy to save a pet and related pet data without having to worry about the pet_id and pet_type in the pet_data table, Laravel will take care of that for you. The function on your dog controller might look like this...
class DogController extends BaseController
{
public function save()
{
$dog = new Dog;
$dog->name = Input::get('name');
$dog->age = Input::get('age');
$dog->save();
$pet_data = new PetData;
$pet_data->color = Input::get('color');
$dog->petData()->save($pet_data);
}
}
As far as creating another controller for admins, I would say yes, do that. It never hurts to keep parts of your website that you consider different in different files. It not only helps with organization, but again, with separation of concerns, which you should probably read more about.
There are also some fantastic 3rd party options for managing roles. I've used zizaco/entrust before and found it very easy to manage. It might make your life a lot easier when trying to manage who can do what on your web app.
I have a Yii form based off a database model/table that I now want to add a custom field too that can then be accessed in the corresponding controller.
So the custom field DOES NOT correspond to a column in the database table.
Can this be done? If so how?
My motivation for doing this is to add a form value that I check, and I only process the form IFF that form value is empty. The field is hidden using CSS, so humans won't see it, and will hopefully be a simple convenient way to minimize spam. Since a bot is likely to fill out the form indiscriminately.
CAPTCHA Alternatives
Hope this makes sense.
Thanks!
You need to add simple property to model:
class User extends CActiveRecord {
public $myField;
}
Also do not forget to add its field in rules() if so required
Between start & end of rendering your form insert hidden (for example) next:
<?php echo CHtml::hiddenField('hidden_secret',''); ?>
Than in controller:
$hidden_secret = Yii::app()->request->getParam('hidden_secret'));
How can i pull data from different tables(models) into view in yii. actually i done this with loadModel method. but my question is how can we import the rules into the view too. Here comes my scenario
I have a User model and Profile model. The User model contains username and password and Profile model contains userid,name,address etc. so in my profile edit view i need all these data with the rules, username-unique,password,confirm pasword-required, etc., i can implement the required rule to all these, but i dunno how to import the table related rules like unique.
So basically this is a form that takes in two models and displays that data for you to edit and submit.
Simply make the render call to your view and pass both the models. e.g. $this->render('aview', array('model1'=>$model1, 'model2'=>$model2));
Get your view to display the form elements based upon these models.
When you submit simply create new objects for respective models and populate them with the data received. e.g.
$model1 = new model1;
$model1=>id = id; //id received from the form submit.
...............
Once you have the models populated you can call validate() on each of them to figure out if the data is according to your rules. If it is you proceed otherwise you display error. I hope this helps unless I missed something in your question.
Hi I'm trying to use the CakePHP comments plugin found here http://cakedc.com/downloads/view/cakephp_comments_plugin but the instructions are really hard to follow. I've managed to add comments but it's displaying the commentWidget that's not working.
I'm getting confused at this part i think
To work properly, the component needs
a specific variable to be set in every
action using it. Its name should be
either
Inflector::variable(Controller::$modelClass)
or Comments::$viewVariable should be
set to other name of this view
variable. That variable should contain
single model record. for example you
need to have next line in you view
So far I've created the comments table, added it to the pluging and components arrays and added the following code to the controller:
public function beforeFilter() {
parent::beforeFilter();
$this->passedArgs['comment_view_type'] = 'flat';
}
I added the route
Router::connectNamed(array('comment', 'comment_view', 'comment_action));
And also the Comments.CommentWidget as a helper in my controller.
I'm just wondering if anyone has used this plugin before and can help me out?
thanks,
Jonesy
You're right - the documentation is really confusingly worded. However, if I understand correctly, what it wants is a copy of the record of the piece of data the comment will be attached to passed to the view the comments will render on.
So say you're making an event page, and you want people to comment on the event. You need to send to the view a variable called "event" with a copy of the base data for that event.
From their example they show: $this->set('post', $this->Post->read(null, $id));
For your event, you'd do something like $this->set('event', $this->Event->read(null, $id_of_event));
The Comment view probably needs this data for hidden fields so it can populate it with the model name and the event id.
I'm new to the MVC pattern but have been trying to grasp it, for example by reading the documentation for the CakePHP framework that I want to try out. However, now I have stumbled upon a scenario that I'm not really sure how to handle.
The web site I'm working on consists of nine fixed pages, that is, there will never exist any other page than those. Each page contains something specific, like the Guest book page holds guest book notes. However, in addition, every page holds a small news box and a short fact box that an admin should be able to edit. From my point of view, those should be considered as models, e.g. NewsPost and ShortFact with belonging controls NewsPostController and ShortFactController. Notice that they are completely unrelated to each other.
Now, my question is, how do I create a single view (web page) containing the guest book notes as well as the news post box and the short fact? Do I:
Set up a unique controller GuestBookController (with an index() action) for the guest book, so that visiting www.domain.com/guest_book lets the index action fetch the latest news post and a random short fact?
Put static pages in /pages/ and in let the PagesController do the fetching?
< Please fill in the proper way here. >
Thanks in advance!
It sounds like you need to look into elements, or else you may be able to embed this into the layout - but its neater to use an element if you ask me, keep the things separate.
http://book.cakephp.org/2.0/en/views.html#elements
These allow you to have create small views that you are able to embed into other views.
You may also need to put some logic into the AppController (remember all other controllers extend the app controller) to load the data required for these views. The beforeRender function should be useful for this - its one of the hook functions cakephp provides, so if you define it on a controller, its always called after the action is finished before the view is rendered.
Something like this in your AppController should help:
function beforeRender() {
$this->dostuff();
}
function doStuff() {
// do what you need to do here - eg: load some data.
$shortfacts = $this->ShortFact->findAll();
$news = $this->NewsPost->findAll();
// news and shortfacts will be available within the $shortfacts and $news variables in the view.
$this->set('shortfacts', $shortfacts);
$this->set('news', $news);
}
If there are models you need in the app controller for use within this doStuff method, then you need to define them within uses at the top of the AppController
class AppController {
var $uses = array('NewsPost', 'ShortFact');
}