Showing posts with label laravel. Show all posts
Showing posts with label laravel. Show all posts

Oct 25, 2016

How to make controller inside a sub-directory in Laravel project

Assume we wanna create our API, so we create a namespace/sub-directory called API inside app/Http/Controllers (in order to distinguish with others sub-namespaces. The fact that, we can effectively put our controllers where ever we want, even not in Http directory).
For example:
php artisan make:controller API/AuthController
php artisan make:controller Admin/DashboardController
And then we define our routes like:
Route::group(['prefix' => 'api', 'namespace' => 'API'], function() {
    Route::post('login', 'AuthController@login');
});

Route::group(array('prefix' => 'adm', 'namespace' => 'AdminPanel'), function() {
    Route::get('/', 'DashboardController@index');
});
This is a simple way for us to have a nice Laravel structure.

Oct 13, 2016

Create PHP/Laravel authentication APIs with Firebase PHP-JWT

On all PHP/Laravel projects (SPA apps) I always use Firebase/PHP-JWT to create our authentication APIs for mobile apps or javascript apps.
Firstly, we include Firebase/PHP-JWT to our projects by adding & downloading dependencies:
composer require firebase/php-jwt
When user login via AJAX call, we need response to client a token (jwt).

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Validator;
use Config;
use Hash;
use Log;
use App\User;
use \Firebase\JWT\JWT;
use \Firebase\JWT\ExpiredException;

class AuthController extends Controller
{
    protected function jwt(User $user)
    {
        $payload = array(
            'sub'   => $user->id,
            'iat'   => time(),
            'exp'   => time() + 60*60
        );
        return JWT::encode($payload, Config::get('app.jwt-secret-key'));
    }

    public function login(Request $req)
    {
        $validator = Validator::make($req->all(), array(
            'email' => 'required|email|min:4|max:255',
            'password'  => 'required|min:8|max:80'
        ));

        if ($validator->fails()) {
            return response()->json(['error' => $validator->errors()], 400);
        }

        $user = User::where('email', '=', $req->input('email'))->first();

        if (!$user) {
            return response()->json(['error' => 'Your email not exists'], 401);
        }

        if (Hash::check($req->input('password'), $user->password)) {
            return response()->json(['jwt' => $this->jwt($user)], 200);
        } else {
            return response()->json(['error' => 'Wrong passwd'], 401);
        }
    }
}
Method jwt(User $user) return a string called token. Basically on authentication we create and store a token locally on client (browser, smart phone device). Then every time we make a call to the server, we check that token and ensure the user is who they say they are.

The routes:

Route::group(array('prefix' => 'api'), function() {
    Route::post('auth/register', 'AuthController@register');
    Route::post('auth/login', 'AuthController@login');
    Route::post('auth/user', 'AuthController@user'); // response returns logged user
});

Corresponding user() method:

    /**
     * return authenticated user
     * return NULL if not authenticated
    **/
    public function user(Request $req, $nullOnFail = false)
    {
        try {
            list($jwtType, $jwt) = explode(' ', $req->header('Authorization'));
        } catch(\ErrorException $e) {
            if ($nullOnFail)
                return null;
            return response()->json(['error' => 'Can not parse Authorization header'], 400);
        }
        if ($jwt) {
            try {
                $credentials = JWT::decode($jwt, Config::get('app.jwt-secret-key'), ['HS256']);
            } catch(ExpiredException $e) {
                if ($nullOnFail)
                    return $nullOnFail;
                return response()->json(['error' => 'jwt_expired'], 400);
            } catch(\Exception $e) {
                if ($nullOnFail)
                    return $nullOnFail;
                return response()->json(['error' => 'An error while decoding jwt'], 400);
            }

            $user = User::where('id', '=', get_object_vars($credentials)['sub'])->first();
            if ($nullOnFail)
                return $user;
            return response()->json(['user' => $user], 200);
        }
        return response()->json(['error' => 'No jwt attached'], 401);
    }

How to write an internet forum based on Laravel and AngularJs? (part 1)

Jul 22, 2016

How Laravel Blade @include .html files

We can include a .html file instead of .php file with Laravel 5 Blade.

By default Blade engine looks for .blade.php files, and then falls back to .php files. We can do what we want by telling Laravel's view system to also consider .html files by adding .html to the searched extensions by adding the following somewhere in our bootstrapping code:


View::addExtension('html', 'php');

In certain project, we add this to the base controller to apply globally.

class Controller extends BaseController
{
    use AuthorizesRequests, AuthorizesResources, DispatchesJobs, ValidatesRequests;

    function __construct() {
        // tells the view finder to look for `.html` files and run
        // them through the normal PHP `include` process
        View::addExtension('html', 'php');
    }
}

May 16, 2016

How to use Bower as frontend dependencies manager for web project based on Laravel 5.x?

1. Install bower globally
$ npm install -g bower
2. We need a bower.json file to get started. The following command will create a file called bower.json.
$ bower init
Or we can create manually in the root of your directory with the following content:
{
  "name": "your-project"
}
3. Add .bowerrc
By default Bower installs into /bower_components, but we want our dependencies in public directory. Create a file named .bowerrc in our root directory with following content:
{
  "directory": "public/bower"
} 
4. Install our front-end dependencies. For example:
$ bower install angular --save
$ bower install jquery --save
Some Related topics:
https://laracasts.com/discuss/channels/laravel/assets-not-accessible-laravel-51