PHP & Web Development Blogs

Search Results For: install
Showing 11 to 15 of 21 blog articles.
27388 views · 4 years ago
Introduction to Gitlab CI for PHP developers
As a developer, you've probably at least heard something about CI - Continuous integration. And if you haven't - you better fix it ASAP, because that's something awesome to have on your skill list and can get extremely helpful in your everyday work. This post will focus on CI for PHP devs, and specifically, on CI implementation from Gitlab. I will suppose you know the basics of Git, PHP, PHPUnit, Docker and unix shell. Intended audience - intermediate PHP devs.
Adding something to your workflow must serve a purpose. In this case the goal is to automate routine tasks and achieve better quality control. Even a basic PHP project IMO needs the following:
* linter) checks (cannot merge changes that are invalid on the syntax level)
* Code style checks
* Unit and integration tests
All of those can be just run eventually, of course. But I prefer an automated CI approach even in my personal projects because it leads to a higher level of discipline, you simply can't avoid following a set of rules that you've developed. Also, it reduces a risk of releasing a bug or regression, thus improving quality.
Gitlab is as generous as giving you their CI for free, even for your private repos. At this point it is starting to look as advertising, therefore a quick comparison table for Gitlab, Github, Bitbucket. AFAIK, Github does not have a built-in solution, instead it is easily integrated with third parties, of which Travis CI seems to be the most popular - I will therefore mention Travis here.

Public repositories (OSS projects). All 3 providers have a free offer for the open-source community!


| Provider | Limits |
|---|---|
| Gitlab | 2,000 CI pipeline minutes per group per month, shared runners |
| Travis | Apparently unlimited |
| Bitbucket| 50 min/month, max 5 users, File storage <= 1Gb/month |

Private repositories


| Provider | Price | Limits |
|---|---|---|
| Gitlab | Free | 2,000 CI pipeline minutes per group per month, shared runners |
| Travis | $69/month | Unlimited builds, 1 job at a time |
| Bitbucket| Free | 50 min/month, max 5 users, File storage <= 1Gb/month |

Getting started

I made a small project based on Laravel framework and called it "ci-showcase". I work in Linux environment, and the commands I use in the examples, are for linux shell. They should be pretty much the same on Mac and nearly the same on Windows though.
composer create-project laravel/laravel ci-showcase

Next, I went to gitlab website and created a new public project: https://gitlab.com/crocodile2u/ci-showcase. Cloned the repo and copied all files and folders from the newly created project - the the new git repo. In the root folder, I placed a .gitignore file:
.idea
vendor
.env

Then the .env file:
APP_ENV=development

Then I generated the application encryption key: php artisan key:generate, and then I wanted to verify that the primary setup works as expected: ./vendor/bin/phpunit, which produced the output OK (2 tests, 2 assertions). Nice, time to commit this: git commit &amp;&amp; git push

At this point, we don't yet have any CI, let's do something about it!

Adding .gitlab-ci.yml

Everyone going to implement CI with Gitlab, is strongly encouraged to bookmark this page: https://docs.gitlab.com/ee/ci/README.html. I will simply provide a short introduction course here plus a bit of boilerplate code to get you started easier.
First QA check that we're going to add is PHP syntax check. PHP has a built-in linter, which you can invoke like this: php -l my-file.php. This is what we're going to use. Because the php -l command doesn't support multiple files as arguments, I've written a small wrapper shell script and saved it to ci/linter.sh:
#!/bin/sh
files=<code>sh ci/get-changed-php-files.sh | xargs</code>last_status=0
status=0
# Loop through changed PHP files and run php -l on each
for f in "$files" ; do message=<code>php -l $f</code> last_status="$?" if [ "$last_status" -ne "0" ]; then # Anything fails -> the whole thing fails echo "PHP Linter is not happy about $f: $message" status="$last_status" fi
done
if [ "$status" -ne "0" ]; then echo "PHP syntax validation failed!"
fi
exit $status

Most of the time, you don't actually want to check each and every PHP file that you have. Instead, it's better to check only those files that have been changed. The Gitlab pipeline runs on every push to the repository, and there is a way to know which PHP files have been changed. Here's a simple script, meet ci/get-changed-php-files.sh:
#!/bin/sh
# What's happening here?
#
# 1. We get names and statuses of files that differ in current branch from their state in origin/master.
# These come in form (multiline)
# 2. The output from git diff is filtered by unix grep utility, we only need files with names ending in .php
# 3. One more filter: filter *out* (grep -v) all lines starting with R or D.
# D means "deleted", R means "renamed"
# 4. The filtered status-name list is passed on to awk command, which is instructed to take only the 2nd part
# of every line, thus just the filename
git diff --name-status origin/master | grep '\.php$' | grep -v "^[RD]" | awk '{ print }'

These scripts can easily be tested in your local environment ( at least if you have a Linux machine, that is ;-) ).
Now, as we have our first check, we'll finally create our .gitlab-ci.yml. This is where your pipeline is declared using YAML notation:
# we're using this beautiful tool for our pipeline: https://github.com/jakzal/phpqa
image: jakzal/phpqa:alpine
# For this sample pipeline, we'll only have 1 stage, in real-world you would like to also add at least "deploy"
stages: - QA
linter:
stage: QA
# this is the main part: what is actually executed
script: - sh ci/get-changed-php-files.sh | xargs sh ci/linter.sh

The first line is image: jakzal/phpqa:alpine and it's telling Gitlab that we want to run our pipeline using a PHP-QA utility by jakzal. It is a docker image containing PHP and a huge variety of QA-tools. We declare one stage - QA, and this stage by now has just a single job named linter. Every job can have it's own docker image, but we don't need that for the purpose of this tutorial. Our project reaches Step 2. Once I had pushed these changes, I immediately went to the project's CI/CD page. Aaaand.... the pipeline was already running! I clicked on the linter job and saw the following happy green output:
Running with gitlab-runner 11.9.0-rc2 (227934c0) on docker-auto-scale ed2dce3a
Using Docker executor with image jakzal/phpqa:alpine ...
Pulling docker image jakzal/phpqa:alpine ...
Using docker image sha256:12bab06185e59387a4bf9f6054e0de9e0d5394ef6400718332c272be8956218f for jakzal/phpqa:alpine ...
Running on runner-ed2dce3a-project-11318734-concurrent-0 via runner-ed2dce3a-srm-1552606379-07370f92...
Initialized empty Git repository in /builds/crocodile2u/ci-showcase/.git/
Fetching changes...
Created fresh repository.
From https://gitlab.com/crocodile2u/ci-showcase * [new branch] master -> origin/master * [new branch] step-1 -> origin/step-1 * [new branch] step-2 -> origin/step-2
Checking out 1651a4e3 as step-2...
Skipping Git submodules setup
$ sh ci/get-changed-php-files.sh | xargs sh ci/linter.sh
Job succeeded

It means that our pipeline was successfully created and run!

PHP Code Sniffer.

PHP Code Sniffer is a tool for keeping app of your PHP files in one uniform code style. It has a hell of customizations and settings, but here we will only perform simple check for compatibilty with PSR-2 standard. A good practice is to create a configuration XML file in your project. I will put it in the root folder. Code sniffer can use a few file names, of which I prefer phpcs.xml:
<?xml version="1.0"?>
/resources

I also will append another section to .gitlab-ci.yml:
code-style:	stage: QA	script:	# Variable $files will contain the list of PHP files that have changes	- files=<code>sh ci/get-changed-php-files.sh</code> # If this list is not empty, we execute the phpcs command on all of them - if [ ! -z "$files" ]; then echo $files | xargs phpcs; fi

Again, we check only those PHP files that differ from master branch, and pass their names to phpcs utility. That's it, Step 3 is finished! If you go to see the pipeline now, you will notice that linter and code-style jobs run in parallel.

Adding PHPUnit

Unit and integration tests are essential for a successful and maintaiable modern software project. In PHP world, PHPUnit is de facto standard for these purposes. The PHPQA docker image already has PHPUnit, but that's not enough. Our project is based on Laravel, which means it depends on a bunch of third-party libraries, Laravel itself being one of them. Those are installed into vendor folder with composer. You might have noticed that our .gitignore file has vendor folder as one of it entries, which means that it is not managed by the Version Control System. Some prefer their dependencies to be part of their Git repository, I prefer to have only the composer.json declarations in Git. Makes the repo much much smaller than the other way round, also makes it easy to avoid bloating your production builds with libraries only needed for development.
Composer is also included into PHPQA docker image, and we can enrich our .gitlab-ci.yml:
test:	stage: QA	cache:	key: dependencies-including-dev	paths: - vendor/	script:	- composer install	- ./vendor/bin/phpunit

PHPUnit requires some configuration, but in the very beginning we used composer create-project to create our project boilerplate.laravel/laravel package has a lot of things included in it, and phpunit.xml is also one of them. All I had to do was to add another line to it:
xml

APP_KEY enironment variable is essential for Laravel to run, so I generated a key with php artisan key:generate.
git commit & git push, and we have all three jobs on theQA stage!

Checking that our checks work

In this branch I intentionally added changes that should fail all three job in our pipeline, take a look at git diff. And we have this out from the pipeline stages:Linter:
$ ci/linter.sh
PHP Linter is not happy about app/User.php:
Parse error: syntax error, unexpected 'syntax' (T_STRING), expecting function (T_FUNCTION) or const (T_CONST) in app/User.php on line 11
Errors parsing app/User.php
PHP syntax validation failed!
ERROR: Job failed: exit code 255

**Code-style**:
$ if [ ! -z "$files" ]; then echo $files | xargs phpcs; fi
FILE: ...ilds/crocodile2u/ci-showcase/app/Http/Controllers/Controller.php
----------------------------------------------------------------------
FOUND 0 ERRORS AND 1 WARNING AFFECTING 1 LINE
---------------------------------------------------------------------- 13 | WARNING | Line exceeds 120 characters; contains 129 characters
----------------------------------------------------------------------
Time: 39ms; Memory: 6MB
ERROR: Job failed: exit code 123

**test**:
$ ./vendor/bin/phpunit
PHPUnit 7.5.6 by Sebastian Bergmann and contributors.
F. 2 / 2 (100%)
Time: 102 ms, Memory: 14.00 MB
There was 1 failure:
1) Tests\Unit\ExampleTest::testBasicTest
This test is now failing
Failed asserting that false is true.
/builds/crocodile2u/ci-showcase/tests/Unit/ExampleTest.php:17
FAILURES!
Tests: 2, Assertions: 2, Failures: 1.
ERROR: Job failed: exit code 1

Congratulations, our pipeline is running, and we now have much less chance of messing up the result of our work.

Conclusion

Now you know how to set up a basic QA pipeline for your PHP project. There's still a lot to learn. Pipeline is a powerful tool. For instance, it can make deployments to different environments for you. Or it can build docker images, store artifacts and more! Sounds cool? Then spend 5 minutes of your time and leave a comment, you can also tell me if there is a pipeline topic you would like to be covered in next posts.
37435 views · 5 years ago
Securing PHP RESTful APIs using Firebase JWT Library

Hello Guys,

In our Last Blog Post, we have created restful apis,But not worked on its security and authentication. Login api can be public but after login apis should be authenticate using any secure token. one of them is JWT, So i am providing the Steps for Create and use JWT Token in our already created API.


Now its time To Implement JWT Authentication IN our Api, So these are the steps to implement it in our already created Apis


Step 1:Install and include Firebase JWT(JSON WEB TOKEN) in our project with following composer command        


 composer require firebase/php-jwt 


include the composer installed packages
require_once('vendor/autoload.php');


use namespace using following:
 use \Firebase\JWT\JWT; 



Step 2: Create a JWT server side using Firebase Jwt Library's encode method in Login action , and return it to Client



Define a private variable named Secret_Key in Class like following:

 private {
$payload = array(
'iss' => $_SERVER['HOST_NAME'],
'exp' => time()+600, 'uId' => $UiD
);
try{
$jwt = JWT::encode($payload, $this->Secret_Key,'HS256'); $res=array("status"=>true,"Token"=>$jwt);
}catch (UnexpectedValueException $e) {
$res=array("status"=>false,"Error"=>$e->getMessage());
}
return $res;
}


In our login action , if the user has been logged in successfully then with the status,_data_ and message just replace the login success code with following code:

$return['status']=1;
$return['_data_']=$UserData[0];
$return['message']='User Logged in Successfully.';

$jwt=$obj->generateToken($UserData[0]['id']);
if($jwt['status']==true)
{
$return['JWT']=$jwt['Token'];
}
else{
unset($return['_data_']);
$return['status']=0;
$return['message']='Error:'.$jwt['Error'];
}





Step 3: Now with every request after login should have the JWT token in its Post(even we can receive it in get or authentication header also but here we are receiving it in post)



No afetr successfully login you will get the JWt Token in your response,Just add that Token with every post request of after login api calls. So we will do it using postman, Find the screenshot 1 for checking the JWT Token is coming in login api response

JWT DEMO LOGIN API RESPONSE


Step 4:After reciving the JWt in every after login api call, we need to check whether the token is fine using JWT decode method in After login Apis like
UserBlogs
is a After login Api, So for verify that we are creating Authencate method in class like following:


 public function Authenticate($JWT,$Curret_User_id)
{
try {
$decoded = JWT::decode($JWT,$this->Secret_Key, array('HS256'));
$payload = json_decode(json_encode($decoded),true);

if($payload['uId'] == $Curret_User_id) {
$res=array("status"=>true);
}else{
$res=array("status"=>false,"Error"=>"Invalid Token or Token Exipred, So Please login Again!");
}
}catch (UnexpectedValueException $e) {
$res=array("status"=>false,"Error"=>$e->getMessage());
}
return $res;

}


Step 5: Cross check the response returned by Authenticate method in
UserBlogs
Action of api , replace the
UserBlogs
Action inner content with following code:


 if(isset($_POST['Uid']))
{

$resp=$obj->Authenticate($_POST['JWT'],$_POST['Uid']);
if($resp['status']==false)
{
$return['status']=0;
$return['message']='Error:'.$resp['Error'];
}
else{
$blogs=$obj->get_all_blogs($_POST['Uid']);
if(count($blogs)>0)
{
$return['status']=1;
$return['_data_']=$blogs;
$return['message']='Success.';
}
else
{
$return['status']=0;
$return['message']='Error:Invalid UserId!';
}
}
}
else
{
$return['status']=0;
$return['message']='Error:User Id not provided!';
}


Ah great its time to check out the UserBlogs Api, please find the screenshoot for that, Remember we need to put the JWt Token in POST Parameter as we have already recived that Value in Login Api call.

JWT DEMO Authentication in userBlogs API Call

Now if you want to verify that token is expiring in given time(10 minutes after generation time/login time), i am just clicking the same api with same token after 10 minutes and you can see there will not return any data and it is returning status false with following message :


JWT DEMO Authentication in userBlogs API Call


Also if you want to eloborate it more then i suggest you to try with modify Uid value with same token , you will another authentication issue and also if you modify the JWT token also then also you will not get the desired result and get authentication Issue

Thanks for reading out if you want the complete code of this file then please find following:
<?php 
header("Content-Type: application/json; charset=UTF-8");
require_once('vendor/autoload.php');
use \Firebase\JWT\JWT;

class DBClass {

private $host = "localhost";
private $username = "root";
private $password = ""; private $database = "news";

public $connection;

private $Secret_Key="*$%43MVKJTKMN$#";
public function connect(){

$this->connection = null;

try{
$this->connection = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->database, $this->username, $this->password);
$this->connection->exec("set names utf8");
}catch(PDOException $exception){
echo "Error: " . $exception->getMessage();
}

return $this->connection;
}

public function login($email,$password){

if($this->connection==null)
{
$this->connect();
}

$query = "SELECT id,name,email,createdAt,updatedAt from users where email= ? and password= ?";
$stmt = $this->connection->prepare($query);
$stmt->execute(array($email,md5($password)));
$ret= $stmt->fetchAll(PDO::FETCH_ASSOC);
return $ret;
}

public function get_all_blogs($Uid){

if($this->connection==null)
{
$this->connect();
}

$query = "SELECT b.*,u.id as Uid,u.email as Uemail,u.name as Uname from blogs b join users u on u.id=b.user_id where b.user_id= ?";
$stmt = $this->connection->prepare($query);
$stmt->execute(array($Uid));
$ret= $stmt->fetchAll(PDO::FETCH_ASSOC);
return $ret;
}

public function response($array)
{
echo json_encode($array);
exit;
}

public function generateToken($UiD)
{
$payload = array(
'iss' => $_SERVER['HOST_NAME'],
'exp' => time()+600, 'uId' => $UiD
);
try{
$jwt = JWT::encode($payload, $this->Secret_Key,'HS256'); $res=array("status"=>true,"Token"=>$jwt);
}catch (UnexpectedValueException $e) {
$res=array("status"=>false,"Error"=>$e->getMessage());
}
return $res;
}

public function Authenticate($JWT,$Current_User_id)
{
try {
$decoded = JWT::decode($JWT,$this->Secret_Key, array('HS256'));
$payload = json_decode(json_encode($decoded),true);

if($payload['uId'] == $Current_User_id) {
$res=array("status"=>true);
}else{
$res=array("status"=>false,"Error"=>"Invalid Token or Token Exipred, So Please login Again!");
}
}catch (UnexpectedValueException $e) {
$res=array("status"=>false,"Error"=>$e->getMessage());
}
return $res;

}
}

$return=array();
$obj = new DBClass();
if(isset($_GET['action']) && $_GET['action']!='')
{
if($_GET['action']=="login")
{
if(isset($_POST['email']) && isset($_POST['password']))
{
$UserData=$obj->login($_POST['email'],$_POST['password']);
if(count($UserData)>0)
{
$return['status']=1;
$return['_data_']=$UserData[0];
$return['message']='User Logged in Successfully.';

$jwt=$obj->generateToken($UserData[0]['id']);
if($jwt['status']==true)
{
$return['JWT']=$jwt['Token'];
}
else{
unset($return['_data_']);
$return['status']=0;
$return['message']='Error:'.$jwt['Error'];
}

}
else
{
$return['status']=0;
$return['message']='Error:Invalid Email or Password!';
}
}
else
{
$return['status']=0;
$return['message']='Error:Email or Password not provided!';
}
}
elseif($_GET['action']=="UserBlogs")
{
if(isset($_POST['Uid']))
{

$resp=$obj->Authenticate($_POST['JWT'],$_POST['Uid']);
if($resp['status']==false)
{
$return['status']=0;
$return['message']='Error:'.$resp['Error'];
}
else{
$blogs=$obj->get_all_blogs($_POST['Uid']);
if(count($blogs)>0)
{
$return['status']=1;
$return['_data_']=$blogs;
$return['message']='Success.';
}
else
{
$return['status']=0;
$return['message']='Error:Invalid UserId!';
}
}
}
else
{
$return['status']=0;
$return['message']='Error:User Id not provided!';
}
}
}
else
{
$return['status']=0;
$return['message']='Error:Action not provided!';
}
$obj->response($return);
$obj->connection=null;
?>

15361 views · 5 years ago
Create Alarm and Monitoring on Custom Memory and Disk Metrics for Amazon EC2

Today I am going write a blog on how to Monitor Memory and Disk custom metrics and creating alarm in Ubuntu.

To do this, we can use Amazon CloudWatch, which provides a flexible, scalable and reliable solution for monitoring our server.

Amazon Cloud Watch will allow us to collect the custom metrics from our applications that we will monitor to troubleshoot any issues, spot trends, and configure operational performance. CloudWatch functions display alarms, graphs, custom metrics data and including statistics.

Installing the Scripts


Before we start installing the scripts for monitoring, we should install all the dependent packages need to perform on Ubuntu.

First login to your AWS server, and from our terminal, install below packages

sudo apt-get update
sudo apt-get install unzip
sudo apt-get install libwww-perl libdatetime-perl


Now Install the Monitoring Scripts


Following are the steps to download and then unzip we need to configure the Cloud Watch Monitoring scripts on our server:
1. In the terminal, we need to change our directory and where we want to add our monitoring scripts.
2. Now run the below command and download the source:

curl https://aws-cloudwatch.s3.amazonaws.com/downloads/CloudWatchMonitoringScripts-1.2.2.zip -O

3. Now uncompress the currently downloaded sources using the following commands

unzip CloudWatchMonitoringScripts-1.2.2.zip && \

rm CloudWatchMonitoringScripts-1.2.2.zip && \

cd aws-scripts-mon


The directory will contain Perl scripts, because of the execution of these scripts only report memory run and disk space utilization metrics will run in our Ubuntu server.
Currently, our folder will contain the following files:
mon-get-instance-stats.pl - This Perl file is used to displaying the current utilization statistics reports for our AWS instance on which these file scripts will be executed.
mon-put-instance-data.pl - This Perl script file will be used for collecting the system metrics on our ubuntu server and which will send them to the Amazon Cloud Watch.
awscreds.template - This Perl script file will contain an example for AWS credentials keys and secret access key named with access key ID.
CloudWatchClient.pm - This Perl script file module will be used to simplify by calling Amazon Cloud Watch from using other scripts.
LICENSE.txt – This file contains the license details for Apache 2.0.
NOTICE.txt – This file contains will gives us information about Copyright notice.
4. For performing the Cloud Watch operations, we need to confirm that whether our scripts have corresponding permissions for the actions:

If we are associated with an IAM role with our EC2 Ubuntu instance, we need to verify that which will grant the permissions to perform the below-listed operations:

cloudwatch:GetMetricStatistics

cloudwatch:PutMetricData

ec2:DescribeTags

cloudwatch:ListMetrics


Now we need to copy the ‘awscreds.template’ file into ‘awscreds.conf’ by using the command below and which will update the file with details of the AWS credentials.

cp awscreds.template awscreds.conf

AWSAccessKeyId = my_access_key_id

AWSSecretKey = my_secret_access_key


Now we completed the configuration.

mon-put-instance-data.pl


This Perl script file will collect memory, disk space utilization data and swap the current system details and then it makes handling a remote call to Amazon Cloud Watch to reports details to the collected cloud watch data as a custom metrics.

We can perform a simple test run, by running the below without sending data to Amazon CloudWatch

./mon-put-instance-data.pl --mem-util --verify --verbose


Now we are going to set a cron for scheduling our metrics and we will send them to Amazon CloudWatch
1. Now we need to edit the crontab by using below command:

 crontab -e

2. Now we will update the file using the following query which will disk space utilization and report memory for particular paths to Amazon CloudWatch in every five minutes:

*/5 * * * * ~/STORAGE/cloudwatch/aws-scripts-mon/mon-put-instance-data.pl --mem-util --mem-avail --mem-used --disk-space-util --disk-space-avail --disk-space-used --disk-path=/ --disk-path=/STORAGE --from-cron


If there is an error, the scripts will write an error message in our system log.

Use of Options

--mem-used
The above command will collect the information about used memory and which will send the details of the reports in MBs into the MemoryUsed metrics. This will give us information about the metric counts memory allocated by applications and the OS as used.
--mem-util
The above command will collect the information about memory utilization in percentages and which will send the details of the Memory Utilization metrics and it will count the usage of the memory applications and the OS.
--disk-space-util
The above command will collect the information to collect the current utilized disk space and which will send the reports in percentages to the DiskSpaceUtilization for the metric and for the selected disks.
--mem-avail
The above command will collect the information about the available memory and which will send the reports in MBs to the MemoryAvailable metrics details. This is the metric counts memory allocated by the applications and the OS as used.
--disk-path=PATH
The above command will collect the information and will point out the which disk path to report disk space.
--disk-space-avail
The above command will collect the information about the available disk space and which will send the reports in GBs to the DiskSpaceAvailable metric for the selected disks.
--disk-space-used
The above command will collect the information about the disk space used and which will send the reports in GBs to the DiskSpaceUsed metric for the selected disks.

The PATH can specify to point or any of the files can be located on which are mounted point for the filesystem which needs to be reported.

If we want to points to the multiple disks, then specify both of the disks like below:

--disk-path=/ --disk-path=/home


Setting an Alarm for Custom Metrics


Before we are going to running our Perl Scripts, then we need to create an alarm that will be listed in our default metrics except for the custom metrics. You can see some default metrics are listed in below image:



Once we completed setting the cron, then the custom metrics will be located in Linux System Metrics.

Now we are going to creating the alarm for our custom metrics
1. We need to open the cloudwatch console panel at https://console.aws.amazon.com/cloudwatch/home
2. Now navigate to the navigation panel, we need to click on Alarm and we can Create Alarm.
3. This will open a popup which with the list of the CloudWatch metrics by category.
4. Now click on the Linux System Metrics . This will be listed out with custom metrics you can see in the below pictures






5. Now we need to select metric details and we need to click on the NEXT button. Now we need to navigate to Define Alarm step.



6. Now we need to define an Alarm with required fields

Now we need to enter the Alarm name for identifying them. Then we need to give a description of our alarm.

Next, we need to give the condition with the maximum limit of bytes count or percentage when it notifies the alarm. If the condition satisfies, then the alarm will start trigger.

We need to provide a piece of additional information about for our alarm.

We need to define what are the actions to be taken when our alarm changes it state.

We need to select or create a new topic with emails needed for sending notification about alarm state.
7. Finally, we need to choose the Create Alarm.

So its completed. Now the alarm is created for our selected custom metrics.

Finished!

Now the alarm will be listed out under the selected state in our AWS panel. Now we need to select an alarm from the list seen and we can see the details and history of our alarm.
19290 views · 5 years ago
Generate PDF from HTML in Laravel 5.7

Today, I will share with you how to create a PDF file from HTML blade file in Laravel 5.7. We will be using dompdf package for generating the PDF file.

In the below example, we will install barryvdh/laravel-dompdf using composer package and thereafter we will add new route url with controller. Then we will create a blade file. Then after we have to just run project with serve and we can check the PDF file is for download.

Download Laravel 5.7

Now I am going to explain the step by step from scratch with laravel installation for dompdf. To get started, we need to download fresh Laravel 5.7 application using command, so open our terminal and run the below command in the command prompt:

composer create-project --prefer-dist laravel/laravel blog


Install laravel-dompdf Package

Now we will install barryvdh/laravel-dompdf composer package by using the following composer command in ourLlaravel 5.7 application.

composer require barryvdh/laravel-dompdf


Then the package is successfully installed in our application, after that open config/app.php file and we need to add alias and service provider.
config/app.php

'providers' => [
....
Barryvdh\DomPDF\ServiceProvider::class,
],

'aliases' => [
....
'PDF' => Barryvdh\DomPDF\Facade::class,
]


Create Routes

Now we need to create routes for the items listing. so now open our "routes/web.php" file and we need to add following route.
routes/web.php

Route::get('demo-generate-pdf','HomeController@demoGeneratePDF');


Create Controller

Here,we need to create a new controllerHomeController (mostly it will be there, we can skip this step if we don't need to create a controller) that will manage our pdf generation using the generatePDF() method of route.
app/Http/Controllers/HomeController.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use PDF;

class HomeController extends Controller
{
public function demoGeneratePDF()
{
$data = ['title' => 'Welcome to My Blog'];
$pdf = PDF::loadView('myPDF', $data);

return $pdf->download('demo.pdf');
}
}


Create Blade File

In the final step, let us create demoPDF.blade.php in the resources/views/demoPDF.blade.php for structure of pdf file and add the following code:
resources/views/demoPDF.blade.php

<!DOCTYPE html>
<html>
<head>
<title>Hi</title>
</head>
<body>
<h1>Welcome to My BLOG - {{ $title }}</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</body>
</html>


Now run the below command for serve and test it:

php artisan serve

12059 views · 5 years ago
Creating a Tiny Blog Management system in Laravel 5.7

Hey There,
I am expecting you are familiar with PHP. In this post I will be using the Laravel framework to create a small blog system. I am showing here very simple steps to create blogs, If you want this complete code then please message me.
What are major Prequisites for Laravel:
* PHP version >= 5.6
* Composer should be installed in system

Create a project with name tiny_blog with following command

composer create-project laravel/laravel --prefer-dist tiny_blog


enter into the laravel project

cd tiny_blog


create a migration file using following artisan command
<pre>php artisan make:migration create_blog_table</pre>
After this command you will found a new file created in database/migrations folder in your project, Just edit the file having 'create_blog_table' appended in its name

Now replace following code to create table schema with function up(), So now the method will look like following:

public function up()
{
Schema::create('blogs', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->string('category');
$table->string('title');
$table->text('description');
$table->timestamps();
});

}


replace following snippet with down method, it will look like following:

public function down()
{
Schema::dropIfExists('blogs');
}


Its time to run the migration file we have created

php artisan migrate



After running,It will create the blogs table in database.Now time to create form and insert data into the table

Laravel itsef provide authentication , use following artisan command :

php artisan make:auth


Now start Larvel:

php artisan serve


it will start the laravel development server at http://127.0.0.1:8000


Now if you run that url the basic default ui will be created and login & register link you can see in Top right position of header

You can register and login now.this feature is provided by authentication module.
Now we need to create a controller for manage blogs with following command:

php artisan make:controller BlogController


will create a file namedBlogController.php in** app/HTTP/controllers** folder location

Now we need to create a Model also, use following command

php artisan make:model Blog


will create a file namedBlog.php in app folder location

Now in Controller we need to create a method for create blogs and available that method in Routes to access it via url. Just editroutes/web.php file and add the following line

Route::get('blog/create','BlogController@createBlog');

/create/blog/ will be url route that land on Blog Controller's createBlog method using get method.

Now before running this route just go to the app/Http/Controllers folder and Edit BlogController.php file and Add the createBlog method in that class as following

public function createBlog()
{
return view('blog.create');
}


This code will try to load the view from/resources/views/blog/create.blade.php

In Laravel blade is a template engine. As we had not created the view file yet, so we need to create a blog folder inside/resources/views/ folder then inside blog folder create a file create.blade.php with following form

@extends('layouts.app')

@section('content')
<div class="container">
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div><br />
@endif
<div class="row">
<form method="post" action="{{url('blog/create')}}">
<div class="form-group">
<input type="hidden" value="{{csrf_token()}}" name="_token" />
<label for="title">Title:</label>
<input type="text" class="form-control" name="title"/>
</div>
<div class="form-group">
<label for="title">Category/Tags:</label>
<input type="text" class="form-control" name="category"/>
</div>
<div class="form-group">
<label for="description">Description:</label>
<textarea cols="10" rows="10" class="form-control" name="description"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
@endsection



Now we need to add a additional route to handle the post request on blog/create route, Just edit routes/web.php file and just add following line in last:

Route::post('blog/create','BlogController@saveBlog'); 


post route to handle the form post on route blog/create


Now create a method name saveBlog to save the user input data in the form
 public function saveBlog(Request $request)
{
$blog = new Blog();

$this->validate($request, [
'title'=>'required',
'category'=>'required',
'description'=> 'required'
]);

$blog->createBlog($request->all());
return redirect('blog/index')->with('success', 'New blog has been created successfully :)'); }


Notice This method is using Blog object that we don't know that where it comes from? , So to make above code working we need to include the model which we created earlier need to include in our controller file So use following code to include it before the class created.

use App\Blog;


Now following line shows that there is a method named createBlog in Model(app/Blog.php), but in actual it is not there:

$blog->createBlog($data);



So go to the file app/Blog.php and Edit it and inside the class add following method:

 public function createBlog($data)
{

$this->user_id = auth()->user()->id;
$this->title = $data['title'];
$this->description = $data['description'];
$this->category = $data['category'];
$this->save();
return 1;
}


Now the creation of blog task has been done , Its time to show the created Entries So just create a route blog/index in routes/web.php

Route::get('blog/index','BlogController@showAllBlogs');


get route blog/index to show all the created blogs by current user


Now just add a method in controller
public function showAllBlogs()
{
$blogs = Blog::where('user_id', auth()->user()->id)->get();

return view('blog.index',compact('blogs'));
}



This method requires to create a index view in blog folder , So create a file named index.blade.php in /resources/views/blog/ folder with following code

@extends('layouts.app')

@section('content')
<div class="container">
@if(\Session::has('success'))
<div class="alert alert-success">
{{\Session::get('success')}}
</div>
@endif
<a type="button" href="{{url('blog/create')}}" class="btn btn-primary">Add New Blog</a>
<br>
<table class="table table-striped">
<thead>
<tr>
<td>ID</td>
<td>Title</td>
<td>Category</td>
<td>Description</td>
<td colspan="2">Action</td>
</tr>
</thead>
<tbody>
@foreach($blogs as $blog)
<tr>
<td>{{$blog->id}}</td>
<td>{{$blog->title}}</td>
<td>{{$blog->category}}</td>
<td>{{$blog->description}}</td>
<td>Edit</td>
<td>Delete</td>
</tr>
@endforeach
</tbody>
</table>
<div>
@endsection



Now all code is ready but we need to add 1 line of code to prevent the blog controller without authentication or without login

just add the following constructor method in BlogController class

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


this constructor method will call very first when user will try to access any of BlogController class method, and the middleware will check whether user is logged in then only it will allow to access that method otherwise it will redirect to login page automatically.


After It Run your Code and you will able to create and listing your created blogs/articles. but the Edit and Delete links are not working right now, If you want that also working then please comment here or message me. If we get multiple requests then definitely i will write its part 2 article


Thanks very much for reading this blog, if you have any doubt about it then let me know in comments or by messaging me.

Following is the final code for BlogController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Blog;



class BlogController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}

public function createBlog()
{
return view('blog/create');
}


public function saveBlog(Request $request)
{
$blog = new Blog();

$this->validate($request, [
'title'=>'required',
'category'=>'required',
'description'=> 'required'
]);

$blog->createBlog($request->all());
return redirect('blog/index')->with('success', 'New blog has been created successfully :)');
}

public function showAllBlogs()
{
$blogs = Blog::where('user_id', auth()->user()->id)->get();

return view('blog.index',compact('blogs'));
}

}

SPONSORS

The Ultimate Managed Hosting Platform