Tuesday, September 1, 2020

Laravel course materials


INTRODUCTION

- Introduction to Laravel.

- Course Outline.

- Familiarise with real world web development.

OOP & DESIGN PATTERNS IN PHP

- Basic Object Oriented Programming Concepts

- Why we need design patterns

- The SOLID design principles

- Creational Design Patterns

- Design patterns (Factory, Abstract Factory, Builder Prototype, Singleton, Prototype, Facades)


SETTING UP LARAVEL ENVIRONMENT

The "Conventional" Way   - WAMP/XAMPP

- Composer

- Apache

- MYSQL

- Redis

Using Docker (Bonus)

- DOCKER

- NGINX

- MYSQL

- PHP

- Redis

- LINUX

Introduction to Version Controlling System

- Git

- Github  Introduction to AWS

- Free tier account in AWS

- AWS Basics (Regions, Availability Zones, IAM, EC2, ELB)

- SSH into your own EC2 instance


UNDERSTANDING LARAVEL ARCHITECTURE CONCEPTS

- Request Lifecycle

- Service Container

- Service Providers

- Facades

- Contracts


SIMPLE TODO APP USING BLADE & BOOTSTRAP

- Database schema design

- Create database tables using migrations

- Configuring Models & Relations

- Web Routing

- Middleware

- Controller

- Authentication

- CRUD with Eloquents & Query Builder

- Views

- Frontend development with blade and JS/JQuery & bootstrap

- Notifications

- Settings


BUILDING AN INSTAGRAM CLONE PART 1 (SYSTEM ANALYSIS)

- Requirements assessment

- Capacity estimations

- Highlevel system & Database design

- Component Design

- Reliability & Consistency

- Performance Optimization Evaluation


BUILDING AN INSTAGRAM CLONE PART 2 (DATABASE AND MODEL CONFIGURATION)

- Schema Design

- Creating migrations using schema definition

- Create and setting up models with relations


BUILDING AN INSTAGRAM CLONE PART 2 (API DEVELOPMENT)

API development in Laravel  API Authentication

- OAuth

- Passsport

- Access Tokens  Basic API Stuffs

- Routing - API validations & Error Responses  Users API

- Sign Up

- Login

- Email Verification (with AWS SES)

- Password Reset (AWS SES)

- Follow/Unfollow user

- User Profile  Posts API

- Creating posts - Uploading Images (with AWS S3)

- Optimisation 1: Queue Post Creation (with AWS SQS)

- Fetching posts

- Optimisation 2: Paginate posts

- Rank posts

- Optimisation 3: Schedule post ranking algorithm

- Optimisation 4: Query Caching with Redis

- Post Details  Reactions API - Reaction CRUD

- Count Reactions/Post in post list api (Like/Comments)

- Load Reactions in Posts (Dashboard)

- Load paginated comments in post details


BUILDING AN INSTAGRAM CLONE PART 3 (FRONTEND DEVELOPMENT)

- Typescript Basics

- Single Page Application (SPA) vs Server Side Rendering (SSR)

- Setting up SSR with express and nodejs

- Authentication & cookie management

- Express Routing

- Setting up Vue CLI & Vuetify

- Setting up CSS preprocessor (SCSS)

- Configuring API client

- Posting and fetching data with api client

- Component Design

- Data management with VUEX

- Front end Development

- Sing Up/Login Page

- Dashboard with infinite scroll pagination

- Profile Page

- Notifications

- Inbox

- Testing (Unit, E2E)

- Bundling (Webpack) & Production Build

- Continuous integration with CIRCLE CI


DEPLOYMENT AND PERFORMANCE OPTIMISATION

- Deploying in EC2 with manual configuration

- Load Balancing with AWS ELB


CONCLUSION

- Real life software development scenario

- Practical scenario of Agile based development

- Software development etiquettes & manners


Wednesday, August 26, 2020

Laravel linux server setup process steps

 "nano /etc/ssh/sshd_config" and "PermitRootLogin yes" for PUTTY access


passwd ----for password change


sudo adduser USERNAME ---for adding new user

usermod -aG sudo USERNAME ---for permission new user


sudo a2ensite your_domain.conf

sudo a2dissite 000-default.conf




https://www.digitalocean.com/community/tutorials/how-to-install-the-apache-web-server-on-ubuntu-18-04

https://www.cloudbooklet.com/upgrade-php-version-to-php-7-4-on-ubuntu/


sudo apt update


sudo apt install curl wget php-cli php-zip php-mbstring git unzip php-xml php7.2-gd


sudo service apache2 restart



php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"


HASH="$(wget -q -O - https://composer.github.io/installer.sig)"


php -r "if (hash_file('SHA384', 'composer-setup.php') === '$HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"


sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer




sudo a2enmod rewrite


sudo chown -R www-data:www-data /var/www/html/sitedomain


sudo nano /etc/apache2/sites-available/000-default.conf 


then


DocumentRoot /var/www/html/sitedomain/public

ServerName sitedomain.com

CustomLog /var/log/apache2/sitedomain.com-access.log combined

ErrorLog /var/log/apache2/sitedomain.com-error.log

<Directory /var/www/html/sitedomain/public/>

Options +Indexes +Includes +FollowSymLinks +MultiViews

AllowOverride All

Require all granted

</Directory>


sudo service apache2 restart


https://docs.beyondco.de/laravel-websockets/1.0/basic-usage/starting.html#using-a-different-port


MAIL_HOST=smtp.sendgrid.net

MAIL_PORT=587

MAIL_USERNAME=apikey

MAIL_PASSWORD=pass

MAIL_ENCRYPTION=null


truncate -s0 error.log //for truncate any file

rm storage/logs/laravel-*.log //delete all log file


vim /etc/mysql/mysql.conf.d/mysqld.cnf

systemctl restart mysql.service



[program:websockets]

command=/usr/bin/php /var/www/html/sitedomain/artisan websockets:serve --port=3030

numprocs=1

autostart=true

autorestart=true

user=root

stdout_logfile=/var/www/html/sitedomain/websockets.log


[program:websockets]

command=/usr/bin/php /var/www/sitedomainlive/artisan websockets:serve --port=3030

numprocs=1

autostart=true

autorestart=true

user=root

stdout_logfile=/var/www/sitedomainlive/websockets.log




[program:laravel-worker]

process_name=%(program_name)s_%(process_num)02d

command=php /var/www/html/sitedomain/artisan queue:work --sleep=3 --tries=3

autostart=true

autorestart=true

user=root

numprocs=8

redirect_stderr=true

stdout_logfile=/var/www/html/sitedomain/worker.log

stopwaitsecs=3600



https://stillat.com/blog/2016/12/07/laravel-task-scheduling-running-the-task-scheduler


crontab -e //adding cron entry to cron tab

sudo service cron restart



[program:laravel_corn]

command=* * * * * php /var/www/html/sitedomain/artisan schedule:run >> /dev/null 2>&1

process_name=%(program_name)s_%(process_num)02d

numprocs=1

autostart=true

autorestart=true

startsecs=0

user=www-data

redirect_stderr=true

stderr_logfile = /var/www/html/sitedomain/laravel_corn_err.log

stdout_logfile = /var/www/html/sitedomain/laravel_corn_stdout.log

stdout_logfile_maxbytes=10MB

stdout_logfile_backups=10



sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start laravel-worker:*

sudo supervisorctl start websockets


sudo ufw allow 3030/tcp



nano /etc/php/7.2/apache2/php.ini


max_execution_time = 120

max_input_vars = 2500

memory_limit = 128M

post_max_size = 32M

upload_max_filesize = 24M

max_file_uploads = 100


sudo service apache2 restart


ab -k -n 500 -c 50 http://sitedomain.com/ //apache branch mark testing for 500 request and 50 concurent user


sudo chown -R $USER:www-data storage

sudo chown -R $USER:www-data bootstrap/cache

chmod -R 775 storage

chmod -R 775 bootstrap/cache

ps aux | egrep '(apache|httpd)'


MAIL_DRIVER=smtp

MAIL_HOST=smtp.sendgrid.net

MAIL_PORT=587

MAIL_USERNAME=apikey

MAIL_PASSWORD=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

MAIL_ENCRYPTION=null



Include /etc/letsencrypt/options-ssl-apache.conf


sudo chown -R $USER:www-data /etc/letsencrypt/live/sitedomain.com

chmod -R 775 /etc/letsencrypt/live/sitedomain.com


//for ssl 

LARAVEL_WEBSOCKETS_HOST=sitedomain.com

LARAVEL_WEBSOCKETS_SCHEME=https

LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT=/etc/letsencrypt/live/sitedomain.com/fullchain.pem

LARAVEL_WEBSOCKETS_SSL_LOCAL_PK=/etc/letsencrypt/live/sitedomain.com/privkey.pem

LARAVEL_WEBSOCKETS_ENCRYPTED=true

MIX_LARAVEL_WEBSOCKETS_ENCRYPTED="${LARAVEL_WEBSOCKETS_ENCRYPTED}"


//withour ssl

LARAVEL_WEBSOCKETS_HOST=

LARAVEL_WEBSOCKETS_SCHEME=

LARAVEL_WEBSOCKETS_SSL_LOCAL_CERT=

LARAVEL_WEBSOCKETS_SSL_LOCAL_PK=

LARAVEL_WEBSOCKETS_ENCRYPTED=false

MIX_LARAVEL_WEBSOCKETS_ENCRYPTED="${LARAVEL_WEBSOCKETS_ENCRYPTED}"





Tuesday, May 19, 2020

Laravel advanced filter way

Making the advanced query filter with Eloquent Filter in Laravel

Introduction

Have you ever experienced make an advanced search page in programming? if your answer is yes maybe you know this feature has many conditions to make a query database.Especially when you are using a relational DB as MySQL in your project at that time our task will getting hard. I was searching for it. Eventually, I found a clean way to implement this feature in the Laravel project.

What's the main problem?

The main problem is that you will make many conditions for every situation. Writing a lot of terms will surely reduce the readability of your code and increase the possibility of make a mistake.
Practical example:
Suppose we want to get the list of the users with the requested parameters as follows:
http://localhost:8000/users/search?age_more_than=25&gender=male&created_at=25-09-2019
The Request parameter will be as follows:
[ 
  'age_more_than' => '24',
  'gender' => 'male',
  'created_at' => '25-09-2019',
]
Implement this feature in UsersController.php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function index(Request $request)
{
$users = User::where('is_active', true);
if ($request->has('age_more_than')) {
$users->where('age', '>', $request->age_more_than);
}
if ($request->has('gender')) {
$users->where('gender', $request->gender);
}
if ($request->has('created_at')) {
$users->where('created_at','>=', $request->created_at);
}
return $users->get();
}
}
We check out a condition for each request.
In the future, if your project will need more filter requests at that time you should add many conditions to the above code. Imagine some of the queries may be advanced therefore your code to be like Monster!

Discover away

Everything began from just a tutorial video called Eloquent Techniques in laracast. It was about a new way to make an advanced filter by use of the query string. It has to separate layer filters from controller and model. It made an Eloquent query by the use of a query string. Advanced Eloquent rescued the readability of your code by a filter class. It was very good but you had to make a method for every condition. It's boring for a creative developer. You don't have a dynamic query and you have to write many methods for per condition just in a separate layer.

Eloquent Filter is your solution

Imagine you will install a package composer and make a query by query string without write where for every condition. Actually you just enter query string according to the principles of that package. Therefore the package will make every condition by the query string. If you want to write a custom query in the separated layer you can do it. You can set fields of your model to allow build queries by the query string. Note that the query string must be sync with the fields of your Model. Isn't great in your opinion !?. This package saves your time and your code. Fortunately like package eloquent-filter is rare in GitHub.

Installation

Run the Composer command
$ composer require mehdi-fathi/eloquent-filter

Basic Usage

Add Filterable trait to your models and set fields that you will want a filter in whitelist. You can override this method in your models.
namespace Tests\Models;
use eloquentFilter\QueryFilter\ModelFilters\Filterable;
use Illuminate\Database\Eloquent\Model;
/**
* Class User.
*/
class User extends Model
{
use Filterable;
/**
* @var array
*/
private static $whiteListFilter = [
'id',
'username',
'family',
'email',
'count_posts',
'created_at',
'updated_at',
];
/**
* @var string
*/
protected $table = 'users';
/**
* @var array
*/
protected $guarded = [];
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function posts()
{
return $this->hasMany('Tests\Models\Post');
}
}
view rawUser.php hosted with ❤ by GitHub
You can set * char for filter in all fields as like below example:
private static $whiteListFilter = ['*'];

Use in Controller

namespace App\Http\Controllers;
use eloquentFilter\QueryFilter\ModelFilters\ModelFilters;
/**
* Class UsersController.
*/
class UsersController
{
/**
* @param \eloquentFilter\QueryFilter\ModelFilters\ModelFilters $modelFilters
*/
public function list(ModelFilters $modelFilters)
{
if (!empty($modelFilters->filters())) {
$perpage = Request::input('perpage');
Request::offsetUnset('perpage');
$users = User::filter($modelFilters)->with('posts')->orderByDesc('id')->paginate($perpage,['*'],'page');
} else {
$users = User::with('posts')->orderByDesc('id')->paginate(10);
}
}
}
Done it!

Simple Example

You just pass the data blade form to query string or generate a query string in the controller method. For example:

Simple Where

/users/list?email=mehdifathi.developer@gmail.com
SELECT ... WHERE ... email = 'mehdifathi.developer@gmail.com'

/users/list?first_name=mehdi&last_name=fathi
SELECT ... WHERE ... first_name = 'mehdi' AND last_name = 'fathi'

/users/list?username[]=ali&username[]=ali22&family=ahmadi
SELECT ... WHERE ... username = 'ali' OR username = 'ali22' AND family = 'ahmadi'

Where by operator

You can set any operator MySQL in the query string.
/users/list?count_posts[operator]=>&count_posts[value]=35
SELECT ... WHERE ... count_posts > 35

/users/list?username[operator]=!=&username[value]=ali
SELECT ... WHERE ... username != 'ali'

/users/list?count_posts[operator]=<&count_posts[value]=25
SELECT ... WHERE ... count_posts < 25

Special Parameters

You can set special parameters limit and orderBy in query string for make query by that.
/users/list?f_params[limit]=1
SELECT ... WHERE ... order by `id` desc limit 1 offset 0

/users/list?f_params[orderBy][field]=id&f_params[orderBy][type]=ASC
SELECT ... WHERE ... order by `id` ASC limit 10 offset 0

Where between

If you are going to make a query whereBetween. You must fill the keys start and end in the query string. you can set it on query string as you know.
/users/list?created_at[start]=2016/05/01&created_at[end]=2017/10/01
SELECT ... WHERE ... created_at BETWEEN '2016/05/01' AND '2017/10/01'

Advanced Where

/users/list?count_posts[operator]=>&count_posts[value]=10&username[]=ali&username[]=mehdi&family=ahmadi&created_at[start]=2016/05/01&created_at[end]=2020/10/01
&f_params[orderBy][field]=id&f_params[orderBy][type]=ASC

select * from `users` where `count_posts` > 10 and `username` in ('ali', 'mehdi') and 
`family` = ahmadi and `created_at` between '2016/05/01' and '2020/10/01' order by 'id' asc limit 10 offset 0
Just note that fields of query string be the same rows table database in $whiteListFilter in your model or declare the method in your model as the override method. The overriding method can be considered custom query filter.

Custom query filter

If you are going to make yourself a query filter you can do it easily. You just make a trait and use it on model:
use Illuminate\Database\Eloquent\Builder;
/**
* Trait usersFilter.
*/
trait usersFilter
{
/**
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param $value
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function username_like(Builder $builder, $value)
{
return $builder->where('username', 'like', '%'.$value.'%');
}
}
Note that fields of query string be the same methods of a trait. Use the trait in your model:
/users/list?username_like=a

select * from `users` where `username` like %a% order by `id` desc limit 10 offset 0
You can make every filter with eloquent-filter.
For more details check out GitHub repository. If you think the eloquent-filter is useful so give a ⭐️ to that repository in Github
Good luck and thank you for sharing your valuable time with me. I hope the Eloquent Filter is useful for your code. If you have any idea or opinion I glade to know it.