Add the url parameters for Laravel search results pagination

Issue: If you paginate your search result, when clicking on the 2 page, or any other nth page of your pagination link, it will return an url with the page parameter but without your search parameter. This cause your filtering to be lost.

Solution:

Make sure to return your parameter variable from the controller function as you will need to call it on your blade view.

return view('my_view',compact( 'queryResult','my_variable'));

In your view:

@foreach($queryResult   as $stuff)
     {{$stuff->stuff_name}}
 @endforeach
{{$ queryResult ->appends(['search_variable=>$my_variable])->links('vendor.pagination.materializecss')}}

if you have several URL parameters you can align the ->appends() one after the other. Don’t forget to ad the varaible to the view in the controller.

Passing variables to Laravel parameter grouping function

Issue: A statement such as

$nb_votes = $request->input('nb_votes');
DB::table('users')
            ->where('name', '=', 'John')
            ->where(function ($query) {
                $query->where('votes', '>', $nb_votes)
                      ->orWhere('title', '=', 'Admin');
            })
            ->get();

will return an error:

Unknown variable $nb_votes 

The issue is due to the fact that $nb_votes in the anonymous function refers to the local scope, while the variable we want to use has been defined outisde of the function. We need to pass the variable to the anonymous function.

Solution: To pass a variable to an anonymous function you can do as follow:

$nb_votes = $request->input('nb_votes');
DB::table('users')
            ->where('name', '=', 'John')
            ->where(function ($query) use ( $nb_votes ) {
                $query->where('votes', '>', $nb_votes)
                      ->orWhere('title', '=', 'Admin');
            })
            ->get();

https://www.php.net/manual/en/functions.anonymous.php

see last example in example #3

For laravel queries documentation:

https://laravel.com/docs/5.8/queries#parameter-grouping

Login with Facebook in Laravel 5.8

To add social media login functionality to Laravel 5.8, one library come over and over again, it’s socialite.

https://github.com/laravel/socialite

SSH into your server and run the following command in the directory where your Laravel is installed:

composer require laravel/socialite

As composer is locked after install. I needed to reinstall completely. On my host, the installation needs to be global for it to work (or at least, a local install did not do the trick). So I ran

composer global remove laravel/installer
composer global require laravel/installer laravel/socialite
cd Path/to/my/directory
laravel new ProjectName --auth

without global, laravel was an unknown command.

Official documentation can be found on the Laravel website:

https://laravel.com/docs/6.x/socialite

Additional resources:

https://medium.com/@confidenceiyke/laravel-5-8-facebook-socialite-authentication-8863b9a43f11

https://getcomposer.org/doc/01-basic-usage.md

https://getcomposer.org/doc/03-cli.md

https://getcomposer.org/doc/01-basic-usage.md

Add google Recaptcha control on login form in Laravel

To implement Google Recaptcha in Laravel check our article on implementing Google Recaptcha for Laravel registration.

in /app/Http/Controllers/Auth/LoginController.php

Add the following lines:

use Illuminate\Http\Request;
use App\Rules\GoogleRecaptcha;

And before theclosing curly brackets:

/** 
* Validate the user login request. 
* 
* @param  \Illuminate\Http\Request  $request 
* @return void 
*/ 
protected function validateLogin(Request $request) 
{ 
    $this->validate($request, [ 
    $this->username() => 'required|string', 
    'password' => 'required|string', 
    'g-recaptcha-response' => ['required', new GoogleRecaptcha], 
    ]); 
}

Login with user name instead of email in Laravel

Default laravel login is set to work with email and password but there might be some instance where login with an email address is not desirable and you might want to change this to login with a username.

The advantage of logging in with an email address is that you can be sure it will be unique. The drawback is that it is a bit long to type and some people are not comfortable giving their email address, so depending on your type of application, where having the email address is not essential, it makes sense to offer to login with a username instead.

In Laravel 5.8

Add the following function in app/Http/Controllers/Auth/LoginController.php

/**
*Use username instead of default (email address)
*for authentication
**/
public function username(){
    return ('name');
}

in the return(‘name’) statement, ‘name’ stand for the column name in your user table in your database you want to use. In my case the column is ‘name’.

in resources/views/auth/login.blade.php change the email login field with a username field as follow:

<div class="form-group row">
    <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label>
    <div class="col-md-6">
       <input id="name" type="text" class="form-control" name="name" required>
  </div>
</div>

As you are now using the username instead of the email for logging in, you need to make sure the username is the unique. To do that you will need to modify your migrations file for create_users_table.php

table->string('name')->unique(); 

And you are all set.

Adding Recaptcha to registration page on Laravel framework

In the app folder, create a Rules folder. Save the following code as GoogleRecaptcha.php:

<?php
namespace App\Rules;
use GuzzleHttp\Client;
use Illuminate\Contracts\Validation\Rule;
class GoogleRecaptcha implements Rule
{

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        $url='https://www.google.com/recaptcha/api/siteverify';
	$data = array(
       		'secret' => env('GOOGLE_RECAPTCHA_SECRET'),
		'response' => @$_POST['g-recaptcha-response']
        );
	$ch = curl_init($url);	
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch , CURLOPT_POSTFIELDS, http_build_query($data));
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	$json = curl_exec($ch);
	curl_close($ch);
	$response = json_decode($json,true);
	var_dump($response);
	if ($response['success'] != false) {
		return 'success';}
	else{return false;}
	#$response= $obj ->{"success"};
	#var_dump($response[0]);
        #$response = $client->post('https://www.google.com/recaptcha/api/siteverify',
         #   [
          #      'form_params' => [
           #         'secret' => env('RECAPTCHA_SECRET_KEY', false),
            #        'remoteip' => request()->getClientIp(),
             #       'response' => $value
              #  ]
            #]
        #);
        #$body = json_decode((string)$response->getBody());
        #return $body->success;
    }
    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'Are you a robot?';
    }
}

In app/Http/Controllers/Auth/RegisterController.php

use App\Rules\GoogleRecaptcha;
/**
 * Get a validator for an incoming registration request.
 *
 * @param  array  $data
 * @return \Illuminate\Contracts\Validation\Validator
 */
protected function validator(array $data)
{
    return Validator::make($data, [
        'name' => 'required|string|max:255',
        'email' => 'required|string|email|max:255|unique:users',
        'password' => 'required|string|min:6|confirmed',
        'g-recaptcha-response' => ['required', new GoogleRecaptcha]
    ]);
}

Original code was with guzzle but it leads to the following issue:

Issue: “cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)”

https://stackoverflow.com/questions/42094842/curl-error-60-ssl-certificate-in-laravel-5-4

in resources/views/auth/register.blade.php

Add in the registration form:

                      @if(env('GOOGLE_RECAPTCHA_KEY'))
                        <div class="form-group row">
                             <div class="g-recaptcha offset-md-4 col-md-6"
                                  data-sitekey="{{env('GOOGLE_RECAPTCHA_KEY')}}">
                             </div>
                         </div>
                       @endif

in the views/layouts/app.blade.php or in the register.blade.php files add the following line:

<script src="https://www.google.com/recaptcha/api.js" async defer></script>

In .env

GOOGLE_RECAPTCHA_KEY=site_key
GOOGLE_RECAPTCHA_SECRET=site_secret

to avoid issue with guzzle, let’s consider making the curl REST API call manually: https://weichie.com/blog/curl-api-calls-with-php/

$jsonurl =""
$curl_handle=curl_init();

The CURL manual call worked perfectly

Custom blade directive @isAdmin in Laravel 5.3+

  1. Create a is_admin column in your user database, only admin can register a user. Allow admin to register user as admin or not.
  2. Open user.php in the app folder and add use Illuminate\Support\Facades\Auth;
  3. Add the following function to the user class:
public function isAdmin()
{
    if (Auth::user() &&  Auth::user()->is_admin == 1) {
        return true;
    }
}

From there we can already check if user is admin in our view like this:

@if(Auth::user()->isAdmin())
    Something that should only be visible to admin
@endif

4. We would like to keep our code elegant so let’s add a custom directive to blade. Open AppServiceProviders.php and add the following code in the boot function:

namespace App\Providers;
 use Illuminate\Support\ServiceProvider;
 use Illuminate\Support\Facades\Schema;
 use Illuminate\Support\Facades\Blade;
 use Illuminate\Support\Facades\Auth;
 class AppServiceProvider extends ServiceProvider
 {
     /**
      * Register any application services.
      *
      * @return void
      */
     public function register()
     {
         Blade::if('isAdmin', function(){
             if(Auth::check())
                 return Auth::user()->is_admin===1?true:false;
             else return false;
         });
     }
 /**  * Bootstrap any application services.  *  
* @return void  */ 
public function boot() {
     Schema::defaultStringLength(191);
    // Blade custom directives for isAdmin
     Blade::directive('isAdmin', function() {
         return "<?php if(Auth::user()->isAdmin()): ?>";
     });
     Blade::directive('endisAdmin', function() {
             return "<?php endif; ?>";
     }); }
 }

From there you should be all set to use @isAdmin @endisAdmin in your blade view files.

In case it doesn’t work, make sure to test that @if(Auth::user()->isAdmin()) is working properly and revert back to your custom directive.

Admin only register page in Laravel 5.2

All credits go to : https://stackoverflow.com/questions/36250746/how-to-protect-register-with-auth-midleware-in-laravel-5-2

Solution #1 (any authenticated user)

On file /app/Http/Controllers/Auth/RegisterController.php

simply change from

public function __construct()
{
    $this->middleware('guest');
}

to

public function __construct()
{
    $this->middleware('auth');
}

Solution #2 (only authenticated admin user) a) run

php artisan make:middleware IsAdmin

b) Add to the routeMiddleware array in your kernel file by opening app/Http/Kernel.php:

'admin' => \App\Http\Middleware\IsAdmin::class,

c) edit isAdmin file

public function handle($request, Closure $next)
{
     if (Auth::user() &&  Auth::user()->is_admin == 1) {
            return $next($request);
     }

    return redirect('/');
}

d) On file /app/Http/Controllers/Auth/RegisterController.php, change the constructor from

public function __construct()
{
    $this->middleware('guest');
}

to

public function __construct()
{
    $this->middleware('admin');
}

e) Update user migration to include a boolean field

Schema::create('users', function (Blueprint $table) {
    $table->mediumIncrements('id');
    $table->string('name');
    $table->string('email')->unique();
    $table->string('password');
    $table->boolean('is_admin')->default(false);
    $table->rememberToken();
    $table->timestamps();
});

f) Update User model to allow ‘is_admin’ field

protected $fillable = [
    'name', 'email', 'password', 'is_admin'
];