Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Коробочный компонент уведомлений.
Когда комментишь статью, то приходят уведомления, и они помечаются прочитанными,
как сделать, что бы при удалении статьи, из таблицы удалялись эти уведомления?
Ведь в таблицу не записывается отдельный id статьи, а записывается всё в столбец data.
Может раширить таблицу уведомлений и добавить отдельный столбец id поста?
Или есть уже готовое решение?
Ведь взять все записи и перебрать каждую, потом искать есть ли в этом объекте id поста,
это будет слишком большая нагрузка и это не логично.
А почему использовали для поиска метод post, а не get?
Я конфиг брал отсюда
Вывожу уведомления.
В таблицу notifications в дату добавляются данные, таким способом
public function toDatabase($notifiable) {
return [
'post_id' => $this->details['post_id'], // id поста
'comment_id' => $this->details['comment_id'], //id комента
'user_comment_id' => $this->details['user_comment_id'] // id юзера, который оставил коммент
];
Теперь мне надо вывести список уведомлений, что бы было видно, кто оставил комент,
и на какой пост, сделал это так
public function readNotification()
{
$user = User::find(Auth::id());
$allData = collect();
foreach ($user->unreadNotifications as $notification) {
$collect1 = collect(Post::find($notification->data['post_id']));
$collect2 = collect(['user_comment' => Comment::find($notification->data['comment_id'])->text]);
$collect3 = collect(['user_name' => User::find($notification->data['user_comment_id'])->name]);
$allData->push($collect1
->merge($collect2)
->merge($collect3)
->merge(['id_notif' => $notification->id]));
}
return view('read-notifications', [
'allData' => $allData,
]);
}
<section class="section main-content">
<div class="container">
@foreach ($allData as $data)
<div class="card">
<div class="card-body">
<h5 class="card-title">{{$data['user_name']}}, добавил комментраий к посту - {{$data['description']}}</h5>
<div class="card-text">{!!$data['user_comment']!!}</div>
<br>
<a href="/post/{{$data['id']}}" class="btn btn-primary">Перейти</a>
<a href="/mark-notif-read/{{$data['id_notif']}}" class="btn btn-primary">Отменить прочитанным</a>
</div>
</div>
<br>
@endforeach
</div>
</section>
Это нормальный способ? Какой есть по лучше?
https://github.com/Div-Man/bulma-laravel
http://domain1606035.ru.host1606035.serv16.hostland.pro
Если авторизироваться с помощью соц сетей, то подтверждать почту не надо.
Почему то, при добавлении первого коммента для своей картинки, аякс не срабатывает, вернее срабатывает, но вёрстка нового коммента не добавляется и ошибок нету.
Если к вашему посту добавлен коммент, то приходит уведомление.
Админки нету.
устанавливал так
composer require --dev laravel/dusk
php artisan dusk:install
<code lang="php">
"require-dev": {
"filp/whoops": "^2.0",
"fzaninotto/faker": "^1.4",
"laravel/browser-kit-testing": "^4.1",
"laravel/dusk": "^4.0",
"mockery/mockery": "^1.0",
"nunomaduro/collision": "^2.0",
"phpunit/phpunit": "^7.0"
},
Вот так пробовал
composer remove vendor/laravel/dusk
не удаляет
vendor/laravel/dusk is not required in your composer.json and has not been removed
Package "vendor/laravel/dusk" listed for update is not installed. Ignoring.
вот так
composer remove vendor/dusk
то же самое
vendor/dusk is not required in your composer.json and has not been removed
Package "vendor/dusk" listed for update is not installed. Ignoring.
Как отследить роуты админки? В доке ничего про это нету, например поставил я вот эту репу https://github.com/SleepingOwlAdmin/demo
и как теперь мне узнать какой контроллер запускается при роуте admin/pages?
Я вот этот код закоментил и всё равно все страницы работают, ничего не понимаю
<?php
/*
$router->get('/information', ['as' => 'admin.information', function (\SleepingOwl\Admin\Contracts\Template\TemplateInterface $template) {
return $template->view(
'Define your information here.',
'Information'
);
}]);
*
*/
/*
$router->post('/news/export.json', ['as' => 'admin.news.export', function (\Illuminate\Http\Request $request) {
$response = new \Illuminate\Http\JsonResponse([
'title' => 'Congratulation! You exported news.',
'news' => App\Model\News5::whereIn('id', $request->_id)->get()
]);
return $response;
}]);
*/
И где хранятся пункты левой навигации? нижнюю половину я нашёл в admin/navigation.php а другую половину не нашёл, где она?
Сделал рейтинг по 5 шкале, всё работает, допустимый ли вариант?
Когда пользователь голосует, то данные записываются в отдельную таблицу,
потом идёт подсчёт голосов и результат присваивается в поле rating в таблицу user.
user_rating
id user_id master_id valuation
1 2 2 3
3 3 2 1
14 1 2 4
public function addRating(Request $request)
{
$userAuth = Auth::user()->id;
//сначала узнаём, голосовал ли уже пользователь
//этот пост
$users = DB::table('user_rating')
->where('master_id', '=', $request->userId)
->where('user_id', '=', $userAuth)
->get();
//если голосовал, то обновляем его новый голос
if($users->count() == 1) {
$this->updateRating($users[0]->id, $request);
}
// иначе первый раз голосуем
else {
$id = DB::table('user_rating')->insertGetId(
[
'user_id' => $userAuth,
'master_id' => $request->userId,
'valuation' => $request->rating
]);
$this->updateRating($id, $request);
}
}
public function updateRating($id, $data)
{
//обновление рейтинга, для пользователя
DB::table('user_rating')
->where('id', $id)
->update(['valuation' => $data->rating]);
//найти все голоса, данного поста
$collection = DB::table('user_rating')
->where('master_id', '=', $data->userId)
->get();
//количество всего голосов
$count= $collection->count();
//извлекаем значения с голосами
$plucked = $collection->pluck('valuation');
// подсчёт среднего числа
$avg = round($plucked->sum()/$count, 1);
User::where('id', $data->userId) ->update(['rating' => $avg]);
}
Вот такой запрос получился
(SQL: insert into `category_image` (`category_id`, `image_id`, `0`, `1`) values (18, 18, 1, 2)
Это неверный запрос, из-за этого выводит ошибку.
$relation = \App\Services\Image::find($idNewImage);
dd($relation->categories()->attach($idNewImage, $categories));
Надо что бы был примерно такой запрос
insert into `category_image` (`category_id`, `image_id`) values ( 2, 18)
И получается, если надо будет добавить во многие категории, то должно быть несколько запросов?
это типа меток длят статей
Код работает, но некоторые говорят, что это плохой пример, и его нужно переписать в отношения, но я не знаю, как, вы можете сказать?
Статьи могут быть добавлены в разные категории
Метод addRelation получает массив с значениями категории и идентификатором статьи
и после обработки эти данные добавляются к промежуточной таблице
array:2 [▼
0 => "1"
1 => "2"
]
public function addRelation($categories, $id)
{
$categoryId = [];
$collection = collect($categories);
$collection = $collection->chunk(1);
$collection->each(function ($item, $key) use (&$categoryId, $id){
$categoryId[] = [
'image_id' => $id,
'category_id' => $item->first()
] ;
}
);
DB::table('category_image')->insert($categoryId);
}
Удаление
public function deleteImage($image)
{
Storage::delete($image->image);
$this->destroy($image->id);
DB::table('category_image')->where('image_id', $image->id)->delete();
}
Модели
class Image extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class);
}
}
class Category extends Model
{
protected $fillable = ['name'];
public $timestamps = false;
public function article()
{
return $this->belongsToMany('App\Services\Image');
}
}
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
});
Schema::create('images', function (Blueprint $table) {
$table->increments('id');
$table->string('image');
$table->timestamps();
});
Schema::create('category_image', function (Blueprint $table) {
$table->increments('id');
$table->integer('image_id');
$table->integer('category_id');
});
public_html
Сделал так
public_html/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule ((?s).*) public/$1 [L]
</IfModule>
# public_html/public/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^((?s).*)$ index.php?_url=/$1 [QSA,L]
</IfModule>
Почему-то не может найти контроллер
Route::get('/', 'imagesController@index');
на локалке всё работает
хостинг 000webhostapp.com
пробовал переименовывать public_html в public, ругается
Forbidden
You don't have permission to access / on this server.
Additionally, a 403 Forbidden error was encountered while trying to use an ErrorDocument to handle the request.
Изменил в LoginController перенаправление на корень, всё равно переходит на home почему?
protected $redirectTo = '/';
protected function redirectTo()
{
return '/';
}
Делаю всё по доке.
Не понимаю, почему ругается на
Auth guard [user] is not defined.?
В контроллере регистрации прописал
use Illuminate\Support\Facades\Auth;
protected function guard()
{
return Auth::guard('user');
}
в IDE нету перехода по ссылке guard
Как вывести записи пивотной таблицы, с пагинатором?
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
public function article()
{
return $this->belongsToMany('App\Services\Image');
}
}
Делаю так, всё хорошо работает
$aaa = Category::find(3);
dd($aaa->article);
Но если добавить с пагинатором, то будет ошибка
$aaa = Category::find(3)::paginate(2);
dd($aaa->article);
Undefined property: Illuminate\Pagination\LengthAwarePaginator::$article
Вот допустим, можно статью засовывать в разные категории, тогда лучше для этого сделать отдельную таблицу и использовать связь многие ко многим?
У одной статьи есть много категорий, у одной категории есть много статей.
Или Многие к одному?
Есть модель Post
<?php
namespace App;
use Carbon\Carbon;
use Illuminate\Support\Facades\Storage;
use Illuminate\Database\Eloquent\Model;
use Cviebrock\EloquentSluggable\Sluggable;
use Illuminate\Support\Facades\Auth;
class Post extends Model
{
use Sluggable;
const IS_DRAFT = 0;
const IS_PUBLIC = 1;
protected $fillable = ['title','content', 'date', 'description'];
public function comments()
{
return $this->hasMany(Comment::class);
}
public function getComments()
{
return $this->comments()->where('status', 1)->get();
}
}
В контроллере, ни к какой метод не вызывается, а только идёт обращение ко всей модели, нужной статье
public function show($slug)
{
$post = Post::where('slug', $slug)->firstOrFail();
return view('pages.show', compact('post'));
}
И в виде, вызывается метод $post->getComments, как этот метод попал в вид, если в контроллере, его не передавали?
или когда идёт любое обращение к классу, таким способом Post:: то в переменную вшиваются все методы?
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
protected $table = 'my_flights';
public function user()
{
return $this->belongsTo('App\User');
}
}
$event = Flight::find(3)->user_id;
$user = User::find($event)->name;
dd($user);
Выводит имя юзера у статьи, даже, если убрать метод user(), тогда для чего он нужен?
Оцените пожалуйста код, типичного простого блога.
Регистрация пользователей.
Пользователям можно только комментить и изменять свой профиль.
Админ может, добавлять посты, категории, теги, убирать ненужные комменты.
Сделал свою костыльную панинацию
https://github.com/Div-Man/My-first-lar … .blade.php
----------------------------------------------------
Я хотел, что бы на главной странице, выводились посты и для каждого поста, выводилось количество комментов, нормальным способом это сделать не смог и сделал таким способом
19 строка https://github.com/Div-Man/My-first-lar … roller.php
и 38 https://github.com/Div-Man/My-first-lar … .blade.php
------------------------------------------
Весь репозиторий https://github.com/Div-Man/My-first-laravel-blog
Допустимый ли такой код пагинатора в laravel? Плохо то, что я напрямую обращаюсь к массиву GET?
Надо что бы первые и последние страницы исчезали из видимости, по мере нахождения на странице.
Например, изначально так: 1 2 3 4. Если окажусь на 6 странице, то первые 2 не будут отображаться и будет так 3 4 5 6.
Код полностью рабочий
<div class="myPag">
<a href="?page=1">Первая</a>
<?php
if (!empty($_GET['page'])) {
if (($_GET['page'] + 3) <= $posts->total()) {
$countPag = $_GET['page'] + 3;
} else {
$countPag = $posts->total();
}
$prev = $_GET['page'] - 1;
if ($_GET['page'] != 1) {
echo '<a href=?page=' . $prev . '>Назад</a>';
}
if ($_GET['page'] > 1) { //это для предыдущих страниц (можно удалить полностью условие, тогда их не будет)
$prevPage = $_GET['page'] - 1;
$arr = [];
for ($j = $prevPage; $j >= 1; $j--) {
$arr[] = $j;
}
$newArr = array_reverse($arr);
$output = array_slice($newArr, -3, 3);
foreach ($output as $key => $val) {
echo '<a href=?page=' . $val . '>' . $val . '</a>';
}
}
for ($i = $_GET['page']; $i <= $countPag; $i++) {
if ($_GET['page'] == $i) {
echo '<span class="active">' . $i . '</span>';
} else {
echo '<a href=?page=' . $i . '>' . $i . '</a>';
}
}
$next = $_GET['page'] + 1;
if ($_GET['page'] != $posts->total()) {
echo '<a href=?page=' . $next . '>Далее</a>';
}
} else {
for ($i = 1; $i <= 3; $i++) {
if ($i == 1) {
echo '<span class="active">' . $i . '</span>';
} else {
echo '<a href=?page=' . $i . '>' . $i . '</a>';
}
}
echo '<a href=?page=2>Далее</a>';
}
?>
<a href="?page=<?php echo $posts->lastPage(); ?>">Последняя</a>
</div>
Что значит через scope?
Это нерабочий код
Надо вывести количество коментов, для открытой статьи.
Посмотрел я на код ORM и мне это не нравится и решил сделать с помощью построителя, допустимый ли такой вариант?
$post = Post::where('slug', $slug)->firstOrFail();
$commentsCount = DB::table('comments')->where('post_id',$post->id)->count();
Можете показать хорошие практики? В гугле статьи есть, но они старые и неизвестно, актуальный ли этот способ или нет.
Учусь добавлять данные в базу, нормальный ли способ? Версия 5.6
Route::get('/create', 'ArticleController@index');
Route::post('/add-article', 'ArticleController@store');
//////////////////////////////////////////////////////////////////
<form action="{{ url('add-article') }}" method="POST" class="form-horizontal">
{{ csrf_field() }}
<input type="hidden" name="created_by" value="{{Auth::id()}}">
<!-- Task Name -->
<div class="form-group">
<label for="task-name" class="col-sm-3 control-label">Новая статья</label>
<div class="col-sm-6">
@if ($errors->has('title'))
<div class="alert alert-danger">Название должно быть длиной, не менее 10 символов и не более 40.</div>
@endif
<input type="text" name="title" id="task-name" class="form-control" >
<br>
@if ($errors->has('description'))
<div class="alert alert-danger">Описание должно быть длиной, не менее 20 символов и не более 200</div>
@endif
<textarea rows=10 name="description" class="form-control"></textarea>
</div>
</div>
<!-- Add Task Button -->
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button type="submit" class="btn btn-default">
<i class="fa fa-btn fa-plus"></i>Добавить статью
</button>
</div>
</div>
</form>
////////////////////////////////////////////////////////////////////////////////////
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|min:10|max:40',
'description' => 'required|min:20|max:200',
]);
DB::table('articles')->insert( [
'title' => $request->title,
'description' => $request->description,
'created_by' => $request->created_by,
] );
}