Restful PHP API Help

I am just starting / learning a simple restful api using ToroPHP.
I am faily new to it all so am creating a simple project.

This is my toro routes:
<?php 
require_once ('Toro.php'); 
require_once ('includes/database.php');
require_once('ScoreHandler.php');

class HelloHandler {
    function get() {
    	$user = "world";
    	if(array_key_exists('user', $_GET))
    		$user = $_GET['user'];
        echo "Hello, $user";
    }
}

ToroHook::add("404",  function() {
	header("HTTP/1.0 404 Not Found");
    //include('404.php');
    exit;
});

Toro::serve(array(
    "/hello/world" => "HelloHandler",
    "/score" => "ScoreHandler",
    "/score/round/([0-9]+)" => "ScoreHandler",
    "/score/team/([0-9]+)" => "ScoreHandler"

));
?>

Open in new window

Im not sure how I will distinguish between /score  or  /score/round   or  /score/team

Then the 3 functions are within this file (ScoreHandler.php):
<?php

class ScoreHandler {
    function get($teamId,$roundId) {
        
        global $con;


        $queryTxt = "SELECT * FROM score WHERE teamId = :teamId";

        if ($teamId) {
            echo "team";
        } else if ($roundId) {
            echo "round";
        } else {
            echo "none";
        }

            try {
                $query = $con->prepare($queryTxt);
                $query->bindParam(':teamId', $teamId, PDO::PARAM_INT);
        
                $query->execute();
                //$result = $query->fetchAll();

                while($row = $query->fetch(PDO::FETCH_ASSOC)) {
                    echo json_encode($row);
                } 

            } catch (PDOException $e) {
                header("HTTP/1.0 500 Internal Server Error");
                echo 'ERROR: ' . $e->getMessage();
            }
 

    }

}

?>

Open in new window


Basically what I want to know is can I use the same function to pull different data from the query (using the where clause).
I want
"/score" => "ScoreHandler" to show ALL scores
"/score/round/([0-9]+)" => "ScoreHandler" to show scores with in a particular round
"/score/team/([0-9]+)" => "ScoreHandler"  to show scores with in a particular team

the mysql table looks like this:
score table
Steve TinsleyAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

gr8gonzoConsultantCommented:
Toro does a foreach loop on the routes, starting at the top and working its way down. When it finds a match for the request, it will break that loop (stop looking for any other matches). That means that if you have "/score" as an entry BEFORE the other entries like "/score/round", then Toro will never make it to the other handlers, because "/score" will also match a request like "/score/round". So first thing to is ensure that the more specific matches go first, and the more generic ones go last:

Toro::serve(array(
    "/hello/world" => "HelloHandler",
    "/score/round/([0-9]+)" => "ScoreHandler",
    "/score/team/([0-9]+)" => "ScoreHandler"
    "/score" => "ScoreHandler",
));

This is the proper order, but Toro doesn't pass anything over to the handler except for anything matched in the regex. So with the above, your ScoreHandler wouldn't know if it was handling a round or a team or just the base request. That means you need to capture the request as part of the regex, so you can code around it. The easiest way to do that would probably be:

Toro::serve(array(
    "/hello/world" => "HelloHandler",
    "/score/(round|team)/([0-9]+)" => "ScoreHandler",
    "/score" => "ScoreHandler",
));

Now your ScoreHandler should be able to determine what kind of request it is, and from there you can code your various paths.
1
Steve TinsleyAuthor Commented:
That's excellent! Has really helped me understand this but has also brought a few more questions :(

Ideally I would like the same getter to give me
/score
/score/team/#
/score/round/#
/score/team/#/team/#

Question 1
Is this a reasonable request?? How would I make that route work


Question 2
Help with my php class....
function get($type1=null,$data1=null,$type2=null,$data2=null) {
        
        global $con;

        if ($type1 == "team") {
            $queryTxt = "SELECT * FROM score WHERE teamId = :teamId";
        } else if ($type1 == "round") {
            $queryTxt = "SELECT * FROM score WHERE roundId = :roundId";
        } else {
            $queryTxt = "SELECT * FROM score";
        }

        try {
            $query = $con->prepare($queryTxt);
            $query->bindParam(':teamId', $data1, PDO::PARAM_INT);
            $query->bindParam(':roundId', $data1, PDO::PARAM_INT);

            $query->execute();

            while($row = $query->fetch(PDO::FETCH_ASSOC)) {
                echo json_encode($row);
            } 

        } catch (PDOException $e) {
            header("HTTP/1.0 500 Internal Server Error");
            echo 'ERROR: ' . $e->getMessage();
        }
    }

Open in new window

How is best to sort the data coming from the restful request to the queryTxt and is there a good why of dynamically creating my bindParam
0
gr8gonzoConsultantCommented:
Toro is pretty minimal, so if you have some complex possibilities for your parameters, it's probably better to just capture all the parameters and process them separately:

Toro::serve(array(
    "/hello/world" => "HelloHandler",
    "/score(/.*)?" => "ScoreHandler",
));

In your handler, use explode() to split any additional parameters by the "/" character, or use further regular expressions:

function get($strParams = null)
{
   $arrParams = array();
   if($strParams != null)
   {
     // Parse all parameters
     if(preg_match_all("@/(team|round)/([0-9]+)@",$strParams,$matches))
     {
       foreach($matches[1] as $idx => $param_type)
       {
         $id = $matches[2][$idx];
         $arrParams[] = array($param_type, $id);
       }
     }

     // Dump all parameters
     print_r($arrParams);
   }
}
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Ray PaseurCommented:
Probably the best example (and best documented routing) for a RESTful API can be found in Laravel.  If I were you, I would kick Toro to the curb and pick up Laravel or its cousin Lumen.  Plenty of online tutorials from Laracasts, too.
http://laravel.com/docs/5.1/routing
http://lumen.laravel.com/docs/routing
https://laracasts.com/
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.