PHP 5 - Laraval Basics

By Sheldon L Published at 2020-07-02 Updated at 2020-07-02


Get Started

php -v
composer -v

composer global require laravel/installer
# export to PATH

laravel

cd <ProjectParent>
laravel new <Project>

cd <Project>
php artisan -version  # PHP CLI

# git ...

MVC

Create a View and a Controller

Rout::get('/user', 'UserController@index');
# `/user` is a route
# `UserController` is a controller
# `index` is a function
php artisan make:controller UserController
# `UserController` is created under `/app/Http/`
class UserController extends Controller
{
  public function index()
  {
    return view('home');
  }
}
Welcome

Models with Relationship

php artisan make:model ModelName -mcr
# -m: migration
# -c: controller
# -r: resource (functions like create(), update()...)

Models and Database

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=test
DB_USERNAME=username
DB_PASSWORD=password
php artisan serve
php artisan migrate
# `/app/Http/Controllers/UserController.php`

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;

class UserController extends Controller
{
  public function index()
  {
    # insert
    DB::insert(
      'INSERT INTO users (name, email, password) VALUES (?, ?, ?)',
      ['sarthak', 'sarthak@bitfumes.com', 'password']
    );
    # select
    $users = DB::select( 'SELECT * FROM users' );
    return $users;

    # update
    DB::update( 'UPDATE users SET name=? WHERE id=1', ['bitfumes']);
    $user = DB::select( 'SELECT * FROM users WHERE id=1' );
    return $user;

    # delete
    DB::delete( 'DELETE * FROM users WHERE id=3' );
    $users = DB::select( 'SELECT * FROM users' );
    return $users;
  }
}

Eloquent ORM

# `/app/Http/Controllers/UserController.php`

use App\Http\Controllers\Controller;
use App\User;

class UserController extends Controller
{
  public function index()
  {
    # insert
    // $user = new User();
    // dd($user); # similar as var_dump, but much more beautiful
    // $user->name = 'sheldon';
    // $user->email = 'sheldon@bitfumes.com';
    // $user->password = bcrypt('password');
    // $user->save();
    # or
    $data = [
      'name' => 'atom',
      'email' => 'atom@lizi.in',
      'password' => bcrypt('password'),
    ];
    User::create($data);

    # delete
    // User::where('id', 4)->delete();

    # update
    // User::where('id', 6)->update(['name' => 'bit']);

    # select
    $users = User::all();

    return $users;
  }
}

>>> User::create['name' => 'atom', 'email' => 'atom@lizi.in', 'password' => bcrypt('password'),]

>>> User::where('id', 4)->delete()

>>> User::where('id', 6)->update(['name' => 'bit'])

>>> User::find(1)->posts()

>>> Post::find(1)->user()

Accessor & Mutators

public function index()
{
  # ... keep the same

  # mutator
  public function setPasswordAttribute($password)
  {
    $this->attributes['password'] = bcrypt('password');
  }

  # accessor
  public function getNameAttribute($name)
  {
    return ucfirst($name);
  }
}

class UserController extends Controller
{
  public function index()
  {
    $data = [
      'name' => 'atom',          # the display will be modified by accessor
      'email' => 'atom@lizi.in',
      'password' => 'password',  # no need bcrypt() for mutator is set
    ];
    User::create($data);
    $users = User::all();

    return $users;
  }
}

User Authentication

composer require laravel/ui
php artisan ui:auth
# it will overwrite `/resources/views/home.blade.php`
# and create new Controller `/app/Http/Controllers/Auth`
# and `/app/Http/Controllers/HomeController.php`
# open 127.0.0.1:8000, login and register are available
# you can login with a user in users table

php artisan ui bootstrap
npm install && npm run dev
# beatify the frontend
# `/public/js` and `public/css`

Config

Upload a File

CSRF Token

<div class="card-body">
    <form action="/upload" method="post">
        @csrf
        <input type="file" name="image" id="">
        <input type="submit" name="upload" value="Upload">
    </form>
</div>

Route and Controller

// Route::post('/upload', function (Request $request) {
    // dd($request->all());         # test request
    // dd($request->file('image')); # test file object named `image`
    // dd($request->image);         # the same as above
    // dd($request->hasFile('image')); # test the `image` is chosen or not

    // $request->image->store('image');
    # default path: /storage/app/`images`/<random_name>.<ext> # see config.filesystem.disk.local

    // $request->image->store('image', 'public');
    # see config.filesystem.disk.public

//     return ('uploaded');

// });

# Better to write function in the controller:
Route::post('/upload', 'UserController@upload');
use Illuminate\Http\UploadedFile; # find this file and find the function needed

public function upload(Request $request) {

    if ($request->hasFile('image')) {
        // dd($request->image);  # the object name will appear at the top, and `use` it
        $fileName = $request->image->getClientOriginalName();
        $request->image->storeAs('images', $fileName, 'public');
    }
    return redirect()->back();
}
php artisan storage:link # link `/storage/app/public` to `/public/storage`

Upload an Avatar

# modify in `xxx_create_users_table.php`

Schema::create('users', function (Blueprint $table) {
    # <...> keep the same

    # add a new field
    $table->string('avatar')->nullable();;
});
# modify 'User.php`

protected $fillable = [
    'name', 'email', 'password', 'avatar' # add 'avatar' here
];
php artisan migrate:refresh  # DANGER: will reset all data values
Route::post('/upload', 'UserController@uploadAvatar');
# `UserController`

public function uploadAvatar(Request $request) {
    if ($request->hasFile('image')) {
        $this->deleteOldAvatar();
        $fileName = $request->image->getClientOriginalName();
        $request->image->storeAs('avatar', $fileName, 'public');
        auth()->user()->update(['avatar' => $fileName]);
    }
    return redirect()->back();

}

protected function deleteOldAvatar() {
    if (auth()->user()->avatar) {
        // dd('/public/avatar/' . auth()->user()->avatar);              # test path
        Storage::delete('/public/avatar/' . auth()->user()->avatar);    # means /storage/app`/public/avatar/`
    }
}
# modify `app.blade.php`

<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
  
  @if (Auth::user()->avatar)
    <img src=" " alt="avatar" width="40px">
  @endif
  <span class="caret"></span>
</a>
# `User`
public static function uploadAvatar($image) {

    (new self())->deleteOldAvatar();

    $fileName = $image->getClientOriginalName();
    $image->storeAs('avatar', $fileName, 'public');
    auth()->user()->update(['avatar' => $fileName]);
}

protected function deleteOldAvatar() {
    if ($this->avatar) {
        Storage::delete('/public/avatar/' . $this->avatar);
    }
}

# `UserController
public function uploadAvatar(Request $request) {
    if ($request->hasFile('image')) {
        User::uploadAvatar($request->image);
    }
    return redirect()->back();
}

Add Feedback Flash Messages

# `UserController`
public function uploadAvatar(Request $request) {
    if ($request->hasFile('image')) {
        User::uploadAvatar($request->image);

        # push session message
        // session()->put('message', 'Image uploaded successfully');

        # flash session only available for one request
        request()->session()->flash('message', 'Image uploaded successfully');
        return redirect()->back();
    }
    request()->session()->flash('error', 'Image not uploaded');
    return redirect()->back();
}

# `home`
@if (session()->has('message'))
    <div class="alert alert-success"></div>
@elseif (session()->has('error'))
    <div class="alert alert-danger"></div>
@endif
# `UserController`
public function uploadAvatar(Request $request) {
    if ($request->hasFile('image')) {
        User::uploadAvatar($request->image);
        return redirect()->back()->with('message', 'Image uploaded successfully');
    }
    return redirect()->back()->with('error', 'Image not uploaded');
}

# `layouts/flash`
@if (session()->has('message'))
    <div class="alert alert-success"></div>
@elseif (session()->has('error'))
    <div class="alert alert-danger"></div>
@endif

# `home`
@include ('layouts/flash')
php artisan make:component Alert
# `UserController`
# keep the same as above

# `app/views/components/Alert.php`
# keep as it is

# `resources/views/components/Alert.php`
<div>
    // display contents in <x-[component]> tag
  @if (session()->has('message'))
      <div class="alert alert-success"></div>
  @elseif (session()->has('error'))
      <div class="alert alert-danger"></div>
  @endif
</div>

# `home`
<x-alert>  // it's better than include because we can pass in more contents here through slot
  <p>Here is the respons from up load:</p>
</x-alert>