نحوه ایجاد پروفایل کاربر در برنامه لاراول
در این قسمت از آموزش در لیداوب به بررسی نحوه ایجاد پروفایلهای کاربری در برنامههای لاراول خواهیم پرداخت. با ما همراه باشید.
نحوه ایجاد پروفایل کاربر در برنامه لاراول
بیشتر وب سایتهایی که به کاربر اجازه میدهند، اطلاعات خود را ثبت کرده و به اشتراک بگذارند، دارای صفحه پروفایل برای هر کاربر هستند. در این آموزش از لیداوب کاری که میخواهیم انجام دهیم این است که به کاربران وب سایت اجازه دهیم که روی یک نام کاربری در مرورگر کلیک کنند و اطلاعات بیشتری درباره آن کاربر را در صفحه پروفایل خود مشاهده کنند. در این آموزش، میتوانید هنگام ساختن صفحه پروفایل برای کاربران خود، نتایج حاصل از اجرای تستهای خود را نیز مشاهده کنید.
ایجاد یک تست پروفایل کاربر
با رفتن به فولدر ویژگیهای برنامه خود، میتوانیم یک کلاس جدید تست را با نام ProfilesTest
اضافه کنیم. سپس، صفحه آزمایشی را برای یک تست جدید اضافه کنید.
شبه کد (Pseudocode) تست با توجه به موارد زیر ایجاد کنید:
- با توجه به اینکه ما یک کاربر در برنامه داریم
- هنگامی که از پروفایل (نام آنها) بازدید میکنیم
- هنگامی که باید نام آنها را در صفحه ببینیم
سپس آن را به یک متد تست و کد مرتبط تبدیل میکنیم.
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class ProfilesTest extends TestCase
{
use DatabaseMigrations;
public function test_a_user_has_a_profile()
{
$user = create('App\User');
$this->withoutExceptionHandling()->get('/profiles/' . $user->name)
->assertSee($user->name);
}
}
پس از آن، اجرای تست را شروع کرده و اجازه دهید خطاها ما را در مراحل بعدی برای هدایت راهنمایی کنند.
[email protected]:~/Code/forumio$ phpunit --filter test_a_user_has_a_profile
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 947 ms, Memory: 8.00MB
There was 1 error:
1) Tests\Feature\ProfilesTest::test_a_user_has_a_profile
Symfony\Component\HttpKernel\Exception\NotFoundHttpException: GET http://localhost/profiles/Athena Zulauf
/home/vagrant/Code/forumio/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/InteractsWithExceptionHandling.php:107
/home/vagrant/Code/forumio/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:326
/home/vagrant/Code/forumio/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:120
/home/vagrant/Code/forumio/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:345
/home/vagrant/Code/forumio/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:168
/home/vagrant/Code/forumio/tests/Feature/ProfilesTest.php:18
ERRORS!
Tests: 1, Assertions: 0, Errors: 1.
ما در حال گرفتن یک NotFoundHttpException
هستیم که البته این بدان معنی است که هیچ راهی برای پشتیبانی از آن درخواست وجود ندارد.
مسیر لازم را اضافه کنید
فایل مسیرهای web.php
را باز کنید، و اجازه دهید مسیری را که نیاز داریم همانطور که در اینجا مشخص شده است، اضافه کنیم. هنگامی که کاربر درخواستی را برای پروفایل کاربر ایجاد میکند، باید متد show()
از ProfilesController
را راه اندازی کرد.
<?php
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', '[email protected]')->name('home');
Route::get('/threads', '[email protected]');
Route::get('/threads/create', '[email protected]');
Route::get('/threads/{channel}/{thread}', '[email protected]');
Route::post('/threads', '[email protected]');
Route::get('/threads/{channel}', '[email protected]');
Route::post('/threads/{channel}/{thread}/replies', '[email protected]');
Route::post('/replies/{reply}/favorites', '[email protected]');
Route::get('/profiles/{user}', '[email protected]');
دوباره تست را اجراکنید تا ببینید چه خطایی صادر شده است.
[email protected]:~/Code/forumio$ phpunit --filter test_a_user_has_a_profile
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 960 ms, Memory: 8.00MB
There was 1 error:
1) Tests\Feature\ProfilesTest::test_a_user_has_a_profile
ReflectionException: Class App\Http\Controllers\ProfilesController does not exist
این تست بذاعث بروز یک خطا میشود، این خطا اعلان میکند که ProfilesController
وجود ندارد. از آنجا که هنوز کنترلری ایجاد نکردهایم،این امر منطقی است.
یک کلاس ProfilesController
به صورت زیر ایجاد میکنیم.
[email protected]:~/Code/forumio$ php artisan make:controller ProfilesController
Controller created successfully.
از آنجایی که اکنون یک ProfilesController داریم، این خطا باید در تست برطرف شود. سپس دوباره آن را تست کنیم.
[email protected]:~/Code/forumio$ phpunit --filter test_a_user_has_a_profile
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 918 ms, Memory: 8.00MB
There was 1 error:
1) Tests\Feature\ProfilesTest::test_a_user_has_a_profile
BadMethodCallException: Method [show] does not exist on [App\Http\Controllers\ProfilesController].
اکنون، یک خطای BadMethodCallException رخ میدهد. البته منطقی است، زیرا هیچ متد show()
بر روی کنترلر وجود ندارد.
ایجاد یک متد ()show
اکنون، ما میتوانیم متد show ()
را به کلاس ProfilesController
اضافه کنیم:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProfilesController extends Controller
{
public function show()
{
}
}
متد show
اکنون وجود دارد. هنوز کاری انجام نشده است، اما بگذارید تست خود را دوباره اجرا کنیم.
[email protected]:~/Code/forumio$ phpunit --filter test_a_user_has_a_profile
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
F 1 / 1 (100%)
Time: 881 ms, Memory: 8.00MB
There was 1 failure:
1) Tests\Feature\ProfilesTest::test_a_user_has_a_profile
Failed asserting that '' contains "Forrest Treutel".
/home/vagrant/Code/forumio/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:236
/home/vagrant/Code/forumio/tests/Feature/ProfilesTest.php:19
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
به نظر می رسد وقتی ما از پروفایل Forrest Treutel بازدید میکنیم در صفحه مشاهده نمیشود. باید متد show()
را برای رفع این خطا اصلاح کنیم.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProfilesController extends Controller
{
public function show()
{
return view('profiles.show');
}
}
ایجاد یک View برای پروفایل کاربر
show.blade.php
برای پروفایلها هنوز وجود ندارد، بنابراین ما باید آن را ایجاد کنیم.
[email protected]:~/Code/forumio$ phpunit --filter test_a_user_has_a_profile
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 861 ms, Memory: 8.00MB
There was 1 error:
1) Tests\Feature\ProfilesTest::test_a_user_has_a_profile
InvalidArgumentException: View [profiles.show] not found.
ویوی profiles.show
یافت نشد. باید این ویو را ایجاد کنیم.
ما با کد زیر شروع میکنیم.
@extends('layouts.app')
@section('content')
{{ $profileUser->name }}
@endsection
بیایید این تست را چرخش دیگر بدهیم.
[email protected]:~/Code/forumio$ phpunit --filter test_a_user_has_a_profile
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 1.26 seconds, Memory: 10.00MB
There was 1 error:
1) Tests\Feature\ProfilesTest::test_a_user_has_a_profile
ErrorException: Undefined variable: profileUser (View: /home/vagrant/Code/forumio/resources/views/profiles/show.blade.php)
به نظر می رسد که ما یک متغیر تعریف نشده داریم. برای رفع این مشکل نیاز داریم دادهها را به ویو منتقل کنیم. برای این کار میتوانیم متد show()
را در ProfilesController
به صورت زیر بروز رسانی کنیم.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ProfilesController extends Controller
{
public function show(User $user)
{
return view('profiles.show', [
'profileUser' => $user
]);
}
}
اکنون که متغیر خود را به اشتراک میگذاریم، ما میتوانیم تست را اجرا کنیم تا ببینیم آیا آن را ثابت کردهایم یا خیر.
[email protected]:~/Code/forumio$ phpunit --filter test_a_user_has_a_profile
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 911 ms, Memory: 8.00MB
There was 1 error:
1) Tests\Feature\ProfilesTest::test_a_user_has_a_profile
Illuminate\Database\Eloquent\ModelNotFoundException: No query results for model [App\User].
بنابراین، خطای قبلی را برطرف کردیم اما اکنون در حال گرفتن ModelNotFoundException هستیم. دلیل این امر در نحوه پیکربندی Route Model Binding به صورت پیش فرض است.
بایندینگ مدل مسیر
اگر بخواهیم مدل از Slug استفاده کند، باید برای پشتیبانی از این روش، متد getRouteKeyName ()
را پیکربندی کنیم. مدل User را باز کنید و به صورت زیر تنظیم کنید:
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function getRouteKeyName()
{
return 'name';
}
}
یکبار دیگر تست را اجرا کنید. به قسمت سبز نگاه کنید!
این بدان معناست که اگر قرار بود به یک صفحه پروفایل در مرورگر مراجعه کنیم، در واقع باید در این مرحله کار کند. یک کاربر در سیستم به نام Tom وجود دارد، بنابراین بیایید به http://forum.io/profiles/tom مراجعه کرده و ببینیم چه چیزی را دریافت میکنیم.
بهترین طراحی ظاهر (Styling) با بوت استرپ
منطق صفحه درست کار میکند. اما برای نمایش بهتر موارد گفته شده، میتوانیم نمایش show.blade.php
را به چیزی شبیه به زیر بروزرسانی کنیم:
@extends('layouts.app')
@section('content')
<div class="container">
<div class="page-header">
<h1>
{{ $profileUser->name }}
<small>registered {{ $profileUser->created_at->diffForHumans() }}</small>
</h1>
</div>
</div>
@endsection
که یک چیدمان پروفایل زیباتر ارائه میدهد.
نمایش موضوعاتی (Threads) که کاربر ایجاد کرده است
یکی از ویژگیهایی که میخواهیم اضافه کنیم، امکان مشاهده کلیه موضوعات ایجاد شده توسط کاربر است که نمایه شما را مشاهده میکند. به منظور اضافه کردن این ویژگی، ابتدا یکبار دیگر برای پشتیبانی از آن یک تست ایجاد خواهیم کرد. در کلاس ProfilesTest میتوانیم یک متد جدید تست test_profiles_display_all_threads_by_the_user()
اضافه کنیم. حالا بیایید به آنچه میخواهیم تست انجام شود فکر کنیم.
- با توجه به اینکه ما کاربر داریم
- با توجه به اینکه ما یک موضوع ایجاد شده توسط آن کاربر داریم
- هنگام بازدید از صفحه پروفایل آنها
- هنگامی که ما باید موضوع آنها را ببینیم
در اینجا چند کد تست وجود دارد که تقریباً به این مراحل نزدیک است:
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class ProfilesTest extends TestCase
{
use DatabaseMigrations;
public function test_a_user_has_a_profile()
{
$user = create('App\User');
$this->withoutExceptionHandling()->get('/profiles/' . $user->name)
->assertSee($user->name);
}
public function test_profiles_display_all_threads_by_the_user()
{
$user = create('App\User');
$thread = create('App\Thread', ['user_id' => $user->id]);
$this->withoutExceptionHandling()->get('/profiles/' . $user->name)
->assertSee($thread->title)
->assertSee($thread->body);
}
}
با انجام تست خود میتوان نتایج را اجرا و مشاهده کرد.
[email protected]:~/Code/forumio$ phpunit --filter test_profiles_display_all_threads_by_the_user
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
F 1 / 1 (100%)
Time: 1.22 seconds, Memory: 10.00MB
There was 1 failure:
1) Tests\Feature\ProfilesTest::test_profiles_display_all_threads_by_the_user
Failed asserting that '(the html)' contains "Alias autem velit atque sit aspernatur.".
/home/vagrant/Code/forumio/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:236
/home/vagrant/Code/forumio/tests/Feature/ProfilesTest.php:29
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
این تست ناموفق است زیرا در حقیقت عنوان موضوع در صفحه پروفایل ظاهر نمیشود. ما باید کدی را درست کنیم که در واقع این اتفاق بیفتد. ما میتوانیم این بخش از نشانه گذاری را به show.blade.php
اضافه کنیم تا موضوعات کاربر نمایش داده شود.
@extends('layouts.app')
@section('content')
<div class="container">
<div class="page-header">
<h1>
{{ $profileUser->name }}
<small>registered {{ $profileUser->created_at->diffForHumans() }}</small>
</h1>
</div>
@foreach($profileUser->threads as $thread)
<div class="panel panel-default">
<div class="panel-heading">
<a href="#">{{ $thread->creator->name }}</a> posted:
{{ $thread->title }}
</div>
<div class="panel-body">
{{ $thread->body }}
</div>
</div>
@endforeach
</div>
@endsection
یک بار دیگر، ما تست خود را اجرا خواهیم کرد تا ببینیم چگونه کار میکند.
[email protected]:~/Code/forumio$ phpunit --filter test_profiles_display_all_threads_by_the_user
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 835 ms, Memory: 10.00MB
There was 1 error:
1) Tests\Feature\ProfilesTest::test_profiles_display_all_threads_by_the_user
ErrorException: Invalid argument supplied for foreach() (View: /home/vagrant/Code/forumio/resources/views/profiles/show.blade.php)
خطا شکایت از یک استدلال نامعتبر است که به حلقه foreach منتقل میشود. خوب، این امر منطقی است از آنجا که ما هنوز رابطه موضوعات را در مدل کاربر (User Model) ایجاد نکردیم. ما میتوانیم همین حالا اضافه کنیم. همچنین توجه داشته باشید که ما متد latest()
را به تعریف رابطه اضافه میکنیم به طوری که ما موضوعات کاربر را مشاهده میکنیم،جدیدترین موضوعات در بالای صفحه ظاهر میشود.
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function getRouteKeyName()
{
return 'name';
}
public function threads()
{
return $this->hasMany(Thread::class)->latest();
}
}
اجرای تست ما نشان میدهد که اکنون در حال گذر است.
[email protected]:~/Code/forumio$ phpunit --filter test_profiles_display_all_threads_by_the_user
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.
. 1 / 1 (100%)
Time: 892 ms, Memory: 10.00MB
OK (1 test, 2 assertions)
هنگامی که ما اکنون از کاربر نمونه خود، صفحه پروفایل Tom در http://forum.io/profiles/tom بازدید میکنیم، ما جدیدترین موضوع را که او ایجاد کرده است مشاهده میکنیم! بنابراین به نظر میرسد مشاهده موضوعات در صفحه پروفایل کاربر اکنون خوب است .
موضوعات جالب در صفحه پروفایل کاربر
از آنجا که کاربران بیشتر وقت خود را برای ارسال موضوعات در برنامه میگذرانند، آنها ممکن است صدها و صدها موضوع ایجاد شده را گردآوری کنند. ما باید به جای اینکه سعی کنیم همه آنها را در یک تصویر (shot) بارگیری کنیم ، باید این موارد را در صفحه پروفایل تنظیم کنیم. این کار به راحتی در متد show()
از ProfilesController و همچنین فایل view مربوط با یک فراخونی برای $threads->links()
تنظیم شده است
بروزرسانی کنترلر
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
class ProfilesController extends Controller
{
public function show(User $user)
{
return view('profiles.show', [
'profileUser' => $user,
'threads' => $user->threads()->paginate(1)
]);
}
}
بروزرسانی view
@extends('layouts.app')
@section('content')
<div class="container">
<div class="page-header">
<h1>
{{ $profileUser->name }}
<small>registered {{ $profileUser->created_at->diffForHumans() }}</small>
</h1>
</div>
@foreach($threads as $thread)
<div class="panel panel-default">
<div class="panel-heading">
<div class="level">
<span class="flex">
<a href="#">{{ $thread->creator->name }}</a> posted:
{{ $thread->title }}
</span>
<span>{{$thread->created_at->diffForHumans()}}</span>
</div>
</div>
<div class="panel-body">
{{ $thread->body }}
</div>
</div>
@endforeach
{{ $threads->links() }}
</div>
@endsection
اکنون صفحه بندی به خوبی کار می کند. ما فقط برای نشان دادن، در این مرحله فقط 1 را تنظیم می کنیم. شاید بتوانید در برنامه واقعی تا 20 یا 30 ضربه بزنید.
اتصال (Linking) نامهای کاربران به صفحه پروفایل آنها
در این مرحله نامهای کاربر نمایش داده شده در فایلهای مشاهده خود به هیچ جایی لینک نمیخورد. بروزرسانی میکنیم تا کاربران بتوانند روی یک نام کاربری در مرورگر کلیک کرده و به صفحه پروفایل خود آورده شوند.
در show.blade.php
شما میتوانید نمونه لینک اول را با لینک دوم مبادله کنید.
<a href="#">{{ $thread->creator->name }}</a>
<a href="/profiles/{{ $thread->creator->name }}">{{ $thread->creator->name }}</a>
در reply.blade.php
شما میتوانید نمونه لینک اول را با لینک دوم مبادله کنید.
<a href="#">{{$reply->owner->name}}</a>
<a href="/profiles/{{ $reply->owner->name }}">{{$reply->owner->name}}</a>
اکنون تمام موارد یک نام کاربر که در لینک مرورگر قرار دارد به پروفایل کاربر بازمیگردد.
استفاده از مسیرهای نامگذاری شده
یکی دیگر از گزینه های شما در این حالت این است که در صورت تمایل یک مسیر نامگذاری شده را تنظیم کنید. به این ترتیب شما میتوانید از مسیر نامگذاری شده در href
از تگهای anchor از فایلهای view خود استفاده کنید. این چطوری کار میکنه؟ اول از همه، باید نامی را برای مسیری که در نظر گرفته شده اختصاص دهیم.
ما این کار را در پرونده مسیرهای خود با مثالی که در اینجا مشخص شده است انجام میدهیم. ما در حال نامگذاری این مسیر profile هستیم.
<?php
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', '[email protected]')->name('home');
Route::get('/threads', '[email protected]');
Route::get('/threads/create', '[email protected]');
Route::get('/threads/{channel}/{thread}', '[email protected]');
Route::post('/threads', '[email protected]');
Route::get('/threads/{channel}', '[email protected]');
Route::post('/threads/{channel}/{thread}/replies', '[email protected]');
Route::post('/replies/{reply}/favorites', '[email protected]');
Route::get('/profiles/{user}', '[email protected]')->name('profile');
نکته جالب در مورد مسیرهای نامگذاری شده این است که میتوانید همچنان که پیکربندی کرده ایم از لینکهای معمولی استفاده کنید. علاوه بر این، ما میتوانیم لینکهای خود را با استفاده از نام مسیر مانند آنچه در اینجا میبینیم، قالب بندی کنیم.
در show.blade.php
شما میتوانید نمونه لینک اول را با لینک دوم مبادله کنید.
<a href="/profiles/{{ $thread->creator->name }}">
<a href="{{ route('profile', $thread->creator) }}">
در reply.blade.php
شما میتوانید نمونه لینک اول را با لینک دوم مبادله کنید.
<a href="/profiles/{{ $reply->owner->name }}">
<a href="{{ route('profile', $reply->owner) }}">
نحوه ایجاد پروفایل های کاربر در خلاصه برنامه خود
اقدامات زیادی برای گرفتن صفحه پروفایل کاربری خود برای کاربران تنظیم و درست شده است. خوشبختانه، ما همه کار را به خوبی انجام دادیم.
مطالعه بیشتر در لیداوب:
این قسمت از آموزش نیز به پایان رسید. در آموزشهای بعد با ما در لیداوب همراه باشید.
دیدگاه ها
متاسفانه فقط اعضای سایت قادر به ثبت دیدگاه هستند
ورود به سایت