Reto - Ejercicio

18/19

Lectura

Practicar es muy importante, ya que te permitir谩 pulir tus habilidades de desarrollo y te animo a que realices el siguiente reto con todo lo que has aprendido.


Crea un ejemplo que ilustre la configuraci贸n de un post o art铆culo de un blog. Entendemos que este tipo de soluciones requieren un autor (quien crea el post) y el post (pieza de contenido creada por un autor). Este post tendr谩 categor铆as para segmentarlos y hacer un f谩cil filtrado.

驴Qu茅 necesitas?

  1. User: clase base para los autores.
  2. Author: hereda de User y es quien crear谩 a los post o art铆culos.
  3. Post: clase protagonista, es quien servir谩 para dar vida al objetivo principal de un blog.
  4. Category: clase que servir谩 para segmentar a nuestros art铆culos. Es un campo m谩s de los art铆culos y permitir谩 por ejemplo que un art铆culo sea de PHP, Vue.js, JavaScript, etc.

No hay una 煤nica soluci贸n ni una soluci贸n correcta, el objetivo es pensar, practicar y entender poco a poco c贸mo funciona esta nueva forma de construir proyectos.

User.php


  
class User 
{
    # Code ...
}

Author.php


  
class Author extends User 
{
    # Code ...
}

Post.php


  
class Post 
{
    # Code ...
}

Category.php


  
class Category
{
    # Code ...
}

Finalmente index.php.

Desarrolla todos estos archivos, pon en pr谩ctica lo aprendido.
Comp谩rteme tus resultados en los comentarios y que m谩s a帽adir铆as.

Aportes 20

Preguntas 0

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesi贸n.

Esta es mi soluci贸n al reto, agradecer铆a cualquier feedback que me puedan dar:

Aqu铆 est谩 el c贸digo: https://github.com/weoka/Poster

Listo!

Mi estructura de archivos es:

+ Blog: {

    +src: {
        -Author.php
        -Category.php
        -Post.php
        -User.php
    }

    +vendor: { ... }

    -composer.json
    -composer.lock
    -index.php

}

composer.json:

{
    "name": "retaxmaster/post",
    "description": "Proyeto de OOP",
    "autoload": {
        "psr-4": {
            "Blog\\": "src/"
        }
    }
}

Author.php:

<?php

namespace Blog;

class Author extends User {

    protected $created_posts;
    protected $posts = [];

    public function create_post(Post $post) {
        $this->posts[] = $post;
    }

    public function get_postst() : array {
        return $this->posts;
    }

}

?>

Category.php:

<?php

namespace Blog;

class Category {

    protected $name;

    public function set_name(string $name) {
        $this->name = $name;
    }

    public function get_name() : string {
        return $this->name;
    }

}

?>

Post.php:

<?php

namespace Blog;

class Post {

    protected $title;
    protected $content;
    protected $category;

    public function add_category(Category $category) {
        $this->category = $category;
    }

    public function add_title(string $title) {
        $this->title = $title;
    }

    public function add_content(string $content) {
        $this->content = $content;
    }

    public function get_post() : string {
        return "<strong>T铆tulo:</strong> $this->title <br> <strong>Contenido:</strong> $this->content <br> <strong>Categor铆a:</strong> {$this->category->get_name()}";
    }

}

?>

User.php:

<?php

namespace Blog;

class User {

    protected $name;
    protected $last_name;

    public function set_name(string $name, string $last_name) {
        $this->name = $name;
        $this->last_name = $last_name;
    }

    public function get_full_name() : string {
        return $this->name . " " . $this->last_name;
    }

}

?>

index.php:

<?php

include __DIR__ . "/vendor/autoload.php";

use Blog\Author;
use Blog\Category;
use Blog\Post;

// Primero creo las categor铆as

// Categor铆a PHP
$php_category = new Category();
$php_category->set_name("PHP");

// Categor铆a VueJS
$vue_category = new Category();
$vue_category->set_name("VueJS");

// Ahora creo al autor
$retaxmaster = new Author();
$retaxmaster->set_name("Carlos", "G贸mez");

// Ahora creo un post sobre PHP
$php_functions_post = new Post();
$php_functions_post->add_title("Post para hablar acerca de funciones en PHP");
$php_functions_post->add_content("En este post hablaremos sobre c贸mo funcionan las funciones en PHP");
$php_functions_post->add_category($php_category);

// Ahora creo un post sobre VueJS
$vue_app_post = new Post();
$vue_app_post->add_title("Post sobre c贸mo crear una app con VueJS");
$vue_app_post->add_content("En este post hablaremos sobre qu茅 necesitamos para crear una app con VueJS");
$vue_app_post->add_category($vue_category);

// Ahora le asigno los posts al autor
$retaxmaster->create_post($php_functions_post);
$retaxmaster->create_post($vue_app_post);

// Y por 煤ltimo listamos los posts
$author_post = $retaxmaster->get_postst();

foreach ($author_post as $post) {
    
    echo "El usuario {$retaxmaster->get_full_name()} tiene el siguiente post: <br><br>";
    echo $post->get_post();
    echo "<br><br><br>";

}

?>

It works 馃槃!

Excelente curso 鉂わ笍

Clase User:

<?php

namespace App;

class User
{
    private $name;
    private $email;
    private $password;

    public function setName($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }

    public function getEmail()
    {
        return $this->email;
    }

    public function setPassword($password)
    {
        $this->password = $password;
    }
}

Clase Author:

<?php

namespace App;
use App\Post;
use App\Category;

class Author extends User
{
    private $posts = [];

    public function setPost(Post $post)
    {
        $this->posts[] = $post;
    }

    public function getPost()
    {
        return $this->posts;
    }

    public function addPost($post)
    {
        array_push($this->posts, $post);
    }

    public function countPosts()
    {
        return count($this->posts);
    }
}

Clase Post:

<?php

namespace App;

class Post
{
    private $title;
    private $content;
    private $category = [];

    public function __construct ($title, $content, Category $category)
    {
        $this->title        = $title;
        $this->content      = $content;
        $this->setCategory($category);
    }

    public function setTitle($title)
    {
        $this->title = $title;
    }

    public function getTitle()
    {
        return $this->title;
    }

    public function setContent($content)
    {
        $this->content = $content;
    }

    public function getContent()
    {
        return $this->content;
    }

    public function setCategory(Category $category)
    {
        array_push($this->category, $category);
    }

    public function getCategory()
    {
        return $this->category;
    }
}

Clase Category:

<?php

namespace App;

class Category
{
    private $name;

    public function __construct($name)
    {
        $this->name = $name;
    }
}

Clase PostTest:

<?php

use PHPUnit\Framework\TestCase;
use App\Author;
use App\Category;
use App\Post;

class PostTest extends TestCase
{
    public function test_post()
    {
        // Creamos un usuario
        $author = new Author();
        // Crear categor铆a
        $category = new Category("PHP");
        // Crear post
        $post = new Post("T铆tulo", "Contenido", $category);
        // Agregar post al autor
        $author->addPost($post);

        // Aserci贸n o afirmaci贸n para comprobar que tenemos 1 post agregado
        $this->assertEquals(1, $author->countPosts());
        // Aserci贸n o afirmaci贸n para comprobar que la categor铆a es una instancia de la clase Category
        $this->assertInstanceOf(Category::class, $post->getCategory()[0]);
    }
}

index.php

<?php

require_once "vendor/autoload.php";
use App\Author;
use App\Post;
use App\Category;

// Crear un autor:
$author = new Author();
$author->setName("Carlos Betancourt");
$author->setEmail("[email protected]");
$author->setPassword("mypassword");

// Crear categor铆as:
$categoryPHP    = new Category("PHP");
$categoryJava   = new Category("Java");
$categoryHTML   = new Category("HTML");

// Crear tres post
$postOne    = new Post("Primer Post","Contenido del primer post.", $categoryPHP, $author);
$postTwo    = new Post("Segundo Post","Contenido del segundo post.", $categoryJava, $author);
$postThree  = new Post("Tercer Post","Contenido del tercer post.", $categoryHTML, $author);

// Agregar otras categor铆as a cada post
$postOne->setCategory($categoryJava);
$postThree->setCategory($categoryJava);

// Agregar posts al author
$author->addPost($postOne);
$author->addPost($postTwo);

echo "<pre>";
var_dump($author);

Es bienvenido el feedback, saludos!!!

Estructure

Author

Category

Post

User

Test

As铆 qued贸 mi proyecto

User.php

<?php

namespace App;

class User
{
    public $nombre;
    protected $password;

    public function __construct($nombre, $password = 'defaultPassword')
    {
        $this->nombre = $nombre;
        $this->password = $password;
    }
}

Author.php

<?php 

namespace App;

class Author extends User
{
    public $amount_of_posts = 0;

    public function addAmountOfPost()
    {
        $this->amount_of_posts = $this->getAmountOfPost() + 1;
    }

    public function getAmountOfPost()
    {
        return $this->amount_of_posts;
    }
}

Comment.php

<?php

namespace App;

class Comment
{
    protected $likes;
    protected $comment;

    public function __construct($comment)
    {
        $this->comment = $comment;
        $this->likes = 0;
    }
}

Category.php

<?php

namespace App;

class Category
{
    public $name;

    public function __construct($name)
    {
        $this->name = $name;
    }
}

Post.php

<?php

namespace App;

class Post
{
    protected $comments = [];
    protected $author;
    protected $category;
    protected $title;
    protected $content;
    protected $views = 0;
    protected $tags = [];

    public function addComment(Comment $comment)
    {
        $this->comments[] = $comment;
    }

    public function countComments()
    {
        return count($this->comments);
    }

    public function getComments()
    {
        return $this->comments;
    }

    public function addAuthor(Author $author)
    {
        $this->author = $author;
        $author->addAmountOfPost();
    }

    public function getAuthor()
    {
        return $this->author;
    }

    public function addCategoty(Category $category)
    {
        $this->category = $category;
    }

    public function getCategory()
    {
        return $this->category;
    }

    public function addTittle($title)
    {
        $this->title = $title;
    }

    public function addContent($content)
    {
        $this->content = $content;
    }

    public function getViews()
    {
        return $this->views;
    }

    public function addView()
    {
        $this->views = $this->getViews() + 1;
    }

    public function addTag($tag)
    {
        $this->tags[] = $tag;
    }

    public function countTags()
    {
        return count($this->tags);
    }

    public function getTags()
    {
        return $this->tags;
    }
}

index.php

<?php

require __DIR__ . '/vendor/autoload.php';

use App\Author;
use App\Category;
use App\Comment;
use App\Post;

$author = new Author("Gustavo");
$category = new Category("PHP");
$post = new Post();
$comment = new Comment("Muy bueno, gracias");

$post->addComment($comment);
$post->addAuthor($author);
$post->addCategoty($category);
$post->addTittle("Introducci贸n a PHP");
$post->addContent("PHP es un lenguaje de programaci贸n Orientado a Objetos");
$post->addView();
$post->addTag("Programaci贸n");
$post->addTag("Backend");

echo '<pre>';
echo var_dump($post);
echo '</pre>';

El reto esta genial, lo solucione a mi manera y conforme lo que llegue a aprender en los cursos que fue bastante. Reconozco que me falta mucho por mejorar y aprender. Les comparto mi repositorio con el reto y les prometo que volver茅 para resolver toda la deuda t茅cnica que deje en el reto. Saludos.

https://github.com/albertusortiz/reto_poo_php/tree/master

Reto Completado ;D

Estructura de carpetas y archivos

Author.php


User.php

Category.php

Comment.php

Post.php


Super!, a practicar lo aprendido

Ahora vamos por el examen 鈥

Comparto mi soluci贸n al reto:

Estructura de archivos

Post.php

namespace App;

class Post 
{
    protected $comments = [];
    protected $title;
    protected $description;

    public function __construct (string $title, string $description)
    {
        $this->title = $title;
        $this->description = $description;
    }

    public function addComment(Comment $comment)
    {
        $this->comments[] = $comment;
    }

    public function countComments()
    {
        return count($this->comments);
    }

    public function getComments()
    {
        return $this->comments;
    }

    public function getTitle()
    {
        return $this->title;
    }

    public function getDescription()
    {
        return $this->description;
    }
}

Category.php

namespace App;

class Category
{
    private $name;

    public function __construct (string $name)
    {
        $this->name = $name;
    }

    public function getName ()
    {
        return $this->name;
    }
}

User.php

namespace App;

class User
{
    protected $firstName;
    protected $lastName;

    public function __construct(string $firstName, string $lastName)
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public function getFirstName ()
    {
        return $this->firstName;
    }

    public function getLastName ()
    {
        return $this->lastName;
    }
}

Author.php

namespace App;

class Author extends User
{
   protected $createdPosts = [];

   public function writePost (Post $post)
   {
        array_push($this->createdPosts, $post);
   }

   public function countCreatedPosts ()
   {
      return count($this->createdPosts);
   }

   public function getCreatedPosts ()
   {
      return $this->createdPosts;
   }
}

index.php

<?php
include './vendor/autoload.php';

use App\Author;
use App\Category;
use App\Post;

// Creo al autor del post
$author = new Author('Nestor', 'Velasquez');

// Creo una categor铆a de ciencias
$scienceCategory = new Category('Ciencias');

// Creo una categor铆a de Programaci贸n
$programmingCategory = new Category('Programacion');

// Creo un primer post
$firstPost = new Post('Las ciencias de la vida', 'La vida es una cienca y la ciencia es una vida... Eres lo que vives, somos ellos, somos aquellos, somos los hombres de negro');

// Creo otro post
$secondPost = new Post('C贸mo ser un hacker con Python', 'Para ser un hacker en python tienes que ser un crack en python primero... asi como yo que soy un super crack');

// Mensaje de bienvenida al usuario autor
echo "<h2>Bienvenido {$author->getFirstName()} {$author->getLastName()}</h2>";

// Le asigno un autor a los post creados
$author->writePost($firstPost);
$author->writePost($secondPost);

echo "<p>Has creado hasta ahora {$author->countCreatedPosts()} Posts</p>";

echo "<p>Tus Posts creados son: </p>";

echo "<table>";
    for ($i=0; $i < $author->countCreatedPosts(); $i++) {
        echo "<tr>";
        echo "<td><h4>{$author->getCreatedPosts()[$i]->getTitle()}</h4>
                    <p>{$author->getCreatedPosts()[$i]->getDescription()}</p>
            </td>";
        echo "</tr>";
    }

Comparto mi soluci贸n

Estructura de Carpetas

User.php

<?php

namespace App;

class User {
    protected $name;
    public function __construct($name)
    {
        $this->name = $name;
    }
}

Author.php

<?php 
namespace App;

use App\User;

class Author extends User 
{

}

Category.php

<?php
namespace App; 

class Category 
{
    protected $name;
    
    public function __construct($name)
    {  
        $this->name = $name;
    }
}

Comment.php

<?php 

namespace App;

class Comment 
{
    
}

Post.php

<?php

namespace App;

class Post 
{
    protected $comments = [];
    public $author;
    public $category;

    public function addComment(Comment $comment){
        $this->comments[] = $comment;
    }

    public function countComments(){
        return count($this->comments);
    }

    public function getComments(){
        return $this->comments;
    }
}

PostTest.php

<?php 
use PHPUnit\Framework\TestCase;
use App\Author;
use App\Post;
use App\Category;

class PostTest extends TestCase
{
    public function test_create_post(){
        $author = new Author('Francisco');
        $category = new Category('PHP');
        $post = new Post();
        $post->author = $author;
        $post->category = $category;        
        
        $this->assertInstanceOf(Author::class, $author);
        $this->assertInstanceOf(Category::class, $category);
        $this->assertInstanceOf(Post::class, $post);
        $this->assertClassHasAttribute('author', Post::class);
        $this->assertClassHasAttribute('category', Post::class);
        $this->assertInstanceOf(Author::class, $post->author);
        $this->assertInstanceOf(Category::class, $post->category);
    }
}

index.php

<?php
include './vendor/autoload.php';

use App\Post;
use App\Author;
use App\Category;

$author = new Author('Francisco');
$category = new Category('PHPUnit');
$post = new Post();
$post->author = $author;
$post->category = $category;

print_r($post);

Excelente practica.

La clase User la declare como abstracta para que no sea instanciada sino solo heredada.

<?php

namespace Reto;

abstract class User
{
    protected $name, $last_name;

    public function __construct($name, $last_name)
    {
        $this->name = $name;
        $this->last_name = $last_name;
    }

    abstract public function getInfo();
}

Las Clase Author utiliza el constructor del padre pero implemente el propio para agregar otra informaci贸n.

<?php

namespace Reto;

class Author extends User
{
    protected $type;
    protected $posts = array();

    public function __construct($name, $last_name)
    {
        parent::__construct($name, $last_name);
        $this->type = 'Author';
    }

    public function getInfo() :string
    {
        return "Hello {$this->name} {$this->last_name}, i hope you are very well today. Author type: {$this->type}";
    }

    public function addPost(Post $post)
    {
        $this->posts[] = $post;
    }

    public function getPost() :array
    {
        return $this->posts;
    }
}

My clase post

<?php

namespace Reto;

class Post
{
    public $title, $description, $category, $author;

    public function __construct(Category $category)
    {
        $this->category = $category;
    }

    public function addTitle($title)
    {
        $this->title = $title;
    }

    public function addDescription($description)
    {
        $this->description = $description;
    }

    public function hasTitle() :bool
    {
        return isset($this->title);
    }

    public function hasDescription() :bool
    {
        return isset($this->description);
    }

    public function getCategory()
    {
        return $this->category;
    }
}

Clase Categor铆a

<?php

namespace Reto;

class Category
{
    protected $nameCategory;

    public function __construct($name)
    {
        $this->nameCategory = $name;
    }
}

Las pruebas:

<?php

use PHPUnit\Framework\TestCase;
use Reto\User;
use Reto\Author;
use Reto\Category;
use Reto\Post;

class PostTest extends TestCase
{
    public function test_post()
    {
        $author = new Author('Fabian', 'Beltran');
        $category = new Category('PHPUnit');
        $post = new Post($category);
        $post->addTitle('Testing whit PHPUnit');
        $post->addDescription(" It's necesary that you put the information here ");
        $author->addPost($post);

        $this->assertEquals(1, $post->hasTitle());
        $this->assertEquals(1, $post->hasDescription());
        $this->assertInstanceOf(Category::class, $post->getCategory());
        $this->assertInstanceOf(Post::class, $author->getPost()[0]);

    }
}

Buenas! Dejo el repositorio en el cual desarroll茅 el reto, saludos!

resultado

composer.json

{
    "name": "slasher/project",
    "description": "just a simple project",
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },
    "require-dev": {
        "phpunit/phpunit": "^9.5"
    }
}

AuthorTest

<?php

use PHPUnit\Framework\TestCase;
use App\Author;

class AuthorTest extends TestCase
{
    public function test_add_author()
    {
        $author = new Author('197O00045', 'Alexis','Vazquez','Morales', true);

        $this->assertInstanceOf(Author::class, $author);
    }
}

CategoryTest

<?php

use PHPUnit\Framework\TestCase;
use App\Category;

class CategoryTest extends TestCase
{
    public function test_add_category()
    {
        $cateogry = new Category('1','PHP');

        $this->assertInstanceOf(Category::class, $cateogry);
    }
}

PostTest

<?php

use PHPUnit\Framework\TestCase;
use App\Post;

class PostTest extends TestCase
{
    public function test_add_post()
    {
        $post = new Post(1, 'este es un nuevo post', '197O00045', '1');

        $this->assertInstanceOf(Post::class, $post);

    }
}

UserTest

<?php

use PHPUnit\Framework\TestCase;
use App\User;

class UserTest extends TestCase
{
    public function test_add_user()
    {
        $user = new User('Alexis','Vazquez','Morales');

        $this->assertInstanceOf(User::class, $user);
    }
}

<?php

require __DIR__ . '/vendor/autoload.php';

use App\Author;
use App\Category;
use App\Post;
use App\Comment;

$post = new Post;

$post->addComment(new Comment("text",new Author("J. Alen","ABC123"),new Category("PHP")));
$post->addComment(new Comment("text",new Author("X. Perry","OPQ789"),new Category("Vue")));
$post->addComment(new Comment("text",new Author("P. Jhons","XYZ654"),new Category("Javascript")));

echo "Cantidad comentarios: {$post->countComments()}";

Hola, este es mi reto, estoy abierto a opiniones acerca del c贸digo

composer.json

{
    "name": "chrisvarg/post",
    "description": "proyecto Post",
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }   
}

User.php

<?php

namespace App;

class User
{
    protected $name;
    protected $lastName;
    
    /**
     * Get the value of lastName
     */ 
    public function getLastName()
    {
        return $this->lastName;
    }

    /**
     * Set the value of lastName
     *
     * @return  self
     */ 
    public function setLastName($lastName)
    {
        $this->lastName = $lastName;

        return $this;
    }

    /**
     * Get the value of name
     */ 
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set the value of name
     *
     * @return  self
     */ 
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }
}

Autor.php

<?php

namespace App;

class Autor extends User
{
    protected $post = [];

    public function createPost(Post $post)
    {
        $this->post[] = $post;
    }

    public function getPost()
    {
        return $this->post;
    }
}

Category.php

<?php

namespace App;

class Category
{
    protected $name;

    /**
     * Get the value of name
     */ 
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set the value of name
     *
     * @return  self
     */ 
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }
}

Post.php

<?php

namespace App;

class Post
{
    protected $title;
    protected $content;
    protected $category;

    /**
     * Get the value of title
     */ 
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * Set the value of title
     *
     * @return  self
     */ 
    public function setTitle(string $title)
    {
        $this->title = $title;
        return $this;
    }

    /**
     * Get the value of content
     */ 
    public function getContent()
    {
        return $this->content;
    }

    /**
     * Set the value of content
     *
     * @return  self
     */ 
    public function setContent(string $content)
    {
        $this->content = $content;

        return $this;
    }

    /**
     * Get the value of category
     */ 
    public function getCategory()
    {
        return $this->category;
    }

    /**
     * Set the value of category
     *
     * @return  self
     */ 
    public function setCategory(Category $category)
    {
        $this->category = $category;

        return $this;
    }

    public function showPost() : string
    {
        return "Title: {$this->getTitle()}
                Content: {$this->getContent()}
                Category: {$this->category->getName()}";
    }
}

index.php

<?php

require_once __DIR__."/vendor/autoload.php";

use App\User;
use App\Autor;
use App\Category;
use App\Post;

// User
$autor = new Autor();
$autor->setName('David');
$autor->setLastName('Vargas');

// Category
$category = new Category();
$category->setName('Laravel');

// Post
$post = new Post();
$post->setTitle('Titulo de un post sobre Laravel');
$post->setContent('Contenido de un post sobre Laravel');
$post->setCategory($category);

$autor->createPost($post);

$posts = $autor->getPost();

foreach ($posts as $post) {
    
    echo $post->showPost();

}

Result

<?php
include 鈥淐lases/User.php鈥;
include 鈥淐lases/Author.php鈥;
include 鈥淐lases/Post.php鈥;
include 鈥淐lases/Category.php鈥;

$user = new Post;
$cate = new Category;
$user->type = new Author();
echo $user->type->getName(鈥楽ebas鈥);
echo "<br>categoria: ".$cate->category;

Mi soluci贸n al reto:

Como dijeron varios compa帽eros, se acepta el feedback con gusto.

index.php

<?php

require_once("vendor/autoload.php");

use App\Author;
use App\Category;
use App\Post;

//Nuevo Autor
$author = new Author('Angelica', 'Estupi帽an', 'Koala');

//Nueva Categor铆a
$category = new Category(['arte','lettering']);

//Nuevo post
$post = new Post('Como crear plantillas con lettering','Aplica nuevas tecnicas', $author, $category);

print_r($post->getAuthor()->getFullname());
echo '</br>';
print_r($post->getCategory()->getCategoryName());
echo '</br>';
print_r($post->getTitle());
echo '</br>';
print_r($post->getContent());

User.php

<?php

namespace App;

abstract class User {
    
    protected $name;
    protected $lastname;
    protected $alias;

    public function __construct(string $name, string $lastname, string $alias)
    {
        $this->name = $name;
        $this->lastname = $lastname;
        $this->alias = $alias;
    }

    public function getName()
    {
       return $this->name;
    }

    public function getLastname()
    {
        return $this->lastname;
    }

    public function getAlias()
    {
        return $this->alias;
    }

    public function getFullname()
    {
        return "{$this->name} {$this->lastname}";
    }
}

Author.php

<?php

namespace App;

class Author extends User
{
    protected $posts = [];
    
    public function __construct($name, $lastname, $alias)
    {
        parent::__construct($name, $lastname, $alias);
    }

    public function setPost(Post $post)
    {
        array_push($this->posts, $post);
    }

    public function getPosts()
    {
        return $this->posts;
    }

    public function getCountPosts()
    {
        return count($this->posts);
    }
}

Category.php

<?php

namespace App;

class Category
{
    protected $categoryName = [];

    public function __construct(array $categoryName)
    {
        $this->categoryName[] = $categoryName;
    }

    public function getCategoryName()
    {
        return $this->categoryName;
    }
}

Unit tests

AuthorTest.php

<?php

use PHPUnit\Framework\TestCase;

class AuthorTest extends TestCase
{
    public function test_it_can_get_author_attributes()
    {
        $author = new \App\Author('Cristian', 'Garcia', 'Nseiken');
       
        $this->assertEquals('Cristian', $author->getName());
        $this->assertEquals('Garcia', $author->getLastname());
        $this->assertEquals('Nseiken', $author->getAlias());
    }

    public function test_it_can_get_author_fullname()
    {
        $author = new \App\Author('Cristian', 'Garcia', 'Nseiken');
        
        $this->assertEquals('Cristian Garcia', $author->getFullname());
    }
}

PostTest.php

<?php

use App\Post;
use App\Author;
use App\Category;
use PHPUnit\Framework\TestCase;

class PostTest extends TestCase
{
    public function test_it_can_create_post_by_author()
    {
        $author = new Author('Cristian', 'Garcia', 'Nseiken');

        $category = new Category(['videojuegos', 'ocio']);

        $post = new Post('Mi gusto por Bioshock', 'Por su historia y jugabilidad', $author, $category);
        
        $author->setPost($post);
        
        $this->assertInstanceOf(Author::class, $post->getAuthor());
        $this->assertInstanceOf(Category::class, $post->getCategory());
        $this->assertEquals('Mi gusto por Bioshock', $post->getTitle());
        $this->assertEquals('Por su historia y jugabilidad', $post->getContent());
        $this->assertEquals(1, $author->getCountPosts());
    }
}