Friday, 27 November 2020

php 8 New features


 PHP 8 is here! It was released on November 26, 2020. You can download it here. It's a new major version, which means that it will introduce some breaking changes, as well as lots of new features and performance improvements.

Because of the breaking changes, there's a higher chance you'll need to make some changes in your code to get it running on PHP 8. If you've kept up to date with the latest releases though, the upgrade shouldn't be too hard, since most breaking changes were deprecated before in the 7.* versions. And don't worry, all these deprecations are listed in this post.


Besides breaking changes, PHP 8 also brings a nice set of new features such as the JIT compiler, union types, attributes, and more.

New features

Let's start with all new features, it's quite a list!


 Union types RFC

Given the dynamically typed nature of PHP, there are lots of cases where union types can be useful. Union types are a collection of two or more types which indicate that either one of those can be used.

public function foo(Foo|Bar $input): int|float;

Note that void can never be part of a union type, since it indicates "no return value at all". Furthermore, nullable unions can be written using |null, or by using the existing ? notation:

public function foo(Foo|null $foo): void;

public function bar(?Bar $bar): void;

 JIT RFC

The JIT — just in time — compiler promises significant performance improvements, albeit not always within the context of web requests. I've done my own benchmarks on real-life web applications, and it seems like the JIT doesn't make that much of a difference, if any, on those kinds of PHP projects.

If you want to know more about what the JIT can do for PHP, you can read another post I wrote about it here.

The nullsafe operator RFC

If you're familiar with the null coalescing operator you're already familiar with its shortcomings: it doesn't work on method calls. Instead you need intermediate checks, or rely on optional helpers provided by some frameworks:

$startDate = $booking->getStartDate();

$dateAsString = $startDate ? $startDate->asDateTimeString() : null;

With the addition of the nullsafe operator, we can now have null coalescing-like behaviour on methods!

$dateAsString = $booking->getStartDate()?->asDateTimeString();

 Named arguments RFC

Named arguments allow you to pass in values to a function, by specifying the value name, so that you don't have to take their order into consideration, and you can also skip optional parameters!

function foo(string $a, string $b, ?string $c = null, ?string $d = null) 
{ /* … */ }

foo(
    b: 'value b', 
    a: 'value a', 
    d: 'value d',
);



 Attributes RFC

Attributes, commonly known as annotations in other languages, offers a way to add meta data to classes, without having to parse docblocks.

As for a quick look, here's an example of what attributes look like, from the RFC:

use App\Attributes\ExampleAttribute;

#[ExampleAttribute]
class Foo
{
    #[ExampleAttribute]
    public const FOO = 'foo';
 
    #[ExampleAttribute]
    public $x;
 
    #[ExampleAttribute]
    public function foo(#[ExampleAttribute] $bar) { }
}
#[Attribute]
class ExampleAttribute
{
    public $value;
 
    public function __construct($value)
    {
        $this->value = $value;
    }
}

Note that this base Attribute used to be called PhpAttribute in the original RFC, but was changed with another RFC afterwards. If you want to take a deep dive in how attributes work, and how you can build your own; you can read about attributes in depth on this blog.

Match expression RFC

You could call it the big brother of the switch expresion: match can return values, doesn't require break statements, can combine conditions, uses strict type comparisons and doesn't do any type coercion.

It looks like this:

$result = match($input) {
    0 => "hello",
    '1', '2', '3' => "world",
};



 Constructor property promotion RFC

This RFC adds syntactic sugar to create value objects or data transfer objects. Instead of specifying class properties and a constructor for them, PHP can now combine them into one.

Instead of doing this:

class Money 
{
    public Currency $currency;
 
    public int $amount;
 
    public function __construct(
        Currency $currency,
        int $amount,
    ) {
        $this->currency = $currency;
        $this->amount = $amount;
    }
}

You can now do this:

class Money 
{
    public function __construct(
        public Currency $currency,
        public int $amount,
    ) {}
}



 New static return type RFC

While it was already possible to return self, static wasn't a valid return type until PHP 8. Given PHP's dynamically typed nature, it's a feature that will be useful to many developers.

class Foo
{
    public function test(): static
    {
        return new static();
    }
}

New mixed type RFC

Some might call it a necessary evil: the mixed type causes many to have mixed feelings. There's a very good argument to make for it though: a missing type can mean lots of things in PHP:

  • A function returns nothing or null
  • We're expecting one of several types
  • We're expecting a type that can't be type hinted in PHP

Because of the reasons above, it's a good thing the mixed type is added. mixed itself means one of these types:

  • array
  • bool
  • callable
  • int
  • float
  • null
  • object
  • resource
  • string

Note that mixed can also be used as a parameter or property type, not just as a return type.

Also note that since mixed already includes null, it's not allowed to make it nullable. The following will trigger an error:

// Fatal error: Mixed types cannot be nullable, null is already part of the mixed type.
function bar(): ?mixed {}

Throw expression RFC

This RFC changes throw from being a statement to being an expression, which makes it possible to throw exception in many new places:

$triggerError = fn () => throw new MyError();

$foo = $bar['offset'] ?? throw new OffsetDoesNotExist('offset');

 Inheritance with private methods RFC

Previously, PHP used to apply the same inheritance checks on public, protected and private methods. In other words: private methods should follow the same method signature rules as protected and public methods. This doesn't make sense, since private methods won't be accessible by child classes.

This RFC changed that behaviour, so that these inheritance checks are not performed on private methods anymore. Furthermore, the use of final private function also didn't make sense, so doing so will now trigger a warning:

Warning: Private methods cannot be final as they are never overridden by other classes

Weak maps RFC

Built upon the weakrefs RFC that was added in PHP 7.4, a WeakMap implementation is added in PHP 8. WeakMap holds references to objects, which don't prevent those objects from being garbage collected.

Take the example of ORMs, they often implement caches which hold references to entity classes to improve the performance of relations between entities. These entity objects can not be garbage collected, as long as this cache has a reference to them, even if the cache is the only thing referencing them.

If this caching layer uses weak references and maps instead, PHP will garbage collect these objects when nothing else references them anymore. Especially in the case of ORMs, which can manage several hundreds, if not thousands of entities within a request; weak maps can offer a better, more resource friendly way of dealing with these objects.

Here's what weak maps look like, an example from the RFC:

class Foo 
{
    private WeakMap $cache;
 
    public function getSomethingWithCaching(object $obj): object
    {
        return $this->cache[$obj]
           ??= $this->computeSomethingExpensive($obj);
    }
}

 Allowing ::class on objects RFC

A small, yet useful, new feature: it's now possible to use ::class on objects, instead of having to use get_class() on them. It works the same way as get_class().

$foo = new Foo();

var_dump($foo::class);

Non-capturing catches RFC

Whenever you wanted to catch an exception before PHP 8, you had to store it in a variable, regardless whether you used that variable or not. With non-capturing catches, you can omit the variable, so instead of this:

try {
    // Something goes wrong
} catch (MySpecialException $exception) {
    Log::error("Something went wrong");
}

You can now do this:

try {
    // Something goes wrong
} catch (MySpecialException) {
    Log::error("Something went wrong");
}

Note that it's required to always specify the type, you're not allowed to have an empty catch. If you want to catch all exceptions and errors, you can use Throwable as the catching type.


Trailing comma in parameter lists RFC

Already possible when calling a function, trailing comma support was still lacking in parameter lists. It's now allowed in PHP 8, meaning you can do the following:

public function(
    string $parameterA,
    int $parameterB,
    Foo $objectfoo,
) {
    // …
}

As a sidenote: trailing commas are also supported in the use list of closures, this was an oversight and now added via a separate RFC.


Create DateTime objects from interface

You can already create a DateTime object from a DateTimeImmutable object using DateTime::createFromImmutable($immutableDateTime), but the other way around was tricky. By adding DateTime::createFromInterface() and DatetimeImmutable::createFromInterface() there's now a generalised way to convert DateTime and DateTimeImmutable objects to each other.

DateTime::createFromInterface(DateTimeInterface $other);

DateTimeImmutable::createFromInterface(DateTimeInterface $other);

 New Stringable interface RFC

The Stringable interface can be used to type hint anything that implements __toString(). Whenever a class implements __toString(), it automatically implements the interface behind the scenes and there's no need to manually implement it.

class Foo
{
    public function __toString(): string
    {
        return 'foo';
    }
}

function bar(string|Stringable $stringable) { /* … */ }

bar(new Foo());
bar('abc');

 New str_contains() function RFC

Some might say it's long overdue, but we finally don't have to rely on strpos() anymore to know whether a string contains another string.

Instead of doing this:

if (strpos('string with lots of words', 'words') !== false) { /* … */ }

You can now do this

if (str_contains('string with lots of words', 'words')) { /* … */ }

 New str_starts_with() and str_ends_with() functions RFC

Two other ones long overdue, these two functions are now added in the core.

str_starts_with('haystack', 'hay'); // true
str_ends_with('haystack', 'stack'); // true

 New fdiv() function PR

The new fdiv() function does something similar as the fmod() and intdiv() functions, which allows for division by 0. Instead of errors you'll get INF, -INF or NAN, depending on the case.


 New get_debug_type() function RFC

get_debug_type() returns the type of a variable. Sounds like something gettype() would do? get_debug_type() returns more useful output for arrays, strings, anonymous classes and objects.

For example, calling gettype() on a class \Foo\Bar would return object. Using get_debug_type() will return the class name.

A full list of differences between get_debug_type() and gettype() can be found in the RFC.


 New get_resource_id() function PR

Resources are special variables in PHP, referring to external resources. One example is a MySQL connection, another one a file handle.

Each one of those resources gets assigned an ID, though previously the only way to know that id was to cast the resource to int:

$resourceId = (int) $resource;

PHP 8 adds the get_resource_id() functions, making this operation more obvious and type-safe:

$resourceId = get_resource_id($resource);

 Abstract methods in traits improvements RFC

Traits can specify abstract methods which must be implemented by the classes using them. There's a caveat though: before PHP 8 the signature of these method implementations weren't validated. The following was valid:

trait Test {
    abstract public function test(int $input): int;
}

class UsesTrait
{
    use Test;

    public function test($input)
    {
        return $input;
    }
}

PHP 8 will perform proper method signature validation when using a trait and implementing its abstract methods. This means you'll need to write this instead:

class UsesTrait
{
    use Test;

    public function test(int $input): int
    {
        return $input;
    }
}

 Object implementation of token_get_all() RFC

The token_get_all() function returns an array of values. This RFC adds a PhpToken class with a PhpToken::tokenize() method. This implementation works with objects instead of plain values. It consumes less memory and is easier to read.


 Variable syntax tweaks RFC

From the RFC: "the Uniform Variable Syntax RFC resolved a number of inconsistencies in PHP's variable syntax. This RFC intends to address a small handful of cases that were overlooked."


 Type annotations for internal functions EXTERNALS

Lots of people pitched in to add proper type annotations to all internal functions. This was a long standing issue, and finally solvable with all the changes made to PHP in previous versions. This means that internal functions and methods will have complete type information in reflection.


 ext-json always available RFC

Previously it was possible to compile PHP without the JSON extension enabled, this is not possible anymore. Since JSON is so widely used, it's best developers can always rely on it being there, instead of having to ensure the extension exist first.

 Breaking changes

As mentioned before: this is a major update and thus there will be breaking changes. The best thing to do is take a look at the full list of breaking changes over at the UPGRADING document.

Many of these breaking changes have been deprecated in previous 7.* versions though, so if you've been staying up-to-date over the years, it shouldn't be all that hard to upgrade to PHP 8.


 Consistent type errors RFC

User-defined functions in PHP will already throw TypeError, but internal functions did not, they rather emitted warnings and returned null. As of PHP 8 the behaviour of internal functions have been made consistent.


Reclassified engine warnings RFC

Lots of errors that previously only triggered warnings or notices, have been converted to proper errors. The following warnings were changed.

  • Undefined variable: Error exception instead of notice
  • Undefined array index: warning instead of notice
  • Division by zero: DivisionByZeroError exception instead of warning
  • Attempt to increment/decrement property '%s' of non-object: Error exception instead of warning
  • Attempt to modify property '%s' of non-object: Error exception instead of warning
  • Attempt to assign property '%s' of non-object: Error exception instead of warning
  • Creating default object from empty value: Error exception instead of warning
  • Trying to get property '%s' of non-object: warning instead of notice
  • Undefined property: %s::$%s: warning instead of notice
  • Cannot add element to the array as the next element is already occupied: Error exception instead of warning
  • Cannot unset offset in a non-array variable: Error exception instead of warning
  • Cannot use a scalar value as an array: Error exception instead of warning
  • Only arrays and Traversables can be unpacked: TypeError exception instead of warning
  • Invalid argument supplied for foreach(): TypeError exception instead of warning
  • Illegal offset type: TypeError exception instead of warning
  • Illegal offset type in isset or empty: TypeError exception instead of warning
  • Illegal offset type in unset: TypeError exception instead of warning
  • Array to string conversion: warning instead of notice
  • Resource ID#%d used as offset, casting to integer (%d): warning instead of notice
  • String offset cast occurred: warning instead of notice
  • Uninitialized string offset: %d: warning instead of notice
  • Cannot assign an empty string to a string offset: Error exception instead of warning
  • Supplied resource is not a valid stream resource: TypeError exception instead of warning

 The @ operator no longer silences fatal errors

It's possible that this change might reveal errors that again were hidden before PHP 8. Make sure to set display_errors=Off on your production servers!


 Default error reporting level

It's now E_ALL instead of everything but E_NOTICE and E_DEPRECATED. This means that many errors might pop up which were previously silently ignored, though probably already existent before PHP 8.


 Default PDO error mode RFC

From the RFC: The current default error mode for PDO is silent. This means that when an SQL error occurs, no errors or warnings may be emitted and no exceptions thrown unless the developer implements their own explicit error handling.

This RFC changes the default error will change to PDO::ERRMODE_EXCEPTION in PHP 8.


 Concatenation precedence RFC

While already deprecated in PHP 7.4, this change is now taken into effect. If you'd write something like this:

echo "sum: " . $a + $b;

PHP would previously interpret it like this:

echo ("sum: " . $a) + $b;

PHP 8 will make it so that it's interpreted like this:

echo "sum: " . ($a + $b);

 Stricter type checks for arithmetic and bitwise operators RFC

Before PHP 8, it was possible to apply arithmetic or bitwise operators on arrays, resources or objects. This isn't possible anymore, and will throw a TypeError:

[] % [42];
$object + 4;

 Namespaced names being a single token RFC

PHP used to interpret each part of a namespace (separated by a backslash \) as a sequence of tokens. This RFC changed that behaviour, meaning reserved names can now be used in namespaces.


 Saner numeric strings RFC

PHP's type system tries to do a lot of smart things when it encounters numbers in strings. This RFC makes that behaviour more consistent and clear.


 Saner string to number comparisons RFC

This RFC fixes the very strange case in PHP where 0 == "foo" results in true. There are some other edge cases like that one, and this RFC fixes them.


 Reflection changes

A few reflection methods have been deprecated:

  • ReflectionFunction::isDisabled()
  • ReflectionParameter::getClass()
  • ReflectionParameter::isCallable()

You should now use ReflectionType to get information about a parameter's type:

$reflectionParameter->getType()->allowsNull();

If the type is a single type, ReflectionParameter::getType() returns an instance of ReflectionNamedType, which you can get its name from and whether it's built-in:

$reflectionParameter->getType()->getName();
$reflectionParameter->getType()->isBuiltin();

If the type is a union type however, you'll get an instance of ReflectionUnionType, which can give you an array of ReflectionNamedType like so:

$reflectionParameter->getType()->getTypes();

Checking whether a type is a union or not can be done with an instanceof check:

if ($reflectionParameter->getType() instanceof ReflectionNamedType) { 
    // It's a single type
}

if ($reflectionParameter->getType() instanceof ReflectionUnionType) {
    // It's a union type
}

Next up, three method signatures of reflection classes have been changed:

ReflectionClass::newInstance($args);
ReflectionFunction::invoke($args);
ReflectionMethod::invoke($object, $args);

Have now become:

ReflectionClass::newInstance(...$args);
ReflectionFunction::invoke(...$args);
ReflectionMethod::invoke($object, ...$args);

The upgrading guide specifies that if you extend these classes, and still want to support both PHP 7 and PHP 8, the following signatures are allowed:

ReflectionClass::newInstance($arg = null, ...$args);
ReflectionFunction::invoke($arg = null, ...$args);
ReflectionMethod::invoke($object, $arg = null, ...$args);

 

Stable sorting RFC

Before PHP 8, sorting algorithms were unstable. This means that the order of equal elements wasn't guaranteed. PHP 8 changes the behaviour of all sorting functions to stable sorting.


 Fatal error for incompatible method signatures RFC

From the RFC: Inheritance errors due to incompatible method signatures currently either throw a fatal error or a warning depending on the cause of the error and the inheritance hierarchy.


 Other deprecations and changes

During the PHP 7.* development, several deprecations were added that are now finalised in PHP 8.

Tuesday, 24 November 2020

How to add bootstrap 4/5 to Angular 10/9

 

We will see how to use Bootstrap to style apps built using Angular 10.

We'll see how to integrate Angular with Bootstrap, in various ways including using ng-bootstrap and ngx-bootstrap packages.

These are the steps of our tutorial:

  • Step 1 - Installing Angular CLI v10
  • Step 2 - Installing Bootstrap 4 in Your Angular 10 Project
  • Step 3 (Method 1) - Adding Bootstrap 4 to Angular 10 Using angular.json
  • Step 3 (Method 2) - Adding Bootstrap 4 to Angular 10 Using index.html
  • Step 3 (Method 3) - Adding Bootstrap 4 to Angular 10 Using styles.css
  • Alternative Step - Adding Bootstrap 4 Using ng-bootstrap and ngx-bootstrap

Step 1: Installing Angular CLI v10

$ npm install -g @angular/cli

After the installation, you'll have at your disposal the ng utility. Let's use it to generate a new Angular 10 project.

$ ng new angular-bootstrap-examples

You will be prompted for a couple of questions:

? Would you like to add Angular routing? Yes

? Which stylesheet format would you like to use? (Use arrow keys)

> CSS

  SCSS   [ https://sass-lang.com/documentation/syntax#scss                ]

  Sass   [ https://sass-lang.com/documentation/syntax#the-indented-syntax ]

  Less   [ http://lesscss.org                                             ]

  Stylus [ http://stylus-lang.com                                         ]

Most importantly, choose CSS as the stylesheet format because we'll use ths CSS version of Bootstrap in our tutorial.

The command will generate the directory structure and necessary files for the project and will install the required dependencies.

Next, navigate inside the root folder of your project

$ cd angular-bootstrap-examples

You can then serve your Angular 10 application using the ng serve command as follows:

$ ng serve

Step 2: Installing Bootstrap 4 in Your Angular 10 Project

In this step, we'll proceed to add Bootstrap 4 to our Angular 10 application.

There are various ways that you can use to install Bootstrap in your project:

Installing Bootstrap from npm using the npm install command,

Downloading Bootstrap files and adding them to the src/assets folder of your Angular project,

Using Bootstrap from a CDN.

Let's proceed with the first method. Go back to your command-line interface and install Bootstrap 4 via npm as follows:

 $ npm install --save bootstrap

This will also add the bootstrap package to package.json.

As the time of writing this tutorial, bootstrap v4.3.1 will be installed.

The Bootstrap 4 assets will be installed in the node_modules/bootstrap folder. You'll need to tell Angular where to look for them.

Next, you also need to install jQuery using the following command:

 $ npm install --save jquery

At the time of this tutorial jquery v3.4.1 will be installed.

Step 3:Adding Bootstrap 4 to Angular 10 Using angular.json

Open the angular.json file of your project and include:

{

  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",

  "version": 1, 

  "newProjectRoot": "projects",

  "projects": {

    "angular-bootstrap-examples": {

      "projectType": "application",

      "schematics": {},

      "root": "",

      "sourceRoot": "src",

      "prefix": "app",

      "architect": {

        "build": {

          "builder": "@angular-devkit/build-angular:browser",

          "options": {

            "outputPath": "dist/angular-bootstrap-examples",

            "index": "src/index.html",

            "main": "src/main.ts",

            "polyfills": "src/polyfills.ts",

            "tsConfig": "tsconfig.app.json",

            "aot": true,

            "assets": [

              "src/favicon.ico",

              "src/assets"

            ],

            "styles": [

              "./node_modules/bootstrap/dist/css/bootstrap.css",

              "src/styles.css"              

            ],

            "scripts": [

              "./node_modules/jquery/dist/jquery.js",

              "./node_modules/bootstrap/dist/js/bootstrap.js"

            ]

          },

Step 3: Adding Bootstrap 4 to Angular 10 Using index.html

You can also include Bootstrap files from node_modules/bootstrap using the index.html file.

<!doctype html>

<html lang="en">

<head>

  <meta charset="utf-8">

  <title>Angular Bootstrap 4 Examples</title>

  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">

  <link rel="icon" type="image/x-icon" href="favicon.ico">

  <link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.css">


</head>

<body>

  <app-root></app-root>

  <script src="../node_modules/jquery/dist/jquery.js"></script>

  <script src="../node_modules/bootstrap/dist/js/bootstrap.js"></script>    

</body>

</html>

Step 3: Adding Bootstrap 4 to Angular 10 Using styles.css

We can also use the styles.css file to add the CSS file of Bootstrap to our project.

Open the src/styles.css file of your Angular project and import the bootstrap.css file as follows:

@import "~bootstrap/dist/css/bootstrap.css"

Adding Bootstrap 4 Using ng-bootstrap and ngx-bootstrap

Bootstrap depends on jQuery and Popper.js libraries, and if you don't include them in your project, any Bootstrap components that rely on JavaScript will not work.

Why not include those libs? For Angular it's better to avoid using libraries that make direct manipulation of the DOM (like jQuery) and let Angular handle that.

Now what if you need the complete features of Bootstrap 4 without the JS libraries?

A better way is to use component libraries created for the sake of making Bootstrap work seamlessly with Angular such as ng-bootstrap or ngx-bootstrap

npm install --save @ng-bootstrap/ng-bootstrap

Next you'll need to add the module you imported in your app root module

import {NgbModule} from '@ng-bootstrap/ng-bootstrap';

@NgModule({

  declarations: [/*...*/],

  imports: [/*...*/, NgbModule.forRoot()],

  /*...*/

})

export class AppModule {

}

Please note that ng-bootstrap requires the Bootstrap 4 CSS file to be present.

You can add it in the styles array of the angular.json file like that:

"styles": [

  "styles.css",

  "../node_modules/bootstrap/dist/css/bootstrap.css"

],

Tuesday, 16 June 2020

create an npm package with a simple node.js module on ubuntu

Today I want to create a npm package for a simple javascriptlibrary with modules and some tests. Src:https://egghead.io/lessons/javascript-how-to-write-a-javascript-library-configuring-npm-and-creating-a-package-json

At first we need a git repository on github.

Create a repository named "starwarsNames"

Login into your github account and create a new repository "starwarsNames"

echo "# starwarsNames" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/pboethig/starwarsNames.git
git push -u origin master

create an account on https://www.npmjs.com, if you dont have one
You will need an account there to publish your extension. 

Remember your <npm-username> you will need it.

Install nodejs
$ apt-get install nodejs
$ sudo ln -s /usr/bin/nodejs /usr/bin/node  

Install npm, if npm is not installed 
$ apt-get install npm 


If you are on windows you have to install it manualy, If you are on mac, you can use the packagemanager,

At next we inititialize the npm project. 
$ npm set init-author-name 'Your Name'
$ npm set init-author-email 'your email'
$ npm set init-author-license 'MIT'
$ npm set save-exact true

If you want to check that config, you can do it with
$ cat ~/.npmrc

Add your npm user to your project 
$ npm adduser
Username: <your npm-username>
Password: <your npm-password>
Email: (this IS public) <your npm-email>

Initilize your npm project
$ npm init

this will ask some data from you, and puts outs the package.json for you

name: (starwars-names-<your npm username>)
version: (1.0.0)
license: (MIT)
About to write to /var/www/html/starwarsNames/package.json:

{
  "name": "starwars-names",
  "version": "1.0.0",
  "description": "get random starwars names",
  "main": "src/index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+ssh://git@github.com/pboethig/starwarsNames.git"
  },
  "keywords": [
    "random",
    "starwars"
  ],
  "author": "pboethig",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/pboethig/starwarsNames/issues"
  },
  "homepage": "https://github.com/pboethig/starwarsNames#readme"
}

Okay. Lets create our first module:
- create a folder "src" in your projectroot to store our module sources.
- now , create a file "index.js" in the new src folder

Open this new file in your code editor. I am using vscode for it. That editor  has great node.js plugins.

Now we want to define our modulestructure. 
Type following code in index.js

var starWarsNames = require('./starwars-names.json');
module.exports =
{
    all,
    random
};
             


 
This tells node that you want to store the "starwars-names.json" list in a variable, that your module will use and it exports 2 properties ("all" and "random")

At next save the starwarsnames in a file "starwars-names.json" in your "src" folder:
 
 
[
  "4-LOM",
  "Ayla Secura",
  "Admiral Ackbar",
  "Ahsoka Tano",
  "Anakin Solo",
  "Asajj Ventress",
  "Aurra Sing",
  "Senator Bail Organa",
  "Barris Offee",
  "Bastila Shan",
  "Ben Skywalker",
  "Bib Fortuna",
  "Boba Fett",
  "Bossk",
  "Brakiss",
  "C-3PO",
  "Cad Bane",
  "Cade Skywalker",
  "Callista Ming",
  "Captain Rex",
  "Carnor Jax",
  "Chewbacca",
  "Clone Commander Cody",
  "Count Dooku",
  "Darth Bane",
  "Darth Krayt",
  "Darth Malgus",
  "Darth Maul",
  "Darth Nihilus",
  "Darth Vader",
  "Dash Rendar",
  "Dengar",
  "Durge",
  "Emperor Palpatine",
  "Exar Kun",
  "Galen Marek",
  "General Crix Madine",
  "General Dodonna",
  "General Grievous",
  "General Veers",
  "Gilad Pellaeon",
  "Grand Moff Tarkin",
  "Greedo",
  "Han Solo",
  "IG 88",
  "Jabba The Hutt",
  "Jacen Solo",
  "Jaina Solo",
  "Jango Fett",
  "Jarael",
  "Jerec",
  "Joruus CBaoth",
  "Kent C. Dodds",
  "Ki-Adi-Mundi",
  "Kir Kanos",
  "Kit Fisto",
  "Kueller",
  "Kyle Katarn",
  "Kyp Durron",
  "Lando Calrissian",
  "Luke Skywalker",
  "Luminara Unduli",
  "Lumiya",
  "Mace Windu",
  "Mara Jade",
  "Mission Vao",
  "Natasi Daala",
  "Nom Anor",
  "Obi-Wan Kenobi",
  "Padmé Admidala",
  "Plo Koon",
  "Pre Vizsla",
  "Prince Xizor",
  "Princess Leia",
  "Proxy",
  "Qui-Gon Jinn",
  "Quinlan Vos",
  "R2-D2",
  "Rahm Kota",
  "Satele Shan",
  "Savage Opress",
  "Sebulba",
  "Shaak Ti",
  "Shmi Skywalker",
  "Talon Karrde",
  "Ulic Qel-Droma",
  "Visas Marr",
  "Watto",
  "Wedge Antilles",
  "Yoda",
  "Zam Wesell",
  "Zayne Carrick",
  "Zuckuss"
]

At next we need a further npm library called unique-random-array.
Lets install it with:

$ npm install --save unique-random-array

This will save the new library to our dependency definition in package.json

Now lets use the new array library in our index.js
 
var uniqueRandomArray = require('unique-random-array');
var starWarsNames = require('./starwars-names.json');
module.exports =
{
    all,
    random
};


Our index.js now looks like that

var uniqueRandomArray = require('unique-random-array');
var starWarsNames = require('./starwars-names.json');
module.exports =
{
    all: starWarsNames,
    random:uniqueRandomArray(starWarsNames)
};
Now that we have the library included, lets use it in our module.

In the export function, we want to reference all starwars-names to the property "all" and a random startwars-name to the property "random".

To to that we only have to export the local variable "starwarsNames" to the global scope by referencing the  exportproperty "all" and the array-function uniqueRandomArray(starwarsNames) from our new library to the export-property "random". Here is the code of "index.js".
Now our index.js looks like that 

 var uniqueRandomArray = require('unique-random-array');
var starWarsNames = require('./starwars-names.json');
module.exports =
{
    all: starWarsNames,
    random:uniqueRandomArray(starWarsNames)
};

Yeah, we havehacked our first node module.

Lets test it!
- open a terminal and navigate to the root folder of your app 
$ node
$ var starwarsNames = require('./src/index.js');
$ starwarsNames.all
$ starwarsNames.random()  

The single commands will output the whole list of names and a random name from the list. Thats realy great!


Now we want to publish it in npm as an own package. 
For that, we have to commit it to our git repository.

open a terminal:
$ cmd to your projectroot
$ touch .gitignore
$ nano .gitignore

add "node_modules" to your .gitignore to prevent commiting the node_modules.

$ git add *
$ git commit -m "init"
$ git push origin master

Thats it.

Now we can publish it to npm.
Thats realy simple.

Just type:
$ npm publish

That it. Now you should directly see your new package on npm !

This is awesome!

Now we want to test, if our module is directly usable via npm.
- open a terminal to the desktop 
$ npm install starwars-names-<your npm_user> 

Super. Now you can use your library, from anywhere in the world.
switch to the desktop and create a file named "test.js" with following content:

var starwarsNames = require('starwars-names-mittax');
console.log(starwarsNames.all);
console.log(starwarsNames.random());

Now run a terminal and cd to the directory where you have stored test.js and run:
$ node test.js

You will now see the results from your library.

This is realy cool!


Thanky to Kent.C.Dotts for the great video! 

Monday, 8 June 2020

Step to Create Your Own Blogger Template


I've always wanted to create my own Blogger template and tried so many times before but couldn't really get it right. I think I finally understood a somehow large chunk of it. I think.
Anyway, here in this post, I will note about the things I have learned/will learn in creating your own template. I won't be getting into much detailed stuff on HTML and CSS how to's. I'm assuming that you already have basic knowledge on these subjects and that you know your way around Blogger. Still, if you have any questions or there is something I didn't explain well, just feel free to leave a comment, and hopefully I can answer it.
Also, since I am also just learning about this, please don't expect a fully functional and Template-Designer-compatible template -- especially since I don't really use the Template Designer. However, I will try to make it as flexible as possible.
If you are to follow along the stuff I will note below, here are some suggested steps on getting started:
  1. Create a new blog for your test template, if you haven't got one yet and select a Simple template. It's best if everything is in its default state. This way, you can really see the changes you apply in your template. Also you wouldn't want to play around with your live blogs and unintentionally mess it up.
  2. Before making any changes, download a copy of the template (Template » Backup/Restore) for reference.
  3. For your test blog, in the Layout page, remove all widgets (Archive, Profile, Lists...) except for Blog Posts. If you can't get rid of the Header and Attribution widgets, edit the template (Template » Edit HTML) and search for Header1. On that line of code, change locked='true' to locked='false'. Do the same for the Attribution by searching Attribution1. Once done, go back to the Layout page and try deleting them. Hopefully that should work. UPDATE: Removing the widget in Blogger's HTML editor will also remove the widget from your template layout (unlike before). Yay!
  4. Once you remove all possible widgets, create a New Post. You can use default text templates found here at Html Ipsum. These templates already consists of HTML tags you would normally use in a blog post. Having a test post like this will be a big help in designing your template.
  5. Also, don't forget to set your test blog's privacy settings - Not listed on Blogger; Not visible to search engines. If you won't be using external apps for further testing, you can also set the permission (Blog readers) to Blog author instead of Anyone.
Stripped the Layout.
Fig.1 - Stripped the Layout.
Now onto the code and stuff. If you are editing your template's xml file in a different editor (like Notepad++) other than Blogger's, be sure to set its encoding to UTF-8 without BOM.

Understanding the <b:section> and <b:widget> tags

Must read: Intro, Section and Widget attributes. This page gives a brief explanation of the Section and Widget parts of the template. Also the attributes of the <b:section> and <b:widget> tags are listed here which we will use later on.
Blogger Template Sections and Widgets
Fig.2 - Just a quick summary minus the attributes.
So I made some tests and this is the leanest code I can upload to Blogger. This, by the way, is based on the Simple template - well at least the first 15 or so lines.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html>
<html b:version='2' class='v2' expr:dir='data:blog.languageDirection' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'>
<head>
  <meta content='IE=EmulateIE7' http-equiv='X-UA-Compatible'/>
  <b:if cond='data:blog.isMobile'>
    <meta content='width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0' name='viewport'/>
  <b:else/>
    <meta content='width=1100' name='viewport'/>
  </b:if>
  <b:include data='blog' name='all-head-content'/>
  <title><data:blog.pageTitle/></title>
  <b:skin>
  </b:skin>
</head>

<body>
  
  <b:section id='header' class='header' maxwidgets='' showaddelement='yes'>
  </b:section>

</body>
</html>
Fig. 3 - Simplest template code.
I tried leaving out the <b:skin/> tags but I get a
We were unable to save your template. Your template could not be parsed as it is not well-formed. Please make sure all XML elements are closed properly. XML error message: (SyntaxError) : Unexpected token <
UPDATE: The XML error message now says "There should be one and only one skin in the template, and we found: 0"
Also, the <body> cannot be left empty. It should always at least have a <b:section> tag. Otherwise you would encounter this error:
... XML error message: Could not find a preferred section to add deleted widgets to.
UPDATE: The XML error message now says "We did not find any section in your template. A template must have at least one b:section tag."
So after uploading the template (Fig.3), a quick preview shows me this:
Fig.4 - Template preview.
As seen on the Layout page (Fig.1) and on the preview (Fig.4), the Blog widget will always be set. So looking at the HTML code in Blogger (Template » Edit HTML), you will see that a <b:widget id='Blog1' locked='false' title='Blog Posts' type='Blog'/> has been inserted in between the <b:section> tag we created. Note that the id I used for this section is header. This I will change in a bit since I don't think we should leave the Blog widget inside this header section. UPDATE: If you uploaded the template in Fig.3, what you would actually see is an empty page because the Blog widget will no longer be automatically created. You have to add this yourself for you to view any post on the page.
Fig.5 - A Blog widget is automatically created in our template. Make sure to include the Blog widget so that you can view your blog posts. This is no longer automatically created.
Ok so now fixing the Blog widget's location. I created a new <b:section> tag, with an id main for the Blog widget and updated the attributes of the header section. So now we get this:

<body>
  
  <b:section id='header' class='header' maxwidgets='1' showaddelement='yes'>
  </b:section>

  <b:section id='main' class="main" maxwidgets='' showaddelements='yes'>
    <b:widget id='Blog1' locked='false' title='Blog Posts' type='Blog'/>
  </b:section>
  
</body>
Fig.6 - Added a new section for the Blog widget.
Fig.7 - New Layout after adding a new section.
Now that we have an Add a Gadget option for the header section in the Layout page, let's add a Page Header widget. Then on the Edit HTML part of the Template page, you will see the Page Header widget right below the <b:section id='header' ...> tag. Note: Just leave the Expand Widgets Templates unchecked. We won't be needing this just yet.
As a precaution to prevent deleting the Header when someday we are drowsily updating our blog template, set the header's locked attribute to true.
By now, you can probably see the pattern of Blogger's template code. We create sections in the template and specify its attributes. Then on the Layout page, we can add widgets (using Add a Gadget) to the section we have created. Note that we don't necessarily have to use Add a Gadget to add a widget to our template. You can do this manually by coding it in your template.
So for example, I would like to add an HTML/Javascript widget below my blog posts. So following this link mentioned earlier, we can see the syntax and attributes of a <b:widget> tag. I would then code my template like this:

<body>
  
  <b:section id='header' class='header' maxwidgets='1' showaddelement='yes'>
    <b:widget id='Header1' locked='true' title='Testground (Header)' type='Header'/>
  </b:section>

  <b:section id='main' class="main" maxwidgets='' showaddelements='yes'>
    <b:widget id='Blog1' locked='false' title='Blog Posts' type='Blog'/>
    <b:widget id='HTML1' locked='false' title='Test HTML widget' type='HTML' />
  </b:section>
  
</body>
Fig.8 - Manually adding an HTML/Javascript widget.
Then, checking the Layout page, we can see that my HTML/Javascript widget is right in its place.
Fig.9 - HTML/Javascript widget added using the <b:section>tag.
Deleting widgets, however, can't be removed by deleting it from the template code. You need to remove it via the Layout page itself (Edit » Remove). If the Remove option isn't visible on the Edit widget window, check that the widget's locked attribute is set to falseAs mentioned earlier, deleting widgets can also be done now in Blogger's HTML template editor.
Let's now move on to defining the rest of the Sections of our template. Normally, it should have a Header, Navbar, Content, Sidebar and Footer. We already have our Header and Content (main) so let me just add the missing ones.
So after adding the sections along with some widgets, I now have this:

<body>
  
  <b:section id='header' class='header' maxwidgets='1' showaddelement='yes'>
    <b:widget id='Header1' locked='true' title='Testground (Header)' type='Header'/>
  </b:section>
  
  <b:section id='nav' class='nav' maxwidgets='1' showaddelements='yes'>
    <b:widget id='PageList1' locked='false' title='Pages' type='PageList'/>
  </b:section>
  
  <b:section id='main' class='main' maxwidgets='' showaddelements='yes'>
    <b:widget id='Blog1' locked='false' title='Blog Posts' type='Blog'/>
  </b:section>
  
  <b:section id='sidebar' class='sidebar' maxwidgets='' showaddelements='yes'>
    <b:widget id='CustomSearch1' locked='false' title='Search' type='CustomSearch'/>
    <b:widget id='BlogArchive1' locked='false' title='Archive' type='BlogArchive'/>
  </b:section>
  
  <b:section id='footer' class='footer' maxwidgets='' showaddelements='yes'>
    <b:widget id='Attribution1' locked='false' title='' type='Attribution'/>
  </b:section>
  
</body>
Fig.9 - Template code with added sections and widgets.
Fig.10 - Layout page with added sections and widgets.
Fig.11 - Template preview.
Some notes:
  • For the <b:section id='nav' ... > tag, I tried using navbar as the id earlier but it wouldn't show up in the saved template and Layout page. It was because the id navbar is already in use. See the navbar widget on the Layout page? I should have noticed that earlier :|
  • Using an invalid id for the widget (e.g. Pagelist1 instead of PageList1) will generate an error.
  • I can't find a complete list of widget types so that I end up using Add a Gadget to install a widget (e.g. PageList, CutomSearch...) then edit its attributes on the template file. If anyone knows where to find one, I'd appreciate a holler..
  • There can be multiple instances of the same widget type. Just be sure to set a different id for each widget - [widgetType][number] (e.g. HTML1, HTML2)
  • I tried removing the title attribute from the PageList in the code but it still remained in the Layout until I removed it via the Gadget's settings.
  • If you are to use you a fluid layout for your blog instead of Blogger's mobile version, I suggest removing the entire <b:if cond='data:blog.isMobile'> block within the <head> tag and replacing it with <meta content='width=device-width,initial-scale=1.0' name='viewport'/> instead.
I think I finally got the Section and Widget basics covered. All you would need now is to style your template and fix the layout using CSS and I guess you would be good to go. For customizing certain areas on your template, I'll be writing separate blog posts for it. But if you want to jump right into customizing your widgets, here is another must-read.
So if you have any questions, don't hesitate to leave a comment and let's see if we can figure it out. Cheers!

Sunday, 9 June 2019

the recreation of thefacebook2004


Hi guys! I'm back with a new article  the recreation of thefacebook2004Thefacebook Clone is nothing more than an attempt to recreate the first version of Facebook was launched in 2003/2004 ,This project aims to be an advanced , lightweight and free clone, being written with PHP , HTML , CSS and with MySQL as data storage. we will discuss about Facebook is a social networking service launched as FaceMash in July 2003, but later changing to TheFacebook on February 4, 2004It was founded by Mark Zuckerberg with his college roommate and fellow Harvard University student Eduardo Saverin. The website's membership was initially limited by the founders to Harvard students, but was expanded to other colleges in the Boston area, the Ivy Leagueand gradually most universities in the United States and Canada,corporationsand by September 2006, to everyone with a valid email address along with an age requirement of being 13 and older

TheFacebook Clone
- Version : 1.0 

Files

index.php

terms.php

privacy.php

contact.php

social_net.php

search.php

profile.php

about.php

register.php

login.php

messages.php

read_message.php

send_message.php

edit_profile.php

edit_privacy.php

edit_account.php

edit_photo.php

my_friends.php

home.php

invite.php

faq.php

logout.php

Images

The recreation of the html, is being based only in images found on the internet.






 















 Hope this post will help you . If you enjoy my work then please share my posts with your buddies and anyone who might be interested in thefacebook2004

                                           coming soon  on Udemy