0
\$\begingroup\$

I am using this code on my own personal website (my personal administration site) so it doesn't need any security and so on. I am not into learning everything about that yet, and although I do know a lot about it already, it is not the case for this code.

My order/sort links are looking like this:

{{ URL::route('events.order', array('order' => 'name', 'by' => $sort, 'search' => $search )) }}

To make sure that the order by and the search is always included in the URL. The actual controller is looking like below:

public function index($order = 'date', $by = 'desc')
{
    if ($by == 'asc') $sort = "desc"; else $sort = "asc";

    $searchString   = Input::get('search');
    $searchString   = strtolower($searchString);

    $searchResult   = Events::orderBy($order, $by)->where(function ($query) use ($searchString)
    {
        $query->where('name', 'LIKE', '%'. $searchString .'%')
        ->orWhere('date', 'LIKE', '%'. $searchString .'%')->get();
    })->Paginate(Auth::user()->events);

    if($searchString)
    {
        $search = str_getcsv($searchString, ' ');

        if (count($search) == '1' && (strpos($searchString,'january') !== false || strpos($searchString,'february') !== false || strpos($searchString,'march') !== false || strpos($searchString,'april') !== false || strpos($searchString,'may') !== false || strpos($searchString,'june') !== false || strpos($searchString,'july') !== false || strpos($searchString,'august') !== false || strpos($searchString,'september') !== false || strpos($searchString,'october') !== false || strpos($searchString,'november') !== false || strpos($searchString,'december') !== false))
        {
            $monthNumber    = date('m', strtotime($searchString));
            $searchResult   = Events::orderBy($order, $by)->where('date', 'LIKE', '%2015-' . $monthNumber . '%')->Paginate(Auth::user()->events);
        }

        if (count($search) == '2' && (strpos($searchString,'january') !== false || strpos($searchString,'february') !== false || strpos($searchString,'march') !== false || strpos($searchString,'april') !== false || strpos($searchString,'may') !== false || strpos($searchString,'june') !== false || strpos($searchString,'july') !== false || strpos($searchString,'august') !== false || strpos($searchString,'september') !== false || strpos($searchString,'october') !== false || strpos($searchString,'november') !== false || strpos($searchString,'december') !== false))
        {
            $searchDay  = current(explode(' ', $searchString));
            $dayNumber  = str_pad($searchDay, 2, '0', STR_PAD_LEFT);

            $searchMonth    = explode(' ', $searchString);
            $month      = $searchMonth[1];
            $monthNumber    = date('m', strtotime($month));

            $searchResult   = Events::orderBy($order, $by)->where('date', 'LIKE', '%2015-' . $monthNumber . '-' . $dayNumber . '%')->Paginate(Auth::user()->events);
        }
    }
        return View::make('events.index')
        ->with('events', $searchResult)
        ->with('sort', $sort)
        ->with('search', $searchString);
}

My main thing what I like reviewed is the search function. What it does is, it searches for the text in both the "name" and "date" fields. The "name" field contains the short description of the event, and the "date" field is formatted like "Y-m-d". I want to be able to search for anything that is submitted, which the following piece of code does for me:

    $searchResult   = Events::orderBy($order, $by)->where(function ($query) use ($searchString)
    {
        $query->where('name', 'LIKE', '%'. $searchString .'%')
        ->orWhere('date', 'LIKE', '%'. $searchString .'%')->get();
    })->Paginate(Auth::user()->events);

Now for the tricky part that I actually need some help with, because I think it can be done much better. I want to also be able to search for a month, like "august". When I search for "auguest", I need all events from august to be displayed. Same goes for every month:

        if (count($search) == '1' && (strpos($searchString,'january') !== false || strpos($searchString,'february') !== false || strpos($searchString,'march') !== false || strpos($searchString,'april') !== false || strpos($searchString,'may') !== false || strpos($searchString,'june') !== false || strpos($searchString,'july') !== false || strpos($searchString,'august') !== false || strpos($searchString,'september') !== false || strpos($searchString,'october') !== false || strpos($searchString,'november') !== false || strpos($searchString,'december') !== false))
        {
            $monthNumber    = date('m', strtotime($searchString));
            $searchResult       = Events::orderBy($order, $by)->where('date', 'LIKE', '%2015-' . $monthNumber . '%')->Paginate(Auth::user()->events);
        }

What this basically does is, check how many strings are being searched for by counting them. Then, it checks if that string is a month (january, february, and so on). Once the search consists of 1 string and it is a month, it will convert the month into the corresponding number format for that date, and it will grab all events for that month and return them.

Same goes for searching for a specific day in a month. For example "4 august" should display all events that occur on the 4th of august, which is the following snippet:

        if (count($search) == '2' && (strpos($searchString,'january') !== false || strpos($searchString,'february') !== false || strpos($searchString,'march') !== false || strpos($searchString,'april') !== false || strpos($searchString,'may') !== false || strpos($searchString,'june') !== false || strpos($searchString,'july') !== false || strpos($searchString,'august') !== false || strpos($searchString,'september') !== false || strpos($searchString,'october') !== false || strpos($searchString,'november') !== false || strpos($searchString,'december') !== false))
        {
            $searchDay  = current(explode(' ', $searchString));
            $dayNumber  = str_pad($searchDay, 2, '0', STR_PAD_LEFT);

            $searchMonth    = explode(' ', $searchString);
            $month      = $searchMonth[1];
            $monthNumber    = date('m', strtotime($month));

            $searchResult       = Events::orderBy($order, $by)->where('date', 'LIKE', '%2015-' . $monthNumber . '-' . $dayNumber . '%')->Paginate(Auth::user()->events);
        }

It checks if the search consists of 2 strings (day and month) and if so, it checks if the second string is a month. Also, it adds a leading zero to the number since in my database it is stored as Y-m-d which means the 4th of august looks like 2015-08-04.

I know I can do it the amateur way for example, and have an extra field in my database which stores the actual date in like "august", "november", and so on, and simply make a query that grabs all events corresponding to the name. I can also change the code to grab events that occur between two dates. For example, all january dates, it should be looking for all events that occur between the 1st of january and the 31st of january. But I chose to do it this way.

What I am looking for is basically a review of my code, and I would like to get some pointers on what to improve. I have no clue if I should be putting some of these things in a model as a function for example. I have no idea if I can write my code better or cleaner, or shorter.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

You shouldn't use LIKE: it doesn't use indexes, if the pattern starts with %.

$query = "MATCH (name, description) AGAINST (?)";
$products = Product::whereRaw($query, [$search])->get();
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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