1

I want to make a restriction if lecID appears twice in the database, it will unable user to insert data into database. But the code has some problem which it will still insert into db even though lecID appears more than two time in my database. Can I know what is the problem. Below is my code:

     <?php

            require ("config1.php");

            if(!empty($_POST)){

       //UPDATED  
           $query="SELECT lecID, COUNT(*)  FROM proposal GROUP BY 
                      lecID=:lecID HAVING COUNT(*)>2 ";
                         $query_params= array(
                          ':lecID'=>$_POST['lecID']
                     );


       try {
         $stmt   = $db->prepare($query);
         $result = $stmt->execute($query_params);
       }catch (PDOException $ex) {
         $response["success"] = 0;
         $response["message"] = $ex->getMessage();
        die(json_encode($response));
}

$row= $stmt->fetch();
    if($row){
    $response["success"] = 0;
    $response["message"] = "This supervisor has reached maximum students.";
    die(json_encode($response));

    }



            $query="SELECT 1  FROM proposal WHERE stuName= :stuName ";
                $query_params= array(
                    ':stuName'=>$_POST['stuName']
                );

        try {
            $stmt   = $db->prepare($query);
            $result = $stmt->execute($query_params);
        }catch (PDOException $ex) {
            $response["success"] = 0;
            $response["message"] = "Database Error!";
            die(json_encode($response));
        }

        $row= $stmt->fetch();
            if($row){
            $response["success"] = 0;
            $response["message"] = "You have already choose supervisor.";
            die(json_encode($response));

            }


        ?>

Really appreciate if someone can point out the problem.

Lawrence
  • 73
  • 6
  • You are checking for if there are any lecId that is present more than twice, i think you have to add a condition to check the specific lecid which you are going to insert. The query should be, select count(*), lecid from proposal where lecid = $_POST['lecID'] group by lecid having count(*) > 2 – Hariraman Radhakrishnan Oct 14 '17 at 08:25
  • And you need to check the return value of the count, not the entire row. – Shadow Oct 14 '17 at 08:33
  • Not working :( @HariramanRadhakrishnan – Lawrence Oct 14 '17 at 08:52
  • can you post the query you have tried? @Lawrence – Hariraman Radhakrishnan Oct 14 '17 at 08:53
  • Your question is has some syntactical issues that make it a little unclear. When I read your code I am guessing you want a Student to be able to create multiple proposals, but if they chose a Lecturer in one proposal they cannot select that Lecturer again. Is that correct? IMO (assuming you are the one doing the data model) I would set a unique index in your "table.proposal" using the stuID and lecID to enforce data integrity, and second, at a minimum redo your insert method to accommodate the error response on violations of that DB rule – David Lundquist Oct 14 '17 at 08:57
  • This SO has the required SQL to have your Database enforce the rules you want, and throw an error if your user violates them. https://stackoverflow.com/questions/635937/how-do-i-specify-unique-constraint-for-multiple-columns-in-mysql PS IMO It is a very bad idea to allow your application to control the data integrity of your DataBase, where possible always let the DataBase control the data integrity :-) – David Lundquist Oct 14 '17 at 08:58
  • One student can only submit one proposal to one lecturer, if submit more than two times to diffent lecturer, it will be restricted. And one lecturer can accept maximum two students( got error that shown in my code). I want to restrict if more than two students add this lecturer, it will not be accepted @DavidLundquist – Lawrence Oct 14 '17 at 09:02
  • Updated my code @HariramanRadhakrishnan – Lawrence Oct 14 '17 at 09:03
  • @DavidLundquist That means I need to add UNIQUE KEY for my lecID? – Lawrence Oct 14 '17 at 09:05
  • Change SQL to `SELECT lecID, COUNT(*) FROM proposal WHERE lecID=:lecID GROUP BY lecID HAVING COUNT(*)>2`. Your `GROUP BY` was making two groups: one for the ID in interest, but also another for all other ID values, so you always had results. – trincot Oct 14 '17 at 09:10
  • I think with your current code you're checking for lecturers who are having more than two students currently. HAVING COUNT(*)>2 returns true only when the lecturer already has two students. This is the reason i think it is creating more than two records. Instead you should check the count is < 2 and then allow that lecturer to be added. – Hariraman Radhakrishnan Oct 14 '17 at 09:10
  • OK so first thing I would do is create a UniqueIndex on your proposal table as discussed, that will make the combination of (stuID and lecID) unique. That will solve your first problem, as your DataBase with throw an error if a student tries to select the Lecturer more than one time....then I would build a PHP method to check for the other two business rules you have as boolean functions so you can check before insert: 1. function isStudentProposalMax() and 2. function isLecturerClassFull() – David Lundquist Oct 14 '17 at 09:12
  • You would add a unique Key for the combination of stuID+lecID, this will prevent any inserts occurring where a student has already chosen lecID. Use a tool like HeidiSQL if you are not comfortable with the command interface for DataBase – David Lundquist Oct 14 '17 at 09:14
  • Noted with Unique key but can you please write the code down as I am not so clear. ? @DavidLundquist – Lawrence Oct 14 '17 at 09:22

1 Answers1

0

First thing, for solving your problem, IMO you should at least try to encapsulate your code in several functions that you can call for each step.

BUSINESS RULES for student course proposals:

  1. A Student that is allowed to create two proposals. The student cannot select the same lecturer for both proposals (DB RULE).
  2. A Lecturer can only accept two Student proposals (each proposal will be a different student).

    ISSUE Your rule here has ambiguity, so I am making an assumption that the proposal table could have more proposals than two that can be assigned to the same lecturer but that each proposal must be a different stuID. I am assuming you have a column called 'is_proposal_accepted' in that table that is set to true when a lecturer accepts a proposal.

  3. student when creating a new proposal cannot choose a Lecturer if that Lecturer has "accepted" two proposals or the student has chosen that Lecturer in a previous proposal.

Step one Enforce the Data Integrity requirement of your Business Rules in the database not in your code:

 ALTER TABLE `proposal` ADD UNIQUE `unique_index`(`stuID`, `lecID`);

Execute the above in your database using the Command Line or a tool such as Heidi SQL.

Step two Encapsulate your code (Some very rough pseudo code to help you with structure):

        class Proposal
        {
            private $dataArr = [];
            private $response = [];

            public function doit($postArrayData)
            {
                //Clean up data if there are issues reject
                if (!$this->clean_up_data($postArrayData)) return $this->get_response();

                /**
                 * Before even trying to do any data inserts check the business rules
                 * Check if the lecturers
                 */
                if (!$this->check_if_lecturer_is_open()) return $this->get_response();
                if (!$this->check_if_student_has_available_proposals()) return $this->get_response();


                /**
                 *    
                If you have reached here in the method your Application based Business rules have been achieved


                NOW save the reocord, if the data violates the
                DB Rules your response will be set to an error,
                otherwise it will show a success message

                 */
                $this->add_proposal();
                return $this->get_response();
            }

            public function clean_up_data($postArrayData)
            {
               /**
                 * Apply any validation checks for data quality here then assign to array
                 EXAMPLE:  Set each field parameter like so:
                 */
                $this->dataArr['stuID'] = $postArrayData['stuID'];

                if (DataHasIssues) {
                    $this->set_response(0, "Crappy Data try again");
                    return false;
                }
                return true;
            }

            //Keep this method private, we want our POST data to be processed first and the in
            private function add_proposal()
            {



                /**
                 * 
                 * 
                 * 
                 * Your DB calls here.....
                 *
                 *  $query = "INSERT INTO proposal (lecName,lecID,stuName,stuID,proposalTitle,proposalObjective,proposalDesc)
                 * VALUES (:proposalID,:lecName,:lecID,:stuName,:stuID,:proposalTitle,:proposalObjective,:proposalDesc)";
                 */
                $query_params = $this->dataArr;
                /**
                 * Execute query with error control here.....
                 * if(ExecuteQuery){
                 *         * return true;  //Student proposal has been added
                 *}
                 * set errors here
                 */
                $this->set_response(0, DB_errors_msg);
                return false;

            }

            private function set_response($success, $message)
            {


                $this->response["success"] = $success;
                $this->response["message"] = $message;


            }

            public function get_response()
            {


                return $this->response;


            }

            public function check_if_lecturer_is_open()
            {

                /**
                 *
                 * $countOfAcceptedProposals ... Select SQL code here to count if the lecID has had two proposals flagged as accepted
                 * */
                if (CountOfAccepptedProsalsByLecID < 2) {
                    return true;
                }
                $this->set_response(0, "This Lecturer is full and is not available");
                return false;
            }


            public function check_if_student_has_available_proposals()
            {

                //USE the dataArr to get the StuID you want to check


                $CountOfProsalsByStuID = returned_count;// select count from where stuID = $this->dataArr['stuID'];

                /**
                 *
                 * $countOfStudentProposals ... Select SQL code here to count if the lecID has had two proposals flagged as accepted
                 * */
                if ($CountOfProsalsByStuID < 2) {
                    return true;
                }
                $this->set_response(0, "Student has reached the maximum number of proposals allowed");
                return false;
            }


        }

Now you can call the Proposal class and have it do the hard work of checking your business rules and saving your Student Proposals properly.

    $proposal = new Proposal();
    echo json_encode($proposal->doit($_POST));  //This returns your response object
David Lundquist
  • 650
  • 7
  • 19
  • What is `DataHasIssues`? Should it be `$DataHasIssues`? – Script47 Oct 14 '17 at 15:12
  • DataHasIssues is just Pseudo Code (fake code to let a developer know what to do).... in this case, I am testing to see that all the data the Student entered comply with my rules. If the data has problems such as "missing data" I would reject it, set my var $DataHasIssues to false. You sound keen to learn to code and I would suggest you check out https://www.freecodecamp.org/ for some free training. – David Lundquist Oct 14 '17 at 21:16
  • If you are a new developer with little time for the details but wish to create a well-built data-driven application that works well I would highly recommend you watch this video. Using the tools shown here is a great way to get started in Laravel for the noob. :-) https://vimeo.com/154415433 – David Lundquist Oct 14 '17 at 21:38