Skip to content

Latest commit

 

History

History
344 lines (280 loc) · 12.6 KB

File metadata and controls

344 lines (280 loc) · 12.6 KB

Annotations (plain php):

  1. Annotations are not supported natively by php but can be installed by running composer require doctrine/annotations in the project directory. (See lesson 13)
  2. Create a new symfony project, run composer create-project symfony/skeleton projectName, the command will create a project with the given projectName within the current directory.

Example of creating a (new Symfony) project:

  1. cd into D:user/userName/projects or any other directory.
  2. run composer create-project symfony/skeleton projectName.
  3. A project named projectName will be created in D:user/userName/projects.
  4. After the project was generated, run php -S 127.0.0.1:8000 -t public/ to run the web development server.
  5. Additionally, for starting/stopping the development server the following commands can be run: symfony server:start and symfony server:stop.

Annotations (Symfony):

  • Not present by default, i.e. using the skeleton project, but they can be installed using composer require annotations.
  • Sometimes for new changes to take place, it is necessary to clear the development cache, run php bin/console cache:clear.

API Routes:

  • All available routes can be listed by running php bin/console debug:router.

ORM:

  • To install ORM (doctrine), run composer require symfony/orm-pack.
  • Install maker (scaffolding for the database), run composer require symfony/maker-bundle --dev.
  • To generate an entity, run php bin/console make:entity.
  • Whilst generating entities, ? will provide a list of all available types.
  • After generating the entity(ies), run php bin/console make:migration to create the database migrations.
  • To execute the migrations to the target database, run php bin/console doctrine:migrations:migrate.
  • To change an existing entity, add/remove the field(s) desired and run php bin/console make:migration, then run User.
  • After adding entity relations 1..*, *..* etc.. before executing the migrations, delete all tables within the database and previous migrations, otherwise errors will occur.

Serializer:

  • Install with composer require serializer.
  • Allows serialization/deserialization.

Fixture Bundles (fake data for testing, aka "Seeding"):

  • docs.: https://symfony.com/bundles/DoctrineFixturesBundle/current/index.html
  • Installation, run composer require --dev doctrine/doctrine-fixtures-bundle.
  • After installation, a class named AppFixtures will be found in src/DataFixtures, within it, test objects can be created. After those are created, run php bin/console doctrine:fixtures:load , type y or yes to load the data into the database. Note that the database records previous to the load will be erased ("purged").

EasyAdmin:

API platform:

  • Install using composer require api. (installs api platform and CORS bundle)
  • Each of the API Platform routes is called "an operation".
  • collectionOperations are for manipulating lists of items whilst itemOperations are for manipulating individual items (CRUD on 1 resource).
  • Regardless of single item manipulation or collection manipulation, specific operations can be enabled/disabled from the defaults provided by API Platform through using annotations on the resource class:
  • There property normalizationContext allows for custom serialization/deserialization contexts (https://api-platform.com/docs/core/serialization/). If no serialization/deserialization group (https://api-platform.com/docs/core/serialization/#using-serialization-groups) is provided, the "default" group is used.
  • Available api routes can be accessed using php bin/console debug:router.
Example:
/**
 * @ApiResource(
 *     itemOperations={"get"},
 *     collectionOperations={"get"}
 * )
 */
 class BlogPost {}

Security:

Faker:

Serialization & Deserialization:

    (PHP) Object (Ex.: Array)                Specified format (JSON,XML)
            |___ 1)Normalize                        |
                       |_________ 2)Encode__________|
            
            |_________SERIALIZATION PROC.___________| 
            
      Specified format (JSON,XML)           (PHP) Object (Ex.: Array)
            |___ 1)Decode                           |
                       |_____ 2)Denormalize_________|
            
            |_________DESERIALIZATION PROC._________| 

Example of Serialization

class User {
    private $id;
    private $name;
    private $fullName;
}    
        ||
        || --- by normalizing, we mean encoding the class data into an
        ||     associative array/map.
        \/
        
    $normalizedUser = [
        'id' => 1,
        'name' => 'eduard_f',
        'fullName' => 'Eduard F.'
    ];
        
        ||
        ||
        ||
        \/
        
    JSON (Serialization):
    {
        "id":1,
        "name":"eduard_f",
        "fullName":"Eduard F."
    }

Example of Deserialization

    JSON object:
        {
            "id":1,
            "name":"eduard_f",
            "fullName":"Eduard F."
        }
        
        ||
        ||  --- Decode (convert to ass. array)
        ||
        \/
        
    $denormalizedUser = [
        'id' => 1,
        'name' => 'eduard_f',
        'fullName' => 'Eduard F.'
    ];   
    
         ||
         ||  --- Denormalization (convert to obj.)
         ||
         \/
         
    class User {
        private $id;
        private $name;
        private $fullName;
    }       

Serialization groups

Adding services

  • After implementing a new service, it will be autowired and configured within the application by Symfony itself, example run php bin/console debug:container PasswordHashSubscriber to verify the service's properties.

Validation

  • Symfony's validation component allows parameter validation on certain constraints.
  • Flow : API Platform --> deserialize data --> call the validator component for validation on the data.
  • Import (with "Assert" alias):
use Symfony\Component\Validator\Constraints as Assert;
  • Example usage:
     * @Assert\NotBlank()               --->    assert that the property is not blank in the request object
     * @Assert\Length(min=6, max=255)   --->    assert that the length is in [6,255]
     */
    private $username;
    
     * @Assert\NotBlank()
     * @Assert\Email()                  --->    assert that the property is a valid email address email@email.org
     */
    private $email;

Regex

  • Need to be surrounded with "/". Example:
(?=.*[A-Z])     (?=.*[a-z])     (?=.*[0-9])     .{7,}
    |               |               |             |_ match on an input/text length of [7,inf)  
    |               |               |_ match against numbers
    |               |_ match against lower case letters
    |_ match against upper case letters

Uniqueness of fields

  • Can be specified as combinations (set) of fields that have to be unique by adding @UniqueEntity(fields={"field1", "field2", "fieldN"}). With this strategy, the set will be validated (checked) against existing records for uniqueness, however if one of the fields is duplicate it will not matter as the entire set is evaluated as a whole rather than individual fields.
  • Or as individual fields by adding several statements of the form @UniqueEntity("field1"), @UniqueEntity("field2") , @UniqueEntity("fieldN"). With this strategy, each field will be validated (checked) against existing records for uniqueness.
  • The latter is preferred.

JWT Tokens (Authentication)

  • Resources:

  • https://www.vaadata.com/blog/jwt-tokens-and-security-working-principles-and-use-cases/

  • https://jwt.io/introduction

  • The user (via the client) sends his credentials and then receives an authentication token (given the credentials are valid).

  • The authentication token is generated automatically as JSON (server).

  • Any subsequent request (client) will include in its headers the JWT and if the JWT is valid, access is granted.

  • Tokens are not encrypted, just encoded (can be read/modified by 3rd parties).

  • 3rd parties cannot sign the token without the public/private key pair.

  • Inside the payload of a JWT the following can be added (safely):

    • user identifier
    • token expiration date
    • token issue date
  • What should be excluded (unsafe):

    • user personal data (email, etc...)
    • credit card numbers
    • user passwords
  • Structure (Anatomy of a JWT):

JWT Token
    |------->   Header
    |           {
    |            "alg": "H256",
    |            "typ": "JWT         
    |           }
    |
    |------->   Payload
                {
                  "sub":"1234567890",
                  "name":"Karl Doe",
                  "iat": 1516239022
                }
  • The signature is done on the Header object as a Public/Private Key pair.
|-----------|               
| Signature | ==========> |---------|
|-----------|             | Header  |
Public/Private            |---------|
  Key pair                | Payload |
                          |---------|
Base64Url(Header) Base64Url(Payload)
Base64Url(Header) Base64Url(Payload)
Signature
Example: See the section "Putting all together"
  • Installation of lexik (library for JWT generation):
composer require lexik/jwt-authentication-bundle # might require check after initial installation
  • If not installed, OpenSSL can be installed by following the instructions specified in this installation guide.
  • Once installed, OpenSSL can be used to generate a private key:
openssl genrsa -out config/jwt/private.pem -aes256 4096 
  • The output (private key) will be found in config/jwt/private.pem, the encryption uses the AES-256 encryption algorithm.
  • From the private key, using the RSA algorithm, the public key is generated using openssl rsa -pubout -in config/jwt/private.pem -out config/jwt/public.pem (the output, public key will be found in config/jwt/public.pem).

Adding user roles

  • After adding user roles (within the user entity), the database tables need to be dropped and the sequence for reinitializing the tables is:
    • Make the migrations, run php bin/console make:migration.
    • Execute the migrations, run php bin/console doctrine:migrations:migrate.
    • Load the fixtures' data, run php bin/console doctrine:fixtures:load.
  • By adding an initializer within the User entity's constructor, we automatically set any given role on the entity.

Swift mail

  • Install by running composer require symfony/swiftmailer-bundle. Usage:
$message = (new \Swift_Message('Please confirm your account!'))
            ->setFrom('api-platform@gmail.com')
            ->setTo($user->getEmail())
            ->setBody($body, 'text/html');

        $this->mailer->send($message);

Vich, image upload

  • Install by running composer require vich/uploader-bundle.