18 de abril de 2024 • 4 min de lectura
Especialista en IA y Automatización
Diseño sistemas de comunicación impulsados por IA. Mi trabajo se centra en agentes de voz, chatbots de WhatsApp, asistentes de IA y automatización de flujos, construidos principalmente sobre Twilio, n8n y LLM modernos como OpenAI y Claude. En los últimos 7 años he entregado más de 30 proyectos de automatización que manejan más de 250 000 interacciones mensuales.
Si te gusta el contenido que hago, puedes suscribirte y recibir información valiosa por correo. No se envía spam, solo novedades sobre publicaciones interesantes o contenido especializado del que hablo.
Los traits son un mecanismo de reutilización de código para lenguajes de herencia simple como PHP. Están diseñados para que los desarrolladores guardemos lógica y la reusemos en distintos lugares de la aplicación. Una clase puede contener todos los traits que haga falta, pero las funciones no pueden colisionar. Si más de 1 trait tiene el mismo nombre de función, hay que especificar cuál usar en la clase que los usa.
¿Cuándo conviene usar traits? Básicamente cuando querés encapsular código que puede correr en distintas partes de tu lógica. Por ejemplo, podemos armar un contador de visitas para distintos tipos de recursos (Posts y Projects) en nuestra app Laravel. Son un buen ejemplo porque podemos encapsular la lógica de guardar la visita y reusarla en varios modelos.
Primero vamos a definir la tabla, el modelo y el trait.
create_visitors_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('visitors', function (Blueprint $table) {
$table->id();
$table->ipAddress('ip');
$table->string('user_agent');
$table->string('url', 500);
$table->string('model_type');
$table->unsignedBigInteger('model_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('visitors');
}
};
App\Models\Visitor.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Visitor extends Model
{
use HasFactory;
protected $fillable = [
'ip',
'user_agent',
'url',
'model_type',
'model_id',
];
}
App\Traits\HasVisitorCounter.php
<?php
namespace App\Traits;
use App\Models\Visitor;
use Illuminate\Database\Eloquent\Relations\MorphMany;
trait HasVisitorCounter
{
public function visitors(): MorphMany
{
return $this->morphMany(Visitor::class, 'model');
}
public function storeVisitor()
{
return $this->visitors()->create([
'ip' => request()->ip(),
'user_agent' => request()->userAgent(),
'url' => request()->fullUrl(),
]);
}
public function visitorsCount()
{
return $this->visitors()->count();
}
}
Esta es la estructura básica que necesitamos para usar el trait. Ahora vamos a sumarlo a los modelos Post y Project para ver cómo reusar la función storeVisitor
App\Models\Post.php
<?php
namespace App\Models;
use App\Traits\HasVisitorCounter;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory, HasVisitorCounter;
protected $fillable = [
'title',
'subtitle',
'content',
'slug',
'post_category_id',
'image',
'is_published',
'published_at'
];
...
}
App\Models\Project.php
<?php
namespace App\Models;
use App\Traits\HasVisitorCounter;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Project extends Model
{
use HasFactory, HasVisitorCounter;
protected $fillable = [
'title',
'slug',
'subtitle',
'content',
'image'
];
...
}
Con eso listo, ya podemos usar storeVisitor() en el modelo donde queramos. En particular, yo lo voy a usar cada vez que renderizo un Post o un Project en la aplicación.
App\Http\Controllers\Web\PostController.php
/**
* Display the specified resource.
*/
public function show(Post $post)
{
// Trait method
$post->storeVisitor();
$relatedPosts = Post::published()
->where(function($query) use ($post) {
$query->where('post_category_id', $post->post_category_id)
->orWhereHas('tags', function ($query) use ($post) {
$query->where(function($q) use ($query, $post) {
$query->where('model_has_tags.taggable_type', Post::class)
->whereIn('model_has_tags.tag_id', $post->tags->pluck('id'));
});
});
})
->where('posts.id', '!=', $post->id)
->limit(4)
->inRandomOrder()
->get();
return view('post.show', [
'breadcrumbs' => $this->breadcrumbsService->getBlogPostBreadcrumbs($post),
'post' => $post,
'relatedPosts' => $relatedPosts
]);
}
App\Http\Controllers\Web\ProjectController.php
/**
* Display the specified resource.
*/
public function show(Project $project)
{
// Trait method
$project->storeVisitor();
return view('project.show', [
'breadcrumbs' => $this->breadcrumbsService->getProjectPublicBreadcrumbs($project),
'project' => $project,
]);
}
Los traits son una herramienta potente para mantener el codebase limpio y evitar aplicar la misma modificación en N lugares distintos de la aplicación. Bien usados, también mejoran la legibilidad del código y te ayudan a aplicar el principio DRY.
¿Te sirvió el post? Si querés, compartilo :)
-Gonza
Descubre cuánto te está costando tu sistema de comunicaciones.
Obtén la auditoría de comunicaciones