• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Rather Newish to OOP, Controller question

#1
So I have something working how I wish it to but I am not sure it is the best way to do it. Essentially, I have a controller called PROJECT.php and two methods inside that controller, JOIN($project_id) and ENTER($project_id).

The join() is simple and queries information about the PROJECT from the database and sends it to the join.php view.

The join.php view has a simple form:

PHP Code:
               <?php
                $attributes 
= array('class' => 'form-horizontal');

 
               echo form_open('project/enter/' $pool['pool_id'], $attributes);
 
               ?>
                <p>Pay <?php echo $project['amount']; ?> to enter the pool? Currently <?php echo $project['entries'] . ' of ' $project['max_entries']; ?> have entered</p>
                <?php if (in_array_r($auth_user_id$entries)) { ?>
                    <p>You have Already Joined.</p>
                <?php } else { ?>
                    <button type="submit" class="btn btn-default">Join</button>
                <?php ?>
                <?php
                echo form_close
();
 
               ?>

So it is simply posting it to the project($project_id) method, which checks a permission and if passes submits data to the database.

PHP Code:
   public function enter($project_id) {
 
       if ($this->require_min_level(1)) {
 
           $data = array(
 
               'project_id' => $project_id,
 
               'user_id' => $this->auth_user_id
            
);

 
           $this->load->model('project_model');
 
           $this->pools_model->add_entry($data);
 
           $this->load->view('includes/nav');
 
           $this->load->view('join');
 
           $this->load->view('includes/footer');
 
       } else {
 
           $this->load->view('includes/nav');
 
           $this->load->view('join');
 
           $this->load->view('includes/footer');
 
       }
 
   

The problems I currently have: 


1) How do I prevent someone from just loading the enter($project_id) controller without using the join($project_id) controller?
2) How can I setup error checking? I would rather do this correctly (globally) as I am pretty early in this project and prefer to take my time and do things the right way. I know Codeigniter does basic error checking by default but to what extent? 
3) Anything you would do different to get the same result?

Is anything blatantly wrong with the above that I should kill right now before I get too far in?

Thanks! Looking forward to getting better at OOP and Codeigniter.
Reply

#2
It's a bit confusing. You say that the join method (in the Project controller, right?) loads information from the database and sends that to the join view.
In your code, I see that the enter method opens the join view. It's not clear what the join method does.
What are the URL's that a visitor must type to enter or join a project?

Then, you have this code twice in the same method:
PHP Code:
$this->load->view('includes/nav');
$this->load->view('join');
$this->load->view('includes/footer'); 
You can avoid this, by putting this code outside the if { } structure. Because in the end, you Always want to load the join view, no matter what.

One other thing: you aren't passing any data to the view. But your view is using the $project array. Where does this array come from?
Reply

#3
Hi Wouter60,

Here is join method which loads the Join view. Join view submits to the enter method and enter method reloads the join view.

PHP Code:
   public function join($project_id) {
 
       if ($this->require_min_level(1)) {
 
           if ($data['project']['active'] == 1) {
 
               $this->load->model('project_model');
 
               $data['pool'] = $this->project_model->get_project($project_id);
 
               $data['entries'] = $this->project_model->get_entries($project_id);
 
               $this->load->model('validation_callables');
 
               $this->load->library('form_validation');
 
               $this->load->view('includes/nav');
 
               $this->load->view('join'$data);
 
               $this->load->view('includes/footer');
 
           } else {
 
               redirect('project/');
 
           }
 
       }
 
   

What I want to do is that after they are entered into the project, load up the join view again and present them information about their entry or errors that might have happened.
Reply

#4
Let me try again at explaining what I am trying to do here:

Controller Project -> Class Project -> Method Join($project_id) -> View join with the above code. Once that page is loaded the visitor is asked if they would like to join the project. If they click join:

Controller Project -> Class Project -> Method Enter($project_id) -> View join is called and the code inside Method Enter is run.

What I am trying to figure out is if this is the best way to do this because I want to also do the following:

1) Prevent direct access to Method Enter via url. So if someone copies the url http://www.site.com/project/enter/1 into their browser it will not run any of the code within the method.
2) Provide error checking and error feedback after the Join button is pressed as well as provide information about things that may have changed due to them joining the project (ex. list how many more projects they can now join, return an error if they are not allowed to join, return an error if the project became full or expired before they pressed join... etc)

Is this approach with MVC the correct one so far? I apologize if this is a question that should be easy to figure out via documentation. It just isn't clicking to me and my MVC learning curve still leaves a lot to be desired.
Reply

#5
To stop the meyhod from running in the URL start the method with an underscroe _method
What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply

#6
(05-20-2016, 02:45 AM)InsiteFX Wrote: To stop the meyhod from running in the URL start the method with an underscroe _method

Ok so make it a private function? Would private function enter($project_id) essentially be the same or is that different?
Reply

#7
Ok, I tried that (I thought I had tried that before.. and I had). When I submit the form now I get a 404 not found and the url shows p in the address bar as trying to call the enter method that needs to not be accessible to the public.

Do I need to do something else with the form post?
Reply

#8
You can check if the user has posted the form or typed the url directly.
E.g. your submit button is named 'submit'.
Put this in your controller:
PHP Code:
if  (! $this->input->post('submit') ) {
    
show_404();
    exit;


You also want form validation.
Read the documentation about the form_validation library.
Reply

#9
I usually post my forms back to the same URL. This allows me to avoid duplicating some of the code (or creating another method to house the code which would otherwise be duplicated), especially the code which loads the view and sets up everything else on the page which is not related to the submitted form data. This also avoids having to use a redirect() or show_404() call unless you want to send the user to a different page after processing the form.

As Wouter60 already stated, you can just check $this->input->post('submit') in the method to see if the form was submitted (though you should put a name attribute on the button and check $this->input->post('value-of-name-attribute'); also, it may be easier to use an input element rather than a button element for that purpose).

It also looks like you're relying on a lot of variables/data to be available throughout your view(s) and controller ($data in join() and $project, $auth_user_id, and $entries in the view), but you're not explicitly defining or passing those variables in the code you've included. The form you've included in your view will likely post nothing at all, given that nothing in the form has a name attribute defined.

Finally, if the whole purpose of the form is to join the project, the form itself shouldn't be rendered if the user has already joined (as opposed to just not rendering the submit button). So, your view would look something like this:

PHP Code:
<?php
$attributes 
= array('class' => 'form-horizontal');

if (
in_array_r($auth_user_id$entries)) { 
?>
<p>You have already joined.</p>
<?php } else { ?>
<p>Pay <?php echo $project['amount']; ?> to enter the pool?
    Currently <?php echo "{$project['entries']} of {$project['max_entries']}"?> have entered.
</p>
<?php echo form_open('project/enter/' $pool['pool_id'], $attributes); ?>
    <input type='submit' name='submit' class="btn btn-default" value='Join' />
<?php
    echo form_close
();

Also, remember to check in_array_r($auth_user_id, $entries) (and, presumably, that $project['entries'] < $project['max_entries']) in your validation even if you're checking before displaying the form. The user could have entered on another page while this one was displayed. You may also want to check whether $project['entries'] < $project['max_entries'] before displaying the form, since you probably wouldn't want people submitting at that point, either (though you'd most likely display a different message, since they may not have joined). It can be tempting to pass the data that needs to be verified through in the form, but it's more secure to retrieve it from the server instead. It also allows you to make sure you account for any submissions from other users/pages since the user initially loaded the form.
Reply

#10
Thank you very much to everyone who has responded. It has helped clear things up greatly.
Reply


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2019 MyBB Group.