Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm building a stream of data based on users a user is following. While I have a working prototype, the code seems unnecessarily ugly with multiple loops with further queries nested in them. I was wondering if I could get any advice on simplifying this, possible handling more within the sql query itself? On with some code: (I've trimmed this down a little and removed some of the rows retrieved).

$init = $conn->prepare("SELECT followerid FROM following WHERE userid=?");
$init->bind_param("s", $userid);
$init->execute();
$init->bind_result($idq);
$init->store_result();
$num = $init->num_rows();
  while($init->fetch()) {

    // get all to be done by each user
    $stmt = $conn->prepare("SELECT activityId FROM done WHERE userId=? ORDER BY number DESC");
    $stmt->bind_param("s", $idq);
    $stmt->execute();
    $stmt->bind_result($aiddo);
    $stmt->store_result();
    $num_do = $stmt->num_rows;
      while($stmt->fetch()) {
        $activityId_do[] = $aiddo;
      }

    // get location information
    for($i=0; $i<=$num_do; $i++) {
      $act_done = $conn->prepare("SELECT fullAddress FROM `activity` WHERE (id=?)");
      $act_done->bind_param("s",$activityId_do[$i]);
      $act_done->execute();
      $act_done->bind_result($fullAddress);
        while($act_done->fetch()) {
          $do_array[] = array(
            "fullAddress"=>$fullAddress,
            "type"=>"do"
          );

        }
    }

    //get all done by each user
    $stmt = $conn->prepare("SELECT activityId FROM done WHERE userId=? ORDER BY number DESC");
    $stmt->bind_param("s", $idq);
    $stmt->execute();
    $stmt->bind_result($aid);
    $stmt->store_result();
    $num_done = $stmt->num_rows;
      while($stmt->fetch()) {
        $activityId[] = $aid;
    }

    for($i=0; $i<=$num_done; $i++) {
      $act_done = $conn->prepare("SELECT fullAddress FROM `activity` WHERE (id=?)");
      $act_done->bind_param("s",$activityId[$i]);
      $act_done->execute();
      $act_done->bind_result($fullAddress);
        while($act_done->fetch()) {
          $done_array[] = array(
            "fullAddress"=>$fullAddress,
            "type"=>"done"
          );

        }
    }

    //get all stories by each user
    $stmt = $conn->prepare("SELECT activityId FROM story WHERE userId=? ORDER BY number DESC");
    $stmt->bind_param("s", $idq);
    $stmt->execute();
    $stmt->bind_result($aidst);
    $stmt->store_result();
    $num_story = $stmt->num_rows;
      while($stmt->fetch()) {
        $activityId_story[] = $aidst;
      }

    for($i=0; $i<=$num_story; $i++) {
      $act_done = $conn->prepare("SELECT fullAddress FROM `activity` WHERE (id=?)");
      $act_done->bind_param("s",$activityId_story[$i]);
      $act_done->execute();
      $act_done->bind_result($fullAddress);
        while($act_done->fetch()) {
          $story_array[] = array(
            "fullAddress"=>$fullAddress,
            "type"=>"story"
          );

        }
    }

}

I originally thought about using a union on the three queries inside the initial while loop, but each array built from the query MUST display the "type"=>"" field, this is hugely important as the way items are displayed in the stream depend on this.

One of the main reasons I was lead to believe there must be a batter way as nesting a query in the second while loop kicked up a stink of errors, thus the use of the for loop on the amount of of rows. But this code just doesn't feel right. It feels ugly and really repetitive, and although it works, I feel it shouldn't be settled for.

After this block of code is run, all 3 arrays are merged into one multidimensional array, like so:

Array
(
[0] => Array
    (
        [fullAddress] => London, England
        [type] => do
    )

[1] => Array
    (
        [fullAddress] => Portsmouth, England
        [type] => done
    )

[2] => Array
    (
        [fullAddress] => Paris, France
        [type] => story
    )

) 

Is there a better way to do this and is this the best way to build the multi-dimensional array in this case?

share|improve this question

1 Answer 1

I would create a table in the database for followed_users or something, where you link your user to the id's of users they are following, then you query that table for the list of id's and run your next query to get the information you are pulling (or, if the data is small, store that data as well into the table

=======================================
| id | user_id | following_id | type  |
=======================================
|  1 |     101 |           12 | story |
|  2 |     108 |           15 | story |
|  3 |     108 |           16 |    do |
|  4 |     108 |           19 |  done |
=======================================

maybe even add in the address, if that is all you are pulling

share|improve this answer
    
While a great suggestion this wouldn't work as each user can have items of each state. They could have items that they are doing, have done and added a story for all at the same time. This is why the type is tied to the type of information that is returned. It's sole use is to tell the javascript how to display the output. –  Jamie Turner yesterday
    
You can have multiple rows with the same user_id and following_id with different type items... that's the joy of databases –  Kender yesterday
    
Yer, I know. But I just can't see how this would solve the issue. It works the way it is, I was just wondering if there way a better way of going about it. Moving the type into the first query seems like it would over complex everything even further. Plus I would then need a new row in the following table for every item in the activity table. What you recon about using a union on the queries inside the first loop. For example: Join the done query with the location information query? –  Jamie Turner yesterday

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.