|

How To Filter Via Query Strings

How To Filter Via Query Strings

This tutorial will focus on adding the ability to filter by query strings when fetching information from the database. There are a few other ways you could do this type of filtering, but many times a simple query string is a nice way to go about it. We’ll start by running all of our tests, and fixing anything that might have gone wrong. Once that is taken care of, we can move on to adding a new feature test to support our new feature of filtering threads by query string. Once the test is set up, we build the feature, test again, and make sure everything is good to go. Let’s set up filtering by query strings now.

In our application, we do not yet have the ability to filter threads by user. The feature we would like to add is to be able to click on a user’s name, and the application will filter and display all threads from that user on the page. How might we do this? We’ll take a stab at creating this feature by filtering via query strings.


Start By Running The Full Test Suite

First off, we will start off by running our full test suite. We want to make sure everything is still working and passing before moving forward.

vagrant@homestead:~/Code/forumio$ phpunit
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

EEEEEEEEEEEEEEEEEEEE                                              20 / 20 (100%)

Time: 965 ms, Memory: 10.00MB

There were 20 errors:

1) Tests\Feature\CreateThreadsTest::test_guest_can_not_create_threads
Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 1 no such table: channels (SQL: select * from "channels")

Oh wow. We have 100% of tests failing. Um, this is not good. Not good at all! What happened? Well the error does give us a clue. No such table channels. This is because when we were setting up the view composer from our last tutorial, the sql query runs even before the database migrations run – so we need to refactor just a bit. In AppServiceProvider.php change the code from this:

back to this:

We run our tests again, and 100% of the tests pass.

vagrant@homestead:~/Code/forumio$ phpunit
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

....................                                              20 / 20 (100%)

Time: 2.94 seconds, Memory: 12.00MB

OK (20 tests, 35 assertions)

Instead of using the share() technique, we go back to using composer() and this will allow fix the order of when the sql query runs, in turn fixing the tests.


Add A New Feature Test To The ReadThreadsTest Class

Let’s open up the ReadThreadsTest Class and add a new test to it. What do we want the test to do? Here is what the pseudo code might look like.

  • Given a user is signed in
  • That user creates a thread
  • A different user creates a thread
  • When the first user visits the threads page with his query string filter
  • Then the first user will see his threads
  • Then the first user will not see other user’s threads

Let’s put that into test code here:

The next step as usual is to run that test to see what the error it produces is.

vagrant@homestead:~/Code/forumio$ phpunit --filter test_a_user_can_filter_by_any_username
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 812 ms, Memory: 10.00MB

There was 1 failure:

1) Tests\Feature\ReadThreadsTest::test_a_user_can_filter_by_any_username
Failed asserting that (the html) does not contain "Quia sunt tempore nostrum qui.".

/home/vagrant/Code/forumio/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:262
/home/vagrant/Code/forumio/tests/Feature/ReadThreadsTest.php:60

FAILURES!
Tests: 1, Assertions: 2, Failures: 1.

So, we know that the index() method of the ThreadsController is the method which is responsible for displaying threads. So we are going to need to work on that method to fix some things up. Here is the current code located at ThreadsController@index:

At this time, the code does not offer a means of determining *who* is making the request to see threads. Our goal is to create some logic where if a user provides some type of filter by means of a query string, then only those particular threads should be displayed. Let’s set that up now.


How To Filter By Query String

A few things have now changed in the code below. In the first if and else blocks, we remove the call to get() on the query. Now, we are simply building up the query, but not actually triggering it yet. The reason for this, is because now we want to add another conditional scenario. That scenario is, what if a query string is provided in the URL field? Well, that is exactly what we set up in the next if block. That if statement says, if you see something like this in the query http://forum.io/threads?by=SomeUserName, then we are going to trigger a query using a where clause where the ‘name’ field in the database is equal to SomeUserName.

We have a dummy user named asdf set up in our database, so let’s load up this URL http://forum.io/threads?by=asdf and see what happens now.
filter by query string

Fantastic! It is working. What’s nice about this query string approach, is that we didn’t even have to modify the routes file. We simply check for the presence of a particular key in the URL using the request() function. So now we have three different options for the query in our index() method. We can query by channel, query everything, or query by username in a query string. Pretty cool. Just to be sure let’s run our test once more, it should work now.

vagrant@homestead:~/Code/forumio$ phpunit --filter test_a_user_can_filter_by_any_username
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 1.44 seconds, Memory: 8.00MB

OK (1 test, 2 assertions)

Adding A Link For Filtering Authenticated User’s Threads

If we add a link now to one of our view files for filtering of the authenticated user threads, we know it will work now. Let’s go ahead and open up app.blade.php and make a few adjustments. Here we re arrange some of the links in the navbar menu and also add a link for filtering by the authenticated user’s threads.

how to create link for query string in url


Start and Finish with the Full Suite of Tests

We began this tutorial by running our full suite of tests, and it’s a good thing we did because we found a doozy we had to fix. At this point, we have added a feature, created a test for that feature, and tested it in isolation from all of our other tests. We need to run all tests once more to make sure that everything works correctly.

vagrant@homestead:~/Code/forumio$ phpunit
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

........FFFE.........                                             21 / 21 (100%)

Time: 3.43 seconds, Memory: 22.00MB

There was 1 error:

1) Tests\Feature\ReadThreadsTest::test_a_user_can_filter_threads_according_to_channel
ErrorException: Trying to get property of non-object (View: /home/vagrant/Code/forumio/resources/vie                                                                                                               ws/layouts/app.blade.php) (View: /home/vagrant/Code/forumio/resources/views/layouts/app.blade.php)

There were 3 failures:

1) Tests\Feature\ReadThreadsTest::test_a_user_can_browse_threads
2) Tests\Feature\ReadThreadsTest::test_a_user_can_read_a_single_thread
3) Tests\Feature\ReadThreadsTest::test_a_user_can_see_replies_that_are_associated_with_a_thread

Hmmm. 1 error and 3 failures. The error message above is stripped down for brevity, but we need to fix these problems. We can tackle these one at a time. First let’s run the first test that we notice failed.

vagrant@homestead:~/Code/forumio$ phpunit --filter test_a_user_can_browse_threads
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 1.24 seconds, Memory: 14.00MB

There was 1 failure:

1) Tests\Feature\ReadThreadsTest::test_a_user_can_browse_threads
"ErrorException thrown with message "Trying to get property of non-object (View: /home/vagrant/Code/forumio/resources/views/layouts/app.blade.php) (View: /home/vagrant/Code/forumio/resources/views/layouts/app.blade.php)"\n

Failed asserting that (the html) ' contains "Odit ea libero sequi qui quis ut.".

Looks like we are throwing an error in the app.blade.php file where we are trying to get a property of a non object. This actually makes sense, because when we put the new link into the navbar, we kind of just assumed that there would be a logged in user to view that link. What about if there is not a logged in user? We need to account for that scenario as well. Let’s once again visit the navbar code and update it. We only want to display that filter by query string link if there is actually a logged in user.

We can now run the test again and see how it works out.

vagrant@homestead:~/Code/forumio$ phpunit --filter test_a_user_can_browse_threads
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 1.11 seconds, Memory: 8.00MB

OK (1 test, 2 assertions)

That looks great. Just for grins, let’s run the whole suite and see if that one change fixed the other failing tests as well.

vagrant@homestead:~/Code/forumio$ phpunit
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

.....................                                             21 / 21 (100%)

Time: 2.69 seconds, Memory: 12.00MB

OK (21 tests, 37 assertions)

Alright! It looks like just fixing that one test in turn fixed all the problems we had.


How To Filter By Query Strings Summary

We’ve successfully added yet another feature to our expanding sample application. Hopefully you enjoyed learning all about creating query strings in the url to get specific sets of data from the database.