Quantcast
Channel: CodeSection,代码区,PHP教程_PHP编程_PHP开发技术文章 - CodeSec
Viewing all 6077 articles
Browse latest View live

User Login and Registration with CodeIgniter REST API

$
0
0

The RESTful web services provide a simple way to exchange data between different applications. If your web application needs to communicate over the across platforms, RESTful web service needs to be developed. The application can connect and work with different platforms (web, mobile, etc) using RESTful API. The REST API uses GET, PUT, POST and DELETE HTTP request for data handling across platforms.

CodeIgniter RESTful web service is the easiest way to integrate REST API service in the web application. Using CodeIgniter Rest Server you can easily create the REST API in CodeIgniter . In this tutorial, we will show you how to implement user login and registration with CodeIgniter REST API .

The example code will demonstrate how to build REST API and handle the user authentication (login and registration) with CodeIgniter.

The following steps will be implemented to create REST API in CodeIgniter .

Setup Rest Server in CodeIgniter. Create API method to handle user login via POST request. Create API method to handle user registration via POST request. Create API method to fetch the user account data via GET request. Create API method to update the user information via PUT request. Interact with the CodeIgniter RESTful API.

Before getting started, take a look the files structure of CodeIgniter REST application.


User Login and Registration with CodeIgniter REST API
Create Database Tables

To store user’s account information, a table needs to be created in the database. The following SQL creates a users table with some basic fields in mysql database.

CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(25) COLLATE utf8_unicode_ci NOT NULL,
`last_name` varchar(25) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`phone` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1=Active | 0=Inactive ',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

The following SQL creates a keys table to store REST API key for authentication.

CREATE TABLE `keys` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`key` varchar(40) NOT NULL,
`level` int(2) NOT NULL,
`ignore_limits` tinyint(1) NOT NULL DEFAULT '0',
`is_private_key` tinyint(1) NOT NULL DEFAULT '0',
`ip_addresses` text,
`date_created` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Import the API key data in the keys table, which will be used to validate the API call.

INSERT INTO `keys` (`id`, `user_id`, `key`, `level`, `ignore_limits`, `is_private_key`, `ip_addresses`, `date_created`) VALUES
(NULL, 1, 'CODEX@123', 0, 0, 0, NULL, '2018-10-11 13:34:33'); CodeIgniter REST Controller Setup

We will use REST Controller library to build RESTful web services in CodeIgniter. Follow the below steps to integrate RESTful server in CodeIgniter using REST Controller library.

Place the REST configuration file ( rest.php ) in application/config/ folder and specify the API configurations. Enable REST API authentication. $config['rest_auth'] = 'basic'; Set the username and password for API authentication. $config['rest_valid_logins'] = ['admin' => '1234']; Set the table name that holds the API key. $config['rest_keys_table'] = 'keys'; Enable REST API key. $config['rest_enable_keys'] = TRUE; Place the CodeIgniter Rest Controller library ( REST_Controller.php ) in the application/libraries/ folder. Place the CodeIgniter Format library ( Format.php ) in the application/libraries/ folder. Place the Rest Controller’s language ( rest_controller_lang.php ) in the application/language/english/ folder for multilingual support.

Note that: All the required files are included in the source code, you don’t need to download these files separately.

Model (User.php)

The User model handles the database related operations (fetch, insert, update, and delete).

__construct() Load the database library. Specify the table name to be used. getRows() Fetch the data from the database based on the given condition and returns data as an array. insert() Insert the data in the database. update() Update the data based on the ID in the database. delete() Delete data based on the ID from the database. <?php if (!defined('BASEPATH')) exit('No direct script access allowed'); class User extends CI_Model { public function __construct() { parent::__construct(); // Load the database library $this->load->database(); $this->userTbl = 'users'; } /* * Get rows from the users table */ function getRows($params = array()){ $this->db->select('*'); $this->db->from($this->userTbl); //fetch data by conditions if(array_key_exists("conditions",$params)){ foreach($params['conditions'] as $key => $value){ $this->db->where($key,$value); } } if(array_key_exists("id",$params)){ $this->db->where('id',$params['id']); $query = $this->db->get(); $result = $query->row_array(); }else{ //set start and limit if(array_key_exists("start",$params) && array_key_exists("limit",$params)){ $this->db->limit($params['limit'],$params['start']); }elseif(!array_key_exists("start",$params) && array_key_exists("limit",$params)){ $this->db->limit($params['limit']); } if(array_key_exists("returnType",$params) && $params['returnType'] == 'count'){ $result = $this->db->count_all_results(); }elseif(array_key_exists("returnType",$params) && $params['returnType'] == 'single'){ $query = $this->db->get(); $result = ($query->num_rows() > 0)?$query->row_array():false; }else{ $query = $this->db->get(); $result = ($query->num_rows() > 0)?$query->result_array():false; } } //return fetched data return $result; } /* * Insert user data */ public function insert($data){ //add created and modified date if not exists if(!array_key_exists("created", $data)){ $data['created'] = date("Y-m-d H:i:s"); } if(!array_key_exists("modified", $data)){ $data['modified'] = date("Y-m-d H:i:s"); } //insert user data to users table $insert = $this->db->insert($this->userTbl, $data); //return the status return $insert?$this->db->insert_id():false; } /* * Update user data */ public function update($data, $id){ //add modified date if not exists if(!array_key_exists('modified', $data)){ $data['modified'] = date("Y-m-d H:i:s"); } //update user data in users table $update = $this->db->update($this->userTbl, $data, array('id'=>$id)); //return the status return $update?true:false; } /* * Delete user data */ public function delete($id){ //update user from users table $delete = $this->db->delete('users',array('id'=>$id)); //return the status return $delete?true:false; } } Controller (Authentication.php)

It’s always better to make a separate folder for API related controller. In this example, we will place the API controller in controllers/api/ folder.

The Authentication API controller handles the API requests. It allows to implement a RESTful interface for the user login and registration through the GET, POST, and PUT request.

__construct() Load the User model to work with the database. login_post() getRows() registration_post() insert() user_get() getRows() user_put() Retrieve the user ID and data from the PUT request. Update the user data in the database based on the ID. <?php if (!defined('BASEPATH')) exit('No direct script access allowed'); // Load the Rest Controller library require APPPATH . '/libraries/REST_Controller.php'; class Authentication extends REST_Controller { public function __construct() { parent::__construct(); // Load the user model $this->load->model('user'); } public function login_post() { // Get the post data $email = $this->post('email'); $password = $this->post('password'); // Validate the post data if(!empty($email) && !empty($password)){ // Check if any user exists with the given credentials $con['returnType'] = 'single'; $con['conditions'] = array( 'email' => $email, 'password' => md5($password), 'status' => 1 ); $user = $this->user->getRows($con); if($user){ // Set the response and exit $this->response([ 'status' => TRUE, 'message' => 'User login successful.', 'data' => $user ], REST_Controller::HTTP_OK); }else{ // Set the response and exit //BAD_REQUEST (400) being the HTTP response code $this->response("Wrong email or password.", REST_Controller::HTTP_BAD_REQUEST); } }else{ // Set the response and exit $this->response("Provide email and password.", REST_Controller::HTTP_BAD_REQUEST); } } public function registration_post() { // Get the post data $first_name = strip_tags($this->post('first_name')); $last_name = strip_tags($this->post('last_name')); $email = strip_tags($this->post('email')); $password = $this->post('password'); $phone = strip_tags($this->post('phone')); // Validate the post data if(!empty($first_name) && !empty($last_name) && !empty($email) && !empty($password)){ // Check if the given email already exists $con['returnType'] = 'count'; $con['conditions'] = array( 'email' => $email, ); $userCount = $this->user->getRows($con); if($userCount > 0){ // Set the response and exit $this->response("The given email already exists.", REST_Controller::HTTP_BAD_REQUEST); }else{ // Insert user data $userData = array( 'first_name' => $first_name, 'last_name' => $last_name, 'email' => $email, 'password' => md5($password), 'phone' => $phone ); $insert = $this->user->insert($userData); // Check if the user data is inserted if($insert){ // Set the response and exit $this->response([ 'status' => TRUE, 'message' => 'The user has been added successfully.', 'data' => $insert ], REST_Controller::HTTP_OK); }else{ // Set the response and exit $this->response("Some problems occurred, please try again.", REST_Controller::HTTP_BAD_REQUEST); } } }else{ // Set the response and exit $this->response("Provide complete user info to add.", REST_Controller::HTTP_BAD_REQUEST); } } public function user_get($id = 0) { // Returns all the users data if the id not specified, // Otherwise, a single user will be returned. $con = $id?array('id' => $id):''; $users = $this->user->getRows($con); // Check if the user data exists if(!empty($users)){ // Set the response and exit //OK (200) being the HTTP response code $this->response($users, REST_Controller::HTTP_OK); }else{ // Set the response and exit //NOT_FOUND (404) being the HTTP response code $this->response([ 'status' => FALSE, 'message' => 'No user was found.' ], REST_Controller::HTTP_NOT_FOUND); } } public function user_put() { $id = $this->put('id'); // Get the post data $first_name = strip_tags($this->put('first_name')); $last_name = strip_tags($this->put('last_name')); $email = strip_tags($this->put('email')); $password = $this->put('password'); $phone = strip_tags($this->put('phone')); // Validate the post data if(!empty($id) && (!empty($first_name) || !empty($last_name) || !empty($email) || !empty($password) || !empty($phone))){ // Update user's account data $userData = array(); if(!empty($first_name)){ $userData['first_name'] = $first_name; } if(!empty($last_name)){ $userData['last_name'] = $last_name; } if(!empty($email)){ $userData['email'] = $email; } if(!empty($password)){ $userData['password'] = md5($password); } if(!empty($phone)){ $userData['phone'] = $phone; } $update = $this->user->update($userData, $id); // Check if the user data is updated if($update){ // Set the response and exit $this->response([ 'status' => TRUE, 'message' => 'The user info has been updated successfully.' ], REST_Controller::HTTP_OK); }else{ // Set the response and exit $this->response("Some problems occurred, please try again.", REST_Controller::HTTP_BAD_REQUEST); } }else{ // Set the response and exit $this->response("Provide at least one user info to update.", REST_Controller::HTTP_BAD_REQUEST); } } } Config

routes.php

Specify the routes for REST API requests (login, registration, view, and update).

$route['api/authentication/login'] = 'api/authentication/login'; $route['api/authentication/registration'] = 'api/authentication/registration'; $route['api/authentication/user/(:num)(\.)([a-zA-Z0-9_-]+)(.*)'] = 'api/authentication/user/id/$1/format/$3$4'; Login and Registration with CodeIgniter RESTful Web Services

You can interact and use the CodeIgniter REST API methods to integrate the user login system in the different applications. The cURL allows you to make HTTP requests in PHP. We will use PHP cURL to interact with CodeIgniter REST API, and perform the GET, POST, and PUT requests. The following examples uses HTTP Basic authentication with API key to connect to the RESTful API.

User Registration via REST API:

The following code performs a POST request to insert the user data for registration (signup) via CodeIgniter REST API.

// API key $apiKey = 'CODEX@123'; // API auth credentials $apiUser = "admin"; $apiPass = "1234"; // API URL $url = 'http://example.com/codeigniter/api/authentication/registration/'; // User account info $userData = array( 'first_name' => 'John', 'last_name' => 'Doe', 'email' => 'john@example.com', 'password' => 'login_pass', 'phone' => '123-456-7890' ); // Create a new cURL resource $ch = curl_init($url); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($ch, CURLOPT_HTTPHEADER, array("X-API-KEY: " . $apiKey)); curl_setopt($ch, CURLOPT_USERPWD, "$apiUser:$apiPass"); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $userData); $result = curl_exec($ch); // Close cURL resource curl_close($ch);

User Login via REST API:

The following code performs a POST request to validate the credential for login (sign in) via CodeIgniter REST API.

// API key $apiKey = 'CODEX@123'; // API auth credentials $apiUser = "admin"; $apiPass = "1234"; // API URL $url = 'http://example.com/codeigniter/api/authentication/login/'; // User account login info $userData = array( 'email' => 'john@example.com', 'password' => 'login_pass' ); // Create a new cURL resource $ch = curl_init($url); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($ch, CURLOPT_HTTPHEADER, array("X-API-KEY: " . $apiKey)); curl_setopt($ch, CURLOPT_USERPWD, "$apiUser:$apiPass"); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $userData); $result = curl_exec($ch); // Close cURL resource curl_close($ch);

Retrieve User Account Data via REST API:

The following code performs a GET request to retrieve the user’s account data via CodeIgniter REST API.

// API key $apiKey = 'CODEX@123'; // API auth credentials $apiUser = "admin"; $apiPass = "1234"; // Specify the ID of the user $userID = 1; // API URL $url = 'http://example.com/codeigniter/api/authentication/user/'.$userID; // Create a new cURL resource $ch = curl_init($url); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($ch, CURLOPT_HTTPHEADER, array("X-API-KEY: " . $apiKey)); curl_setopt($ch, CURLOPT_USERPWD, "$apiUser:$apiPass"); $result = curl_exec($ch); // Close cURL resource curl_close($ch);

Update User Account via REST API:

The following code performs a PUT request to update the user data via CodeIgniter REST API.

// API key $apiKey = 'CODEX@123'; // API auth credentials $apiUser = "admin"; $apiPass = "1234"; // Specify the ID of the user $userID = 1; // API URL $url = 'http://example.com/codeigniter/api/authentication/user/'; // User account info $userData = array( 'id' => 1, 'first_name' => 'John2', 'last_name' => 'Doe2', 'email' => 'john2@example.com', 'password' => 'user_new_pass', 'phone' => '545-856-3439' ); // Create a new cURL resource $ch = curl_init($url); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-API-KEY: '.$apiKey, 'Content-Type: application/x-www-form-urlencoded')); curl_setopt($ch, CURLOPT_USERPWD, "$apiUser:$apiPass"); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($userData)); $result = curl_exec($ch); // Close cURL resource curl_close($ch);

Are you want to get implementation help, or modify or extend the functionality of this script?Submit paid service request

Download Source Code


Exakat 1.4.9 Review - Exakat

$
0
0

Exakat 1.4.9 Review - Exakat

Exakat 1.4.9 Review

Exakat 1.4.9 Review

Exakat 1.4.9 follows the preparation of php 7.3 : we added a lot of new rules to get ready for the upcoming version. There was already 9 available checks, but more are coming in. The most interesting of it is that they close edge cases that will benefit other versions : avoid giving references to static properties, avoid mixing reading and writing the same variable in the same expression. We also kindly suggest you start using ‘named regex’, where the captured subpatterns have names. As the saying goes, I am not a number, I am the Exakat 1.4.9 review.

Static properties and references

From the UPGRADING docs , static properties were split between inheriting classes when the property was set with a reference.

<?php
class Test {
public static $x = 0;
}
class Test2 extends Test { }
Test2::$x = &$x;
$x = 1;
var_dump(Test::$x, Test2::$x);
// Previously: int(0), int(1)
// Now: int(1), int(1)
?>

This is a fairly rare piece of code, but a nasty bug when it shows up. This is now reported as an issue for version below PHP 7.3.

Repeated interfaces

PHP accepts multiple time the same interfaces in a implements clause, just like that :

<?php
class foo implements bar, bar, bar, bar {
}
?>

Once bar is implemented, the following one is also valid, so there is no need for an error. As for clean code, of course, there is no need to repeat the interface, so this is now reported.

Note that this analysis is distinct from the Already Parents Interface analysis, which reports when an interface is implemented multiple times, over several generations : for example, when the class and its children both implements the same interface. This double implementation is also superfluous, but it is easier to miss.

Named Regex

PCRE is moving to PCRE 2.0 in PHP 7.3, so it will be time to review all those regex. While you’re at it, why not impress your friends and co-workers by giving names to sub-patterns ?

When using PCRE, sub-patterns get a number for later reference. In fact, you can give those subpatterns a literal name : this way, it is easier to understand what was captured, and in case of regex reorganisation, there is no need to change all the offsets. Look at that, there are even two ways to name a sub-pattern:

<?php
$x = 'abc';
preg_match_all('/(?<name>a)/', $x, $r);
print_r($r[1]);
print_r($r['name']);
preg_match("/(?<name>a)(?'sub'b)/", $x, $s);
print $s[2];
print $s['sub'];
?>

It works with preg_match and preg_match_all . This is not a PHP 7.3 upgrade: this was introduced in PHP 5.2.2. Boy, time flies…

Accessing properties the right way

PHP warns us each time a property is accessed the wrong way : accessing a static property normally, or accessing normally a static property. The two errors are not the same : the first a Notice, while the second is a fatal error.

<?php
class a {
static public $a = 1;
function foo() {
echo self\:\:$a; // right
echo $this->a; // WRONG
}
}
class b {
public $b = 1;
function foo() {
echo $this->$b; // right
echo b\:\:$b; // WRONG
}
}
?>

It is recommended checking all the access, and stick to their definition.

The Weekly Audits : 2018, Week #42

Exakat includes a ‘weekly’ report : this report is built with a selection of five analysis. This means a short audit report, with few issues to review. This is not a lot to read them, and review them in your code. Everyone in the PHP community can focus on one of the classic coding problems and fix it. Talk about the weekly audit around you : you’ll find programmers facing the same challenges.

To obtain the ‘weekly’ audit, run an audit, and request the ‘Weekly’ report.

# Init the project (skip when it is already done) php exakat.phar init -p <yourproject> -R https://github.com/Seldaek/monolog.git -git
# Run the project (skip when it is already done) php exakat.phar project -p <yourproject>
# Export the weekly project (every monday) php exakat.phar report -p <yourproject> -format Weekly
# Open projects/<yourproject>/weekly/index.html in your browser

Every week, you can find here 5 new analysis to review in your code. In fact, when your code is clean, you can also take a quick look at the upcoming

This week, we focus on five special analysis.

Logical Should Use Symbolic Operators : Logical operators come in two flavors : and / &&, || / or, ^ / xor. Repeated print() : Always merge several print or echo in one call. Buried Assignation : Those assignations are buried in the code, and placed in unexpected situations. Hash Algorithms : There is a long but limited list of hashing algorithms available to PHP. No Empty Regex : PHP regex don’t accept empty regex, nor regex with alphanumeric delimiter.

Every week, you can find here 5 new analysis to review in your code. In fact, when your code is clean, you can also take a quick look at the upcoming week with the ‘Go further’ section.

Happy PHP Code Reviews

All the 359 analyzers are presented in the docs, including the fuzzy Strtr arguments : this native PHP call requires strings of the same length to be useful. Although this mostly applies to older code sources, it is a rare bug : 5% applications mishandle strtr().

You can check all of the Exakat reports at the gallery:exakat gallery.

Download Exakat on exakat.io, install it with Docker , upgrade it with ‘exakat.phar upgrade -u’ and like us on github .

40 Interactive Click, Hold & Drag Website Designs

$
0
0

A strong, memorable web designis one of the best ways to stand out. A well-designed click, hold anddrag to explore and scroll website can catch people`s attention, cause them to want to look a little longer, and make them remember your site. If it`s used wisely it saves a lot of space and helps in compartmentalising the content on an app. In this post, you`ll find 40 Interactive Click, Hold & Drag Website Designs from both individual web designers and creative studios worldwide.

Millions of Downloads:43,000+ WordPress Themes, Plugins & Design Assets Ad

Avada WordPress
40 Interactive Click, Hold &amp; Drag Website Designs
XTheme WordPress
40 Interactive Click, Hold &amp; Drag Website Designs
Enfold WordPress
40 Interactive Click, Hold &amp; Drag Website Designs
Flatsome WordPress
40 Interactive Click, Hold &amp; Drag Website Designs
the7 WordPress
40 Interactive Click, Hold &amp; Drag Website Designs
Bridge WordPress
40 Interactive Click, Hold &amp; Drag Website Designs
Leviev Group
40 Interactive Click, Hold &amp; Drag Website Designs
The House That Yauch Built
40 Interactive Click, Hold &amp; Drag Website Designs
RUYA DIGITAL
40 Interactive Click, Hold &amp; Drag Website Designs
Ben Mingo ― Portfolio
40 Interactive Click, Hold &amp; Drag Website Designs
Marie Morelle Illustrator
40 Interactive Click, Hold &amp; Drag Website Designs
H A
40 Interactive Click, Hold &amp; Drag Website Designs
Artistsweb
40 Interactive Click, Hold &amp; Drag Website Designs
LIBERTY LONDON
40 Interactive Click, Hold &amp; Drag Website Designs
Corona WOOOHOOO
40 Interactive Click, Hold &amp; Drag Website Designs
Carlos G Notario
40 Interactive Click, Hold &amp; Drag Website Designs
BLUES DESIGN
40 Interactive Click, Hold &amp; Drag Website Designs
Love Lost
40 Interactive Click, Hold &amp; Drag Website Designs
BryBry
40 Interactive Click, Hold &amp; Drag Website Designs
Decathlon United
40 Interactive Click, Hold &amp; Drag Website Designs
WEIMA Maschinenbau
40 Interactive Click, Hold &amp; Drag Website Designs
Black Messiah
40 Interactive Click, Hold &amp; Drag Website Designs
Art4GlobalGoals
40 Interactive Click, Hold &amp; Drag Website Designs
Celia LOPEZ
40 Interactive Click, Hold &amp; Drag Website Designs
The Shift
40 Interactive Click, Hold &amp; Drag Website Designs
Fisheye Gallery
40 Interactive Click, Hold &amp; Drag Website Designs
Possibles
40 Interactive Click, Hold &amp; Drag Website Designs
Bullying and Behavior
40 Interactive Click, Hold &amp; Drag Website Designs
Red Collar’s Team
40 Interactive Click, Hold &amp; Drag Website Designs
Vide Infra
40 Interactive Click, Hold &amp; Drag Website Designs
Air France Music
40 Interactive Click, Hold &amp; Drag Website Designs
7h34
40 Interactive Click, Hold &amp; Drag Website Designs
Thymia
40 Interactive Click, Hold &amp; Drag Website Designs
World of Synesthesia
40 Interactive Click, Hold &amp; Drag Website Designs
World cup in pattern
40 Interactive Click, Hold &amp; Drag Website Designs
Mi Banxico
40 Interactive Click, Hold &amp; Drag Website Designs
Du Haihang
40 Interactive Click, Hold &amp; Drag Website Designs
Resn’s Little Helper
40 Interactive Click, Hold &amp; Drag Website Designs
Eurovet
40 Interactive Click, Hold &amp; Drag Website Designs
Space.io Why we explore
40 Interactive Click, Hold &amp; Drag Website Designs
Evert_45 blogs from the past
40 Interactive Click, Hold &amp; Drag Website Designs
Real Estate: Stained Glass
40 Interactive Click, Hold &amp; Drag Website Designs
Mausoleum of Augustus
40 Interactive Click, Hold &amp; Drag Website Designs
Desires Tram
40 Interactive Click, Hold &amp; Drag Website Designs
I Buongiorno
40 Interactive Click, Hold &amp; Drag Website Designs
Kvell
40 Interactive Click, Hold &amp; Drag Website Designs

Migrating from AWS EC2 to AWS Lightsail.

$
0
0

As is good practice for any and all Cloud Engineers I am constantly looking for ways to minimize cost of operations and simpify operations. For this blog specifically it currently costs around 25 USD / mo. The costs comes from the EC2 instance, RDS ( + 14 day back ups), and a EFS volume, Route52 domain, and outbound traffic. Looking around Lightsail is a much simpler and cheaper solution; so I started migrating.

AWS Lightsail in a nutshell

Lightsail is, ostensibly, a dumbed down UI for simple VPS administration. Servers can be provisioned, a SSH key is provided, port access, and disk snapshots are all available via the UI; a simplified UI.

The Process Provision VPS SSH into machine

This is standard fair linux access. The Lightsail UI provides a download link for the *.pem file. Download it, move it to ~/.ssh, change permissions to 0400 and connect as normal. The UI also provides a web based SSH interface. I suspect this leverages AWS Systems Manager in the background.

Updated OS

Again, pretty standard fare, however I did an upgrade to Ubuntu 18.04. Call me brave but this is a personal blog site not a corporate payment system.

Install services

LEMP stack FTW

Nginx config is always all over the place. Configuration JSON files everywhere. Ugg. php/PHP-FPM was easy as usual. I went with the Unix sock style configuration. mysql, DO NOT FORGET TO RUN THE HARDENING SCRIPT Migrate WordPress

With the core services install I move on to the unknown part of the migration. How to migrate WordPress. Luckily WordPress contains basic import / export functionality via the Settings menu item.


Migrating from AWS EC2 to AWS Lightsail.

Took the output and imported it into the new instance. Everything went fine except the Link Directory content. That sucked, I had to find an alterate solution and migrate the content manually. Boo.

Update domain

With the content moved I went to Route 53 and setup a subdomain (https://blog.davidjeddy.com) and pointed it at the new static IP provisioned via the Lightsail UI. I then waited for propagation. Once I was sure blog.* pointed correctly I edited the TLD to redirect to blog.* thus not losing any organic traffic or mess with anyone’s bookmarks.

Backups

This is the web, crashes happen. It is a fact of life. For LightSail backup up my application was as easy as clicking ‘Create Snapshot’ in the UI and the disk is imaged. I can even do this via the CLI API .Since the instance now contains my entire applications and database it is an all-inclusive backup. Be sure to test your recovery plan!

Decommission old infrastructure

Once I was sure everything was running I did a ‘soft off’ of the old location. Specifically added a banner to the top of the site indicating the move was happening. At the end of the week I checked traffic patterns to ensure the old instance was no longer receiving traffic. Then, lights off.

Conclusion

Average cost before migration was running in the range of 25 USD / month. Projected cost after migration is around 10 USD / month. While not thousands per month this shows that AWS is serious about giving Linode / Dreamhost, other basic VPS providers a run for the money. Low cost + AWS infrastructure = market competition from the bottom to the top.

An Automatic PHP Restful Router

$
0
0
Router

An Fully Automatic, Framework independent, RESTful php Router component used in scrawler.


An Automatic PHP Restful Router
Why Scrawler Router?

This is an library for automatic restful routing, you do not have to define a single route, it automatically detects the url and calls the corresponding controller. Automatic routing is made possible by following some conventions.

Installation Using Composer composer require scrawler/router Getting Started

In your index.php

<?php use Scrawler\Router\RouteCollection; use Scrawler\Router\Router; use Symfony\Component\HttpFoundation\Response; $dir = /path/to/your/controllers; $namespace = Namespace\of\your\controllers; $router = new Router(new RouteCollection($dir,$namespace)); //Optional you can now pass your own Request object to Router for Router to work on //$router = new Router(new RouteCollection($dir,$namespace),Request $request); //Dispatch route and get back the response $response = $router->dispatch(); //Do anything with your Response object here //Probably middleware can hook in here //send response $response->send();

Done now whatever request occurs it will be automatically routed . You don't have define a single route

How it Works?

The automatic routing is possible by following some conventions. Lets take a example lets say a controller Hello

<?php //Hello.php class Hello{ public function getWorld(){ return "Hello World"; } }

now calling localhost/hello/world from your browser you will see hello world on your screen.

How does it do it automatically?

Each request to the server is interpreted by ghost route in following way:

METHOD /controller/function/arguments1/arguments2

The controller and function that would be invoked will be

<?php class controller{ public function methodFunction(arguments1,arguments2){ //Definition goes here } }

For Example the following call:

GET /user/find/1

would invoke following controller and method

<?php class User{ public function getFind($id){ //Function definition goes here } }

In above example 1 will be passed as argument $id

How should I name my function for automatic routing?

The function name in the controller should be named according to following convention: methodFunctionname Note:The method should always be written in small and the first word of function name should always start with capital. Method is the method used while calling url. Valid methods are:

all - maps any kind of request method i.e it can be get,post etc get - mpas url called by GET method post - maps url called by POST method put - maps url called by PUT method delete - maps url called by DELETE method

Some eg. of valid function names are: getArticles, postUser, putResource Invalid function names are: GETarticles, Postuser, PutResource

Need more information on working?

Test folders are probably the best place where you can see internal working of various functions and use them in your project accordinglt

Server Configuration Apache

You may need to add the following snippet in your Apache HTTP server virtual host configuration or .htaccess file.

RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond $1 !^(index\.php) RewriteRule ^(.*)$ /index.php/$1 [L]

Alternatively, if you’re lucky enough to be using a version of Apache greater than 2.2.15, then you can instead just use this one, single line:

FallbackResource /index.php IIS

For IIS you will need to install URL Rewrite for IIS and then add the following rule to your web.config :

<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <rewrite> <rule name="Toro" stopProcessing="true"> <match url="^(.*)$" ignoreCase="false" /> <conditions logicalGrouping="MatchAll"> <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" /> <add input="{R:1}" pattern="^(index\.php)" ignoreCase="false" negate="true" /> </conditions> <action type="Rewrite" url="/index.php/{R:1}" /> </rule> </rewrite> </system.webServer> </configuration> Nginx

Under the server block of your virtual host configuration, you only need to add three lines.

location / { try_files $uri $uri/ /index.php?$args; } License

Scrawler Router is created by Pranjal Pandey and released under the MIT License.

Stitcher.io: Laravel domains

$
0
0

On the Sticher.io site there's a new tutorial posted where Brendt shares some thoughts about domain driven design and splitting codebases to make them more maintainable and logically separated.

While many concepts in this post are inspired by DDD principles, they will not follow every rule set by the paradigm. In our context, "domain" can also be named "module". A "domain" simply refers to a category of related stuff, that's it.

The post then starts with a definition of what a "domain" is and how it relates to functionality in an application (a Laravel app in this case). He gives an example of restructuring the code into "domains" of functionality rather than thinking about their types (enums, rules, etc). He provides a new proposed directory structure for these domains including folders for Actions , Exceptions , Rules , Status and ValueObjects . He then walks through several of these categories and gives a bit more detail about what's inside and some of the functionality those files might contain.

Migrate from AWS Ec2 to Lightsail

$
0
0

As is good practice for any and all Cloud Engineers I am constantly looking for ways to minimize cost of operations and simpify operations. For this blog specifically it currently costs around 25 USD / mo. The costs comes from the EC2 instance, RDS ( + 14 day back ups), and a EFS volume, Route52 domain, and outbound traffic. Looking around Lightsail is a much simpler and cheaper solution; so I started migrating.

AWS Lightsail in a nutshell

Lightsail is, ostensibly, a dumbed down UI for simple VPS administration. Servers can be provisioned, a SSH key is provided, port access, and disk snapshots are all available via the UI; a simplified UI.

The Process SSH into machine

This is standard fair linux access. The Lightsail UI provides a download link for the *.pem file. Download it, move it to ~/.ssh, change permissions to 0400 and connect as normal. The UI also provides a web based SSH interface. I suspect this leverages AWS Systems Manager in the background.

Updated OS

Again, pretty standard fare, however I did an upgrade to Ubuntu 18.04. Call me brave but this is a personal blog site not a corporate payment system.

Install services

LEMP stack FTW

Nginx config is always all over the place. Configuration JSON files everywhere. Ugg. php/PHP-FPM was easy as usual. I went with the Unix sock style configuration. mysql, DO NOT FORGET TO RUN THE HARDENING SCRIPT Migrate Wordpress

With the core services install I move on to the unknown part of the migration. How to migrate Wordpress. Luckily Wordpress contains basic import / export functionality via the Settings menu item.


Migrate from AWS Ec2 to Lightsail
WIN!

Took the output and imported it into the new instance. Everything went fine except the Link Directory content. That sucked, I had to find an alterate solution and migrate the content manually. :( Boo.

Update domain

With the content moved I went to Route 53 and setup a subdomain (https://blog.davidjeddy.com) and pointed it at the new static IP provisioned via the Lightsail UI. I then waited for propagation. Once I was sure blog.* pointed correctly I edited the TLD to redirect to blog.* thus not losing any organic traffic or mess with anyone's bookmarks.

Backups

This is the web, crashes happen. It is a fact of life. For LightSail backup up my application was as easy as clicking 'Create Snapshot' in the UI and the disk is imaged. I can even do this via the CLI API .Since the instance now contains my entire applications and database it is an all-inclusive backup. Be sure to test your recovery plan!

Decommission old infrastructure

Once I was sure everything was running I did a 'soft off' of the old location. Specifically added a banner to the top of the site indicating the move was happening. At the end of the week I checked traffic patterns to ensure the old instance was no longer receiving traffic. Then, lights off.

Conclusion

Average cost before migration was running in the range of 25 USD / month. Projected cost after migration is around 10 USD / month. While not thousands per month this shows that AWS is serious about giving Linode / Dreamhost, other basic VPS providers a run for the money. Low cost + AWS infrastructure = market competition from the bottom to the top.

25+ Pieces of Advice to Help You Handle Gutenberg’s Predicament [WP Experts Adv ...

$
0
0

No ratings yet.

On the eve of the most buzzing upgrade in the WordPress universe, we’ve interviewed Michael Torbert , Matthew Woodward , Brian Jackson , andother WP experts. Further, you will learn what we need to know about this change, and what we need to fine tune on our websites before the release of WordPress 5.0 with Gutenberg editor by default.

Here we go with a checklist forWordPress websites that includes the info you need to consider if you want to survive an upgrade to version 5.0. The main and the most buzzing thing in WordPress 5 will be new default content builderGutenberg. This editor uses content blocks and allows adding various media items directly into the post/page body, without adding custom shortcodes or HTML code blocks.

Some people say that Gutenberg will break the WordPress part of the Internet. Others say that it’s our future and we have no choice but to accept it. Anyway, Gutenberg will be the default editor in WordPress 5.0 and we have to check if our websites are ready for it. The exact date of WordPress 5.0 release has not been given yet, probably it’s expected by the end of this year. So there is still some time to get prepared.

By the way, the new editor is named after Johannes Gutenberg - the person who started the Printing Revolution by introducing the printing press. He is regarded as a person who had started the new milestone of a history. So we can assume how ambitious WordPress team is about Gutenberg.

So here’s the to-do list for those, whose websites are built with WordPress Make a backup of your existing site

Always back up the live site before doing any updates like this one. That way, whatever goes wrong, you can always rollback, says certified WordPress expert Nikola Vejin at Codeable .

Create a staging environment

To test the new editor, create a staging site and then perform the WordPress update on this staging site first. A staging is a perfect copy of your original website and it's a safety measure. Now add a few posts using the new shiny Gutenberg editor. And then properly test all your core features and pages of the website as there might be unexpected conflicts, - says Marius Vetrici , WordPress specialist at WPRiders , - only when you confirm that the updated staging site works fine, you can roll out the updates on the live site. And then check the core features of the live site to ensure that it runs as expected.

Update your theme, plugins

As always, keep your plugins up to date in order to have the most current integration, says Michael Torbert , Co-Author of WordPress All-in-One for Dummies.

In addition to this, Ihtisham Zahoor , Web Developer at WordPress , recommends to update the site's themes and plugins, create a backup, and run health check before and after the upgrade to version 5 for a smooth transition.

Check your theme compatibility

I’d make sure to test the theme on staging site to make sure it's fully compatible before you decide to make the change. A lot of exciting new features for the editor are coming that will provide blocks to add elements to the content of the page and this will allow a lot of flexibility with page layout design to users. Most older themes are not going to support it.” - Says full stack developer Frederick Pohl .

If your theme is compatible, just relax and wait for the 5.0 release. According to Stacy M. Clements, web consultant who specializes in WordPress, Business Owner at Milepost42 , if your site is built with a reputable and supportedWordPress theme and plugins, and you keep it up to date, it's likely you will have a few problems. Major theme and plugin developers are aware of Gutenberg and are doing their best to modify their software to deal with the changes. If you have a custom-built theme or plugins, you will want to check with your developer to make sure the software is modified appropriately.

If your theme is built by TemplateMonster and you have noticed some problem while testing, just write to the support team and they will help you handle it.

Test how everything works with Gutenberg

Stacy M. Clements recommends you to check all types of content you have (pages, posts, any custom content types). You may find that everything works well, or you may find some problems with the way your content is displayed, or the way how your theme elements are displayed, or custom content you've created with a page builder. Make sure you're using the latest versions of your theme and plugins, but if you still have problems, contact your theme developer to find if they're going to support Gutenberg, if not, probably it’s time to change the theme.

If you need to make some major changes to get your site "Gutenberg-compatible", you can buy some time by installing the Classic Editor plugin which restores TinyMCE editor.

According to Brian Jackson , CMO of Kinsta , the Classic Editor is no longer a fallback option by the end of 2019. So it's very important that all WordPress users, bloggers, and developers alike dive into Gutenberg and start testing it as soon as possible.

Read all comments given by experts to have an advantage in the process of transition to the Gutenberg and to save your website, especially if your business completely depends on it.

It's very important that all WordPress users, bloggers, and developers alike dive into Gutenberg and start testing it as soon as possible. Gutenberg is coming, whether you like it or not. I wouldn't be surprised if the Classic Editor is no longer a fallback option by the end of 2019.

The first thing you should probably do is check to see if your WordPress theme is going to support the new Gutenberg blocks. If the theme developer is already on top of things, then you probably don't have much to worry about other than learning the new editor. If the developer hasn't even started testing stuff on Gutenberg yet, it may be time to look for a new theme. I'm a massive fan of GeneratePress.

The above goes for all plugins that tie into the WordPress editor. The Yoast SEO plugin is just one example where it already supports Gutenberg, and they are actively adding more and more support.

The best advice I can give users right now is not to wait to test everything on their site with Gutenberg. Many WordPress hosts have staging environments which make testing thingslike this easy.


Using Private Repositories in Composer on Heroku

$
0
0

I’m a big fan of Heroku . I enjoy writing code, but I don’t enjoy wrangling servers to run my code. Heroku is a “platform-as-a-service” (PaaS) provider, meaning it provides a hosting platform and all you have to do is push code; it will configure load-balanced servers and services for you.

Another service I use is Bitbucket . Bitbucket is great for hosting private repositories if you’re boot-strapping or don’t want to pay GitHub for private repositories. I use Bitbucket to host the source code for my personal projects that are closed source.

If you’re working on personal projects then you may also host the source code of packages in private repositories. To use these private packages as Composer dependencies in an application you deploy to Heroku, you’ll need to go through some configuration steps. The steps are roughly:

Create an OAuth consumer in your Bitbucket account. Add a COMPOSER_AUTH environment variable to your Heroku application. Set the repository URL in your composer.json file. Create an OAuth consumer in Bitbucket Sign in to your Bitbucket account: https://bitbucket.org/account/signin/ Click your avatar in the bottom-left of the screen. Click on “Bitbucket settings”. Choose “OAuth” from the “Access Management” section. Click the “Add consumer” button under the “OAuth consumers” heading. Set the name to “Heroku” and add a dummy callback URL; something like “https://example.com” is fine. Give the consumer the read repositories permission, and click “Save”. You’ll now have a new consumer. Make a note of its Key and Secret values. Add environment variable to Heroku

You’ll now need to add a COMPOSER_AUTH environment variable to your Heroku application. As the name suggests, it specifies to Composer how to authenticate access private repositories. Documentation for this environment variable (and other available variables) is here: https://getcomposer.org/doc/03-cli.md#composer-auth

The environment variable’s value with be a JSON object. The object should look like this:

{ "bitbucket-oauth": { "bitbucket.org": { "consumer-key": "XXX", "consumer-secret": "XXX" } } }

Obviously, replace the XXX values with the key and secret that was generated when you created your OAuth consumer on Bitbucket.

Now, set the environment variable in your Heroku app. You can either use the Heroku dashboard or the Heroku CLI . Setting an environment variable using the CLI looks like this:

$ heroku config:set COMPOSER_AUTH='{ \ "bitbucket-oauth": { \ "bitbucket.org": { \ "consumer-key": "XXX", \ "consumer-secret": "XXX" \ } \ } \ }' --app name-of-your-app

Be sure to use the actual name of your application for the --app flag.

Configure the repository URL

The final step to be able to use a private hosted package is to add to your composer.json file as a dependency, and set its URL.

Add a repositories key to your composer.json file if one does not exist already. It should be an array of objects. Each object should have a type and a url value. For packages hosted on Bitbucket, the type would be vcs and the URL would be the HTTPS URL of the repository, i.e.

{ "repositories": [ { "type": "vcs", "url": "https://bitbucket.org/your-username/your-repository-name.git" } ] }

It’s important you use the HTTPS URL, as the SSH URL does not work when authenticating using OAuth.

Finally, add the name of your package as it is in its own composer.json file as a dependency of your application:

{ "require": { "your-vendor-name/your-package-name": "dev-master" }, "repositories": [ { "type": "vcs", "url": "https://bitbucket.org/your-username/your-repository-name.git" } ] }

Commit the changes.

Finishing up

Now, when you next deploy your application to Heroku (using git push heroku ), if your consumer key and secret, repository URL, and package name are all correct; Heroku should use OAuth to authenticate with Bitbucket and be able to pull down your package’s source code!

TutsPlus.com: Trigonometry, Random Numbers and More With Built-in PHP Math Funct ...

$
0
0

The TutsPlus.com site has another great php tutorial for those new to the language covering mathematical functionality in the language , from the basics out to more complex topics like trigonometry and random number generation.

Sometimes, the maths required in a program can be more involved. You might need to work with logarithmic, trigonometric or exponential functions. In this tutorial, I'll discuss how to use each of these functions in PHP, with examples. This tutorial will introduce you to the built-in math functions in PHP for doing trigonometry, exponentiation, and logarithm calculations. We'll also look at rounding and generating random numbers.

They start off with some of the "heavy hitters" in PHP's math functionality and how how to perform trigonometric operations with the likes of sin , cos and tan . This is applied to create an interesting dynamic image using the GD functionality. Next up comes the exponential and logarithmic functions with simple examples followed by a section sharing some other useful math functions for more everyday needs.

StarTutorial.com: Modern PHP Developer - Iterator

$
0
0

StarTutorial has continued their "Modern php Developer" series of tutorials with their latest covering the use of Iterators for working with sets of data.

If you have used a for loop in PHP, the idea of iteration is most likely not foreign to you. You pass an array to a for loop, and perform some logic inside the loop, but did you know that you can actually pass data structures other than arrays to a for loop? That's where Iterator comes into play.

The tutorial starts by introducing some of the basic concepts of what iterators are and how they're represented in PHP in their most basic form: arrays. They cover some of the basic array handing and functions before getting into the actual Iterator object handling. The article is then broken up into a few parts covering iterators and their functionality:

Your first iterator class Why iterator? SPL Iterators ArrayObject vs SPL ArrayIterator Iterating the File System Peeking ahead with CachingIterator Generator

Code and a summary of the functionality is included in each section providing you with a great start towards using iterators over simple arrays in your modern PHP applications.

PHP Training in Chennai

$
0
0

PHP Training in Chennai

Learn php Training in Chennai from FITA, the professional institute who delivers training to enhance your technical skills. We help you in achieving your dreams through personal and professional development.

PHP is an open source programming language that is recognized globally as the most powerful scripting language for creating websites. FITA is a leading PHP Training Institute in Chennai.

Learn how to use PHP for data drove websites and our expert trainers will show you how to create professional websites that leverage the power of robust data at the same time keeping the usability in mind. FITA has been teaching PHP course in Chennai and has trained more than 1200 students and has helped to achieve professional results faster and more efficiently. Trained students from PHPCourse in Chennai are placed in top IT companies.

Learn PHP Training at FITA and gain an in-depth knowledge of PHP.

PHP Course Syllabus:

The course syllabus is specially designed for candidates to enter into the technology industry.

Understanding the PHP Basics Variables and Data Types in PHP Operators in PHP: Arithmetic, Logical and Comparison Mix your HTML with PHP Play a bit with Strings String Manipulation

Arrays in PHP

Array Basics Multidimensional Arrays Searching in Arrays Sorting Arrays Control Structures & Loops Using If, Else and ElseIf Using Switch Using While and Do While Loops Using for each loop Using Continue, Break and Goto Using Functions Built-in functions Custom Functions Passing Arguments Using Mandatory and Optional Parameters Returning Value from Function Text Functions Mathematical Functions Managing Global Variables $_GLOBALS $_SERVER $_GET $_POST $_COOKE $_FLES $_SESSON Cookie and Session Management in PHP File Management File handling basics Understanding File Permissions File Create File Read File Write File Append File Delete Renaming Files Copying Files Working with Directories Parsing Directory Structures File Upload Mastering mysql Introduction to SQL and Database Using SELECT, INSERT, UPDATE and DELETE queries Using JOINS Using phpMyAdmin Creating a Database Retrieving from Database Storing in Database Updating Values in Database Deleting from Database Creating a Table Advanced concepts in Database Sending Emails with PHP Configuring SMTP Server Sendmail_path directive Sending Text Email Sending HTML Email Object-Oriented Programming in PHP Using Classes and Objects Creating Methods Working with Properties Understanding Oops concepts Exception Handling in PHP Building CMS with PHP Creating a Database Creating Article Index Creating Article View Page Creating a Control Panel for Users Adding, Editing and Deleting Articles through CMS MVC Getting Familiar with MVC Directory Structure Parsing URLs Creating Controllers Controlling URL Parameters Passing Data Implementing your code in MVC What do you gain by learning PHP Course in Chennai? We are offering a lot of job opportunities for well-trained professionals in the market. PHP professionals are having a huge demand in IT industry. PHP professionals in the market are getting the high pay scale. PHP experts have a good career growth in IT industry They are the leading global IT experts for building and maintenance of the websites. Many of the IT companies are looking for the best PHP developers.

Learn PHP Training in Chennai at FITA to sustain in the global world. Many of the Best PHP professionals who are working in top IT Companies are trainers. Many of the students who are interested in learning the PHP Course, they will learn first the Web Designing Course in Chennai . We are providing the Certification and placement support to the students.

FITA makes learning a different experience

Gaining certification from a renowned PHP Training Insitute in Chennai opens many doors in this working world. We focus mainly on high-quality training to enhance your knowledge. The biggest challenge in today’s world is to get a job in the IT industry. FITA upgrades you with the latest versions.

FITAis a leading training institute thatoffers the in-depth program onPHPTrainingin Chennai. Training is offered by highlyexperiencedprofessionals with rich experience in UI designing and server-side PHP programming. If you are specifically looking for any customized trainingin the modules provided in our PHPtraining in Chennai syllabus, talk to our student counsellor to customize your PHP and MySQL Training! To know more about the BestPHP Training Institute in Chennai offered at FITA, call us at 98404-11333.

FITA has been ratedas the bestPHPTraining in Chennaiby Students and Professionals alike!

PHPTraining Center in Chennai Venue:

Are you located in any of these areas Adyar, Ambattur, Aminjikarai, Adambakkam, Anna Nagar, Anna Salai, Ashok Nagar, Besant Nagar, Choolaimedu, Chromepet, Egmore, Ekkattuthangal, Guindy, K.K.Nagar, Kilpauk, Kodambakkam, Madipakkam, Medavakkam, Mylapore, Nandanam, Nanganallur, Nungambakkam, OMR, Pallikaranai, Perungudi, Porur, Saidapet, Sholinganallur, St. Thomas Mount, T. Nagar, Tambaram, Teynampet, Thiruvanmiyur, Thoraipakkam,Vadapalani, Velachery, Villivakkam, Virugambakkam and West Mambalam.

Our T Nagar or Velachery office is just few kilometer away from your location. If you need the best PHPTraining in Chennai , drive a couple of extra kilometers is worth it!

PHP Training


PHP Training in Chennai
Rated 5/5 based on 6421 reviews

Insert php array into mysql

$
0
0

I have an array $product_array, and when I use print_r($product_array);. The array shows like this

Array ( [0] => Array ( [ID] => P00100 [NAME] => Edina [PRICE] => $20.00 ) [1] => Array ( [ID] => P00101 [NAME] => Richfield [PRICE] => $21.00 ) [2] => Array ( [ID] => P00102 [NAME] => Bloomington [PRICE] => $22.00 ) )

I set my database table in 4 columes, first one is mainid, and which is auto increment, following with ID, NAME, PRICE, as the keys showed above. I would like to insert this array $product_array into mysql. Can anyone help? Would be very much appreciated! tks.

$sql = array(); foreach( $myarray as $row ) { $sql[] = '('.$row['ID'].', "'.mysql_real_escape_string($row['NAME']).'", "'.$row['PRICE'].'")'; } mysql_query('INSERT INTO table (ID, NAME,PRICE) VALUES '.implode(',', $sql));

see more details :

insert multiple rows via a php array into mysql

Laravel 5.7: Adding Support for Login with Username or Email

$
0
0

I've already published a few articles on Laravel Login to support username or email. In this article, I'm going to cover the process of adding the username or email support with Laravel 5.7 default authentication system.

The process below helps you to understand the following things.

Adds support for email verification which is supported by default in the framework now. Adds support for register with the username, which is not available on a default authentication system. Adds support for login with either username or email.

The reason behind writing this article is peoples, preferring my previous articles about Laravel login and register with username or email support for earlier versions of Laravel.

Compatibility

If you are starting your fresh Laravel 5.7 project, and want to add the support for username or email for login and register, you could follow the steps from the beginning.

For any existing project just upgraded to Laravel 5.7, it is, of course, useful to follow the article to customize your authentication system.

Customization

Let's begin with the registration part to add support for username or email login with Laravel 5.7.

Register

For a fresh Laravel 5.7 setup, begin with generating the default auth scaffolding with an artisan console command, which ships with the framework out of the box.

Routes // no email verification Auth::routes(); // after adding, email verification Auth::routes(['verify' => true]); I would like to recommend you to follow the earlier article [ Email Verification after Registration with Laravel 5.7 ] side by side with this article to implement email verification with Laravel 5.7 authentication system. Database

For existing project add a new migration file using an artisan command to add a new field to the users' table, and for the new fresh project, you can easily edit the migration file generated with auth scaffolding and add a single line below.

$table->string('username')->unique();

To fill value in the database for username field, we've to add a key username to the $fillable property under app/User.php database model.

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

The user registration form also requires a little bit of customization to add the username field.

<div class="form-group row"> <label for="username" class="col-md-4 col-form-label text-md-right">{{ __('Username') }}</label> <div class="col-md-6"> <input id="username" type="text" class="form-control{{ $errors->has('username') ? ' is-invalid' : '' }}" name="username" value="{{ old('username') }}" required> @if ($errors->has('username')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('username') }}</strong> </span> @endif </div> </div> Controller

The default auth system ships with a controller class, which handles the necessary methods for the registration system. We've to edit a few methods under that class to add the username to the database.

Login

We've already added the necessary routes, email verification steps linked with another article. For the login system to support username or email we need to override a few methods on the login controller.

The login form requires a very little change on the input type field from email to text.

<input id="email" type="text" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required autofocus>

The controller class for login also ships with the framework and uses an AuthenticatesUsers trait, which handles the specific methods necessary for the default auth system.

To apply the new changes we need, we have to override the methods under the controller class for the login system.

// LoginController.php /** * Get the needed authorization credentials from the request. * * @param \Illuminate\Http\Request $request * @return array */ protected function credentials(Request $request) { $field = $this->field($request); return [ $field => $request->get($this->username()), 'password' => $request->get('password'), ]; } /** * Determine if the request field is email or username. * * @param \Illuminate\Http\Request $request * @return string */ public function field(Request $request) { $email = $this->username(); return filter_var($request->get($email), FILTER_VALIDATE_EMAIL) ? $email : 'username'; } /** * Validate the user login request. * * @param \Illuminate\Http\Request $request * @return void */ protected function validateLogin(Request $request) { $field = $this->field($request); $messages = ["{$this->username()}.exists" => 'The account you are trying to login is not registered or it has been disabled.']; $this->validate($request, [ $this->username() => "required|exists:users,{$field}", 'password' => 'required', ], $messages); } Code

The full source code for the all above customization is available on the github repository.

Conclusion

Thanks for following up my regular articles, and reading up to the end. If you have any feedback for me, feel free to leave your comment. Do not forget to share if you think worth sharing, and reading my articles.

Happy Coding!

How to use Laravel's Service Container with 3rd party packages

$
0
0

This is a pretty common scenario in day to day programming. You want to include an official 3rd party php package in your Laravel application. However, the API provider like Google Spreadsheets doesn’t provide a Laravel PHP package.

I’m going to show you how to Laravel-ify any PHP package easily inside of your exisiting Laravel application.

To show you how to do it, I’m going to use Googlesheets PHP Client. So in your package.json you should have it installed:

$ composer require google/apiclient:^2.0 Generating a Service Provider

Now in Laravel to define a Service you’ll first need to create a Service Provider. You can quickly generate one with an artisan command:

$ php artisan make:provider GoogleServiceProvider

That should generate a brand new GoogleServiceProvider in app/providers/GoogleServiceProvider.php .

Registering your new Service Provider

Now you need to register your shiny new ServiceProvider with your Laravel application. In config/app.php scroll down till you find the providers array. Add your new provider to it:

use App\ServiceProvider\GoogleServiceProvider; // rest of config/app.php $providers = [ // other providers GoogleServiceProvider::class, ];

Great now your Laravel application knows to look for GoogleServiceProvider when it’s booting up.

Defining your Google Spreadsheet as a Service

Now we can actually create your Google SpreadSheet Client as a Service. This will allow us to inject your Google SpreadSheet Client anywhere in your Laravel application without reinstantating it over and over again.

Open up your GoogleServiceProvider :

use Google_Client; use Google_Service_Sheets; class GoogleServiceProvider extends ServiceProvider { /** * Register bindings in the container. * * @return void */ public function register() { $this->app->singleton('google_spreadsheet_client', function ($app) { // we will instantiate the Google Spread Sheet Client once in this function $client = new Google_Client(); $client->setApplicationName('Google Sheets API PHP Quickstart'); $client->setScopes(Google_Service_Sheets::SPREADSHEETS_READONLY); $client->setAuthConfig('credentials.json'); $client->setAccessType('offline'); $client->setPrompt('select_account consent'); $service = new Google_Service_Sheets($client); return $service; }); } }

Great! Now you have wired up your Google Spread Sheet client as a service named google_spreadsheet_client . You can also bind services to Interfaces or Class names, but let’s keep things simple for this tutorial.

Using your new Google SpreadSheet Service in your application code

Now that you have defined a service, you can use the Laravel container helper to instantiate it anywhere:

class SpreadsheetsController extends Controller { /** * Get all spreadsheets */ public function index() { $spreadsheets = this->app->make('google_speadsheets_client'); // now you can use Google_Spread_Sheets client in anyway your choose } }

Note: you can also use the global helper resolve('google_spreadsheets_client') to access the container, if you want to access your service outside of a controller.

I hope this helps. If you have any other questions reach out to me at @ctrlaltdylan on the Twitters.


Async Expressive with Swoole

$
0
0

Have you have used Node.js ?

For those of my readers unfamiliar with Node.js, it's a server-side javascript framework that provides the ability to create, among other things, network services. To do so, it provides an event loop, which allows for such things as asynchronous processing.

In the php ecosystem, a group of Chinese developers have been creating an extension that provides many of the same capabilities as Node.js. This extension, called Swoole , allows you to create web servers with asynchronous capabilities. In many cases, the asynchronous capabilities are handled via coroutines, allowing you to write normal, synchronous code that still benefits from the asynchronous nature of the system event loop, allowing your server to continue responding to new requests as they come in!

We've been gradually adding and refining our Swoole support in Expressive , and recently issued a stable release that will work with any PSR-15 request handler. In this post, I'll enumerate what I feel are the reasons for considering Swoole when deploying your PHP middleware application.

I feel there are three key advantages to Swoole, and, by extension, any async PHP runtime:

Application-specific servers Performance Async processing Application-specific servers

There are a few general architectures for applications:

A single web server sitting in front of many web applications. A single web server sitting in front of a single web application. A load balancer sitting in front of many servers. Some servers might serve the same application, to provide redundancy. (Often, today, these may even be identical docker containers.)
Async Expressive with Swoole

The first scenario is common in internal networks and development, and in many shared hosting scenarios. It's generally considered less secure, however, as a vulnerability in one application can potentially escalate to affect all applications hosted on the server. Additionally, it means that any updates to PHP versions must be tested on all applications, which often means updates are few and far between ― which is also problematic from a security standpoint.

When you want to isolate the environment, you'll move to a single web server, single PHP application model:


Async Expressive with Swoole

And when you start scaling, this becomes a load balancer sitting in front of many of these web server/PHP application pairs:


Async Expressive with Swoole

In each of these last two scenarios, there's one thing I want to point out: your application consists of at least two distinct services: the PHP processes, and a web server.

You may have other services as well, such as an RDBMS or document database, cache, search, etc. But generally these are on separate servers and scaled separately. As such, they're outside of this discussion.

In these scenarios, this means each "server" is actually a composite. And when you are adding redundancy to your architecture, this adds significant complexity. It's one more process on each and every node that can fail, and additional configuration you need when deploying.

When we start thinking about microservices, this becomes more problematic. Microservices should be quick and easy to deploy; one service per container is both typical and desired.

What Swoole lets us do is remove one layer of that complexity.


Async Expressive with Swoole

We can have a service per container, and that container can be built with only PHP. We start the Swoole HTTP server, and it's ready to go. We then tell the reverse proxy or load balancer how to route to it, and we're done.

This is useful in each of the scenarios, including the one web server/mulitiple applications scenario, as we can have different PHP runtimes per application. Our "web server" becomes a reverse proxy instead.

Application-specific servers allow us to simplify our deployment, and ship microservices quickly.

Performance

Remember when PHP 7 came out, and it was like doubling the performance of your application?

What if you could do that again?

In our initial benchmarks of Expressive applications, we found that they performed four times better under Swoole than under a traditional nginx+php-fpm pair. More interesting: when benchmarking with a high number of concurrent requests, we also found that Swoole had fewer failed requests. This means you get both better performance and better resilience!

And the hits keep rolling in: when we enabled Swoole's coroutine support and benchmarked endpoints that made use of functionality backed by that coroutine support, we observed up to a ten-fold increase!

The coroutine support covers primarily network I/O operations. As such, operations that hit cache servers, use PDO, or make web requests benefit from it immediately, with no changes to your code.

Swoole makes this possible in a couple of ways. First, because you are firing up a server exactly once, you lose the price of bootstrapping your application that you normally incur on each and every request; your application is bootstrapped from the moment you start accepting requests. Bootstrapping often accounts for the greatest single amount of resource usage in your application.

Second, Swoole runs as an event loop, just like Node.js, allowing it to defer processing of long-running requests in order to respond to new, incoming requests. This leads into my last point.

Async processing

Swoole's event loop provides async functionality to PHP applications. While a number of userland libraries have popped up over the past five years or so that provide async capabilities for PHP, Swoole's is done as a native C extension, and works regardless of the operating system.

When you have an event loop, you can defer processing, which allows the server to respond to additional requests. Commonly, deferment can be explicit:

public function handle(ServerRequestInterface $request) : ResponseInterface { $ts = new DateTimeImmutable(); \Swoole\Event::defer($this->createCacheDeferment($ts)); return new EmptyResponse(202); } public function createCacheDeferment(DateTimeImmutable $ts) : callable { return function () use ($ts) { sleep(5); $now = new DateTimeImmutable(); $item = $this->cache->getItem('ts'); $item->set(sprintf( "Started: %s\nEnded: %s", $ts->format('r'), $now->format('r') )); $this->cache->save($item); }; }

In this example, we calculate the content to return, defer caching, and return a response immediately. This means your user does not need to wait for you to finish caching content.

Logging is another use case. In the Expressive Swoole bindings, we do access logging after we mark the response complete. This ensures that logging does not impact response times.

Another use case is webhooks. Your application can accept a payload immediately, but finish processing of it after sending the response back to the client.

Swoole also provides async-enabled versions of common filesystem operations, mysql, Redis, and an HTTP client. In each of these, you provide a callback indicating what should be done once the operation is complete:

use Swoole\Http\Client as HttpClient; $client = new HttpClient('https://example.com'); $client->setHeaders([ 'Accept' => 'application/json', 'Authorization' => sprintf('Bearer %s', $token), ]); // Make the request, telling it what code to execute once // it is complete: $client->get('/api/resource', function ($response) { // process the response }); // This code executes before the request completes: $counter++;

Code like the above has led to the term "callback hell" when you have many such deferments that depend on each other. So, what do you do if if you want your code to be "non-blocking", but don't want to write callbacks all the time? Well, recent versions of Swoole allow you to enable coroutine support for most I/O operations. What this means is that you can write your code just like you would in a synchronous environment, but whenever code that triggers a coroutine occurs, the server will advance the event loop, allowing it to answer additional requests before the current one completes its work, and then resume execution once it has.

// This spawns a coroutine: $statement = $pdo->query($sql);

Async functionality may not directly improve the performance of your application, but it will let your application answer more requests, allowing you to handle greater volumes of traffic!

zend-expressive-swoole

We released zendframework/zend-expressive-swoole 1.0.0 two weeks ago. This library acts as a zend-httphandlerrunner RequestHandlerRunner implementation, which means:

It can be used with any PSR-15 application. It can be used with any PSR-7 implementation.

In other words, if you want to use Swoole with the upcoming Slim 4 or with equip/dispatch or with northwoods/broker or any of the myriad PSR-15 dispatch systems out there, you can.

The library provides some interesting features for users:

Serving of static resources, with HTTP client-side caching headers. Configurable logging. Abiility to restart worker processes.

I've been running applications on versions of it for the past two months, and have noted that it has been stable and reliable. I definitely think it's worth giving it a spin!

Fin

I'm really excited about the possibilities of Swoole and other async systems, as I think they afford us better performance, better reliability, and the ability to defer functionality that doesn't need to complete before we respond to clients. I'd love to hear YOUR experiences, though, particularly in the form of blog posts! Send me a link to a blog post via a comment, or by tweeting at me , and I'll add it to the ZF newsletter .

Posted by Matthew Weier O'Phinney ,

As End of Life Nears, More Than Half of Websites Still Use PHP V5

$
0
0

As End of Life Nears, More Than Half of Websites Still Use PHP V5

Support for php 5.6 drops on December 31 but a recent report found that almost 62 percent of websites are still using version 5.

Almost 62 percent of all websites are still running PHP version 5 even as version 5.6 of the server-side scripting language inches toward an ominous end-of-life.

Hypertext Preprocessor (PHP), a programming language designed for use in web-based applications with HTML content, supports a wide variety of platforms and is used by numerous web-based software applications, including popular content management systems like WordPress, Joomla and Drupal.

However, starting in December, versions 5.6 and 7.0 will no longer be supported.

“The deadlines will not be extended, and it is critical that PHP-based websites are upgraded to ensure that security support is provided,” a recent CERT notice has warned users .

Despite end-of-life in the horizon, a new report by Web Technology Surveys found that PHP version 5 is still used by 61.8 percent of all server-side programming language websites. And, of those using version 5, 41.5 percent of websites are using version 5.6, the report said.

What this means is, security patches, upgrades and bug fixes will cease for end-of-life technology putting that percentage of PHP-based websites using PHP 7.0 and below at risk.
As End of Life Nears, More Than Half of Websites Still Use PHP V5

Researchers and developers alike have called on these websites to update to newer, supported versions of PHP 7.2.

It’s particularly critical given the popularity of PHP: A full 78.9 percent of all websites use PHP overall, Web Technology Surveys’ report found.

Martin Wheatley, senior web application developer and web security tester, said that impacted websites would run on a platform that no longer receives updates opening them up to hacks, data exposure or malware.

“I know there are still sites out there that run on PHP 5.6 (and earlier!) that should really be moved on, either updated for PHP 7.2 or if the code is un-maintainable due to years of abuse by developers, simply rebuilt in a modern framework,” he said in a post . “These sites probably include old libraries that haven’t had the joy of an update or have long since been abandoned. The libraries probably have bugs and security holes in themselves, never mind the hosting platform or the website code itself. In some cases library code can be updated easily, others not.”

Many websites are dragging their feet given that the updates cost time and money, he said.

And content management systems are doing nothing to help this cause Drupal is the only CMS that has posted an official notice requiring an upgrade to PHP 7 by March (three months after the PHP 5.6 end of life deadline).


As End of Life Nears, More Than Half of Websites Still Use PHP V5

“Drupal 8 will require PHP 7 starting March 6, 2019,” the company said. “Drupal 8 users who are running Drupal 8 on PHP 5.5 or PHP 5.6 should begin planning to upgrade their PHP version to 7.0 or higher (PHP 7.1+ is recommended). Drupal 8.6 will be the final Drupal 8 version to support PHP 5, andwill reach end-of-life on March 6, 2019, when Drupal 8.7.0 is released.”

There has been no such notice from WordPress or Joomla. Neither responded to a request for comment from Threatpost.

So what can websites that are still using PHP 5.6 do? Software engineer David Eddy stressed that they should contact their hosting provider and push them to support a secure version of the language.

“If you have a little technical knowledge, you and your team may be able to do a direct migration to a new machine with PHP 7,” he said in a recent post . “Otherwise, if you are a bit more technical you can install PHP 7 yourself. This may require removing an unsupported WordPress plugins, swapping code libraries or even doing some reprogramming due to a language extension no longer being supported.”

In addition to the risks associated with PHP 5.6, PHP 7.1 comes with advantages, including new features and bug fixes.

That includes speed improvements, according to web developer and Under2 Co-Founder Shane Jones, who took to Twitter to encourage websites to upgrade.

Anyone that's worked with me recently will know that I've been banging on about upgrading from #PHP5 to #PHP7 for years now. Mainly I've been focussed on the speed improvements due to #PHP being able to process more requests per second. Especially in #WordPress .

Thread 1/6 pic.twitter.com/HEPXq1ENO0

― Shane (@shanejones) October 15, 2018

In the end, while updating PHP is painful and time-consuming, is it worth protecting websites from various security risks that come with end of life, experts said.

“Yes it does cost time and money, but what’s worse, a small monthly support fee, or a headline ‘Site hacked, thousands of user details stolen’ followed by a fine for up to 20 million euros or 4% of your turnover under GDPR… I know what I’d rather pay,” said Wheatley.

Loading a laravel view with extension &period;html

$
0
0

Is it possible to have Laravel load view templates with a .html extension?

I'm rebuilding an existing app that has a bunch of .html files that are uploaded by users. It's a sort of multi-tenant application where each user can control the look and feel of their area by uploading templates.

I need to rebuild the app and make the change completely transparent to the users so I'd like to keep the .html extensions.

The best way I have found is to use View::addExtension in your base controller;

Here's my code sample:

View::addExtension('blade.html','blade');

class BaseController extends Controller { /** * Setup the layout used by the controller. * * @return void */ protected function setupLayout() { // Allows us to use easy-to-edit html extension files. // You can set 2nd param to 'php' is you want to // just process with php (no blade tags) View::addExtension('blade.html','blade'); if ( ! is_null($this->layout)) { $this->layout = View::make($this->layout); } } }

BUF早餐铺 | 黑客挟持罗马尼亚市政厅电脑并要求比特币赎金;PHP 5版年底终止安全更新, ...

$
0
0

各位 Buffer 早上好,今天是 2018 年 10 月 17 日星期三,农历九月初九。今天的早餐铺内容有:黑客挟持罗马尼亚市政厅电脑并要求比特币赎金;php 5版年底终止安全更新,6成网站恐面临风险;索尼表示已修复PS4漏洞 官方给出解决方法;NSA调查Google新系统Fuchsia的安全性;Twitter推出新项目:旨在追踪仇恨用户网络活动。


BUF早餐铺 | 黑客挟持罗马尼亚市政厅电脑并要求比特币赎金;PHP 5版年底终止安全更新, ...
黑客挟持罗马尼亚市政厅电脑并要求比特币赎金 据romania-insider消息,一名份不明的黑客已经封锁了罗马尼亚最富有的布加勒斯特第一区市政厅的所有计算机,并要求当局支付比特币的赎金以解锁网络。该区市长 Dan Tudorache表示,袭击者要求比特币支付大笔款项。不过,市政厅的 IT团队已经设法从这次攻击中解救了了大约一半的计算机,预计所有计算机在本周末之前能正常运行。[来源: Bianews ] PHP 5版年底终止安全更新,6成网站恐面临风险 10月16日上午消息,据中国台湾地区媒体报道,Web科技应用现况的调查公司W3Techs近日表示,根据所有网站使用的PHP版本状况,从明年1月1日起,有近62%的网站将因未能获得安全更新而陷入被黑或被植入恶意程序的风险。根据W3Techs的调查,截自本月15日,在其研究的网站样本中,使用PHP的比例高达78.9%,而所有网站使用PHP 5的比例又达到61.8%。细分当中版本,所有网站使用PHP 5.6版的比例为41.5%,为版本5之冠。[来源: 新浪科技 ] 索尼表示已修复PS4漏洞 官方给出解决方法

索尼就PS4漏洞问题进行了回应,索尼表示正计划通过系统更新解决。不过PlayStation英国客服官方Twitter现在表示,PS4漏洞问题已经修复,并给出了官方解决方法。

PlayStation英国客服官方Twitter说:“我们已经修复了这个问题,这个问题并不会把你的主机变砖,它们只是将你的主机陷入崩溃循环。其实这个问题5分钟之内就能很快搞定。在PS移动app上删除信息,然后安全模式启动,使用Option 5,主机就能恢复正常”。[来源: 3DMGAME ] NSA调查Google新系统Fuchsia的安全性 NSA对操作系统和软件进行调查主要是为了研究其是否可用于国家安全工作,因此,安全问题是他们考虑的焦点。他们发现,Zircon是Fuchsia唯一在监督模式运行的部分,而其他部分如驱动程序、文件系统和网络则以用户模式运行,这意味着应用程序在Fuchsia上的运行方式与在其他大多数操作系统的运行方式截然不同,但是,root工作操作的泄漏会导致严重的安全问题。[来源: OFweek ] Twitter推出新项目:旨在追踪仇恨用户网络活动 据外媒报道,跟其他社交媒体公司一样,Twitter也在其平台上继续处理着极端主义问题。日前,它推出了一个新项目以此来监控用户在上面的仇恨行为。据悉,新推出的工具叫Exploring Online Hate指示板,它由Twitter和新美国基金会(New America Foundation)、反诽谤联盟(Anti-Defamation League)联合推出。[来源: cnBeta ]

Encryption &lpar;large&rpar; files in PHP with openSSL

$
0
0

I'm trying to encrypt (big) files in php using AES and have looked into using Mcrypt and OpenSSL, the problem is all solutions I have found so far only encrypt strings, and the files I'm trying to encrypt would trigger the max memory limit for PHP (which unfortunately can't be set higher), how would I go about achieving this?

You could use CBC encryption using Mcrypt and then encrypt a segment of data at a time. Make sure that the segment is x times the block size of the used cipher (e.g. 16 bytes for AES). Encrypt the segment and take the last block of the generated ciphertext and use it as IV for the next segment. The final segment should be PKCS#7 padded (plenty of examples out there including in the mcrypt_encrypt comments).

By chaining the segments together you get a ciphertext indistinguishable from a single encrypt (test your code using this information). Decryption is identical, using the ciphertext as IV. To see how it works, look at the CBC encryption method:


Encryption &amp;lpar;large&amp;rpar; files in PHP with openSSL

EDIT: if possible you should use the OpenSSL equivalent functionality. That's not (well) documented, but you should be able to do the same using the code found in the link within the comment that Scott mentioned . Note that you should first perform everything without padding, and then for the final segment with padding .

Viewing all 6077 articles
Browse latest View live