Прочие движки | Очередное г.cms ))
Тема закрыта by
mir007
Причина: оалалалалалал
Причина: оалалалалалал
Писать cms? (Открытое голосование)
Нет (5 чел. - 38 %)
Да (5 чел. - 38 %)
Мне всё ровно (3 чел. - 23 %)
С другой
стороны, один комментарий,
какой-то один, конкретный
комментарий, принадлежит
только к одной статье. Такое
отношение называется один к
одному (One to One).
Пока каснемся отношения один
ко многим. В laravel, для
определения такого отношения
необходимо добавить
специальный метод в модель. В
нашем случае — это
модель Article. Добавим метод
comments
<?php
namespace App;
use Illuminate\Database\Eloquent
\Model;
class Article extends Model
{
protected $table="articles";
protected $fillable=
['title','content','preview','meta_description','
meta_keywords','category_id','comments_enable','
public'];
public function comments()
{
return $this->hasMany('App
\Comments','article_id','id');
}
}
article_id — это внешний
ключ, id — это локальный ключ.
Т.е. это ключи по которым
определяется связь между
коментариемя и статьей.
Теперь попробуем вывести
комментарии. Возвращаемся к
виду
resources/views/site/show.blade.php
И допишем
<div class="comments">
<ul>
@foreach($comments as $comment)
<li>Автор: {{$comment->author}}
<br>{{$comment->content}}</li>
@endforeach
</ul>
</div>
И в контролере
FrontController.php изменим
метод show, тот самый, который
отображает наши статьи
public function show ( $id )
{
$comments = Article :: where
( 'public' , '=', 1)-> find( $id )-
> comments; // выбираем все
комментарии, который относятся
к статье
$article = Article:: where
( 'public' , '=', 1)-> find( $id );
return view ( 'site.show' ,
[ 'article' =>
$article , 'comments' =>
$comments ]);
}
Теперь можно подобавлять
несколько комментариев к
статьи и посмотреть, что они
отображаются. Далее будем
усложнять.
Сейчас комментарии
отображаются без модерации.
Изменим условия выборки в
контролере FrontController.php
public function show ( $id )
{
$comments = Article :: where
( 'public' , '=', 1)-> find( $id )-
> comments()-> where
( 'public' , '=', '1' )-> get ();
$article = Article:: where
( 'public' , '=', 1)-> find( $id );
return view ( 'site.show' ,
[ 'article' =>
$article , 'comments' =>
$comments ]);
}
Теперь будут отображаться
комментарии, только со
значением public=1. Т.е. сейчас
у нас ни один комменарий не
будет отображаться.
Надо это исправить.
Пошаманим с админкой.
Добавим в файл
dashboard.blade.php пункт
<a href="{{action('CommentsController@show')}}">
Управление комментариями</a>
Я хочу использовать уже
существующий контролер
CommentsController, хотя это,
наверное, не правильно. Но я
хочу показать, как можно
использовать посредников ни
через маршруты, а прямо в
контролере.
Для этого изменим контролер
CommentsController
<?php
namespace App\Http\Controllers;
use App\Comments;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers
\Controller;
class CommentsController
extends Controller
{
public function __construct()
{
$this->middleware('auth',
['only' => ['show']]); //
посредник auth будет применен
только для метода show
}
public function save(Request
$request, $id)
{
$this->validate($request, [
'author' => 'required|max:100|
min:5',
'email' => 'required|email',
'content'=>'required|min:5|
max:400'
]);
$all=$request->all();//
Получаем все данные из формы в
массив
$all['article_id']=$id;//
Добавляем в массив id статьи
Comments::create($all);//
Сохраняем в базу
return back()->with
('message','Спасибо за
комментарий. После проверки он
будет опубликован');
}
}
И сам метод show
public function show ()
{
$comments = Comments :: all ();
return view
( 'admin.comments.show' ,
[ 'comments' => $comments ]);
}
И теперь добавим вид,
который будет отображать все
комментарии подряд resources/
views/admin/comments/
show.blade.php
@extends ( 'admin.main' )
@section ( 'content' )
< table >
< tr >
< td >Автор</ td >
< td > Email </ td >
< td >Комментарий</ td >
< td >Дата</ td >
< td >Статус</ td >
< td >Действие</ td >
</ tr >
@foreach ( $comments as $comment )
< tr >
< td >{{ $comment -> author }}</ td >
< td >{{ $comment -> email }}</ td >
< td >{{ $comment -> content }}</ td>
< td >{{ $comment -> created_at }}</
td>
< td >{{ $comment -> public }}</ td >
< td >< a href = "{{action
('CommentsController@delete',
['id'=>$comment-
>id])}}" >Удалить</ a >
< a href = "{{action
('CommentsController@published',
['id'=>$comment-
>id])}}" >Опубликовать</ a >
</ td >
</ tr >
@endforeach
</ table >
@endsection
И маршрут
Route::get('comments','CommentsController@show');
Я сразу добавлю маршруты,
для удаления комменатрия и
для публикации
Route :: get( 'comments/delete/
{id}' , 'CommentsController@delete' );
Route :: get( 'comments/published/
{id}' , 'CommentsController@published' );
И доделываем контролер
CommentsController.php
public function delete ( $id )
{
$comment = Comments:: find( $id );
$comment -> delete ();
return back ();
}
public function published ( $id )
{
$comment = Comments:: find( $id );
$comment -> public = 1;
$comment -> save();
return back ();
}
Теперь перейдем по адресу
site.ru/adminzone/comments
Мы должны увидеть таблицу
со всеми комментариями.
Который мы можем удалять или
публиковать.
Что здесь плохого? Мы не
видим к какой статье относится
комментарий. Чисто
теоритически, каким sql
запросом можно получить все
данные о комментарии, а
также название статьи? На
голом SQL — это будет так
select c.*, a.title from articles a, comments c where
c.article_id=a.id;
стороны, один комментарий,
какой-то один, конкретный
комментарий, принадлежит
только к одной статье. Такое
отношение называется один к
одному (One to One).
Пока каснемся отношения один
ко многим. В laravel, для
определения такого отношения
необходимо добавить
специальный метод в модель. В
нашем случае — это
модель Article. Добавим метод
comments
<?php
namespace App;
use Illuminate\Database\Eloquent
\Model;
class Article extends Model
{
protected $table="articles";
protected $fillable=
['title','content','preview','meta_description','
meta_keywords','category_id','comments_enable','
public'];
public function comments()
{
return $this->hasMany('App
\Comments','article_id','id');
}
}
article_id — это внешний
ключ, id — это локальный ключ.
Т.е. это ключи по которым
определяется связь между
коментариемя и статьей.
Теперь попробуем вывести
комментарии. Возвращаемся к
виду
resources/views/site/show.blade.php
И допишем
<div class="comments">
<ul>
@foreach($comments as $comment)
<li>Автор: {{$comment->author}}
<br>{{$comment->content}}</li>
@endforeach
</ul>
</div>
И в контролере
FrontController.php изменим
метод show, тот самый, который
отображает наши статьи
public function show ( $id )
{
$comments = Article :: where
( 'public' , '=', 1)-> find( $id )-
> comments; // выбираем все
комментарии, который относятся
к статье
$article = Article:: where
( 'public' , '=', 1)-> find( $id );
return view ( 'site.show' ,
[ 'article' =>
$article , 'comments' =>
$comments ]);
}
Теперь можно подобавлять
несколько комментариев к
статьи и посмотреть, что они
отображаются. Далее будем
усложнять.
Сейчас комментарии
отображаются без модерации.
Изменим условия выборки в
контролере FrontController.php
public function show ( $id )
{
$comments = Article :: where
( 'public' , '=', 1)-> find( $id )-
> comments()-> where
( 'public' , '=', '1' )-> get ();
$article = Article:: where
( 'public' , '=', 1)-> find( $id );
return view ( 'site.show' ,
[ 'article' =>
$article , 'comments' =>
$comments ]);
}
Теперь будут отображаться
комментарии, только со
значением public=1. Т.е. сейчас
у нас ни один комменарий не
будет отображаться.
Надо это исправить.
Пошаманим с админкой.
Добавим в файл
dashboard.blade.php пункт
<a href="{{action('CommentsController@show')}}">
Управление комментариями</a>
Я хочу использовать уже
существующий контролер
CommentsController, хотя это,
наверное, не правильно. Но я
хочу показать, как можно
использовать посредников ни
через маршруты, а прямо в
контролере.
Для этого изменим контролер
CommentsController
<?php
namespace App\Http\Controllers;
use App\Comments;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers
\Controller;
class CommentsController
extends Controller
{
public function __construct()
{
$this->middleware('auth',
['only' => ['show']]); //
посредник auth будет применен
только для метода show
}
public function save(Request
$request, $id)
{
$this->validate($request, [
'author' => 'required|max:100|
min:5',
'email' => 'required|email',
'content'=>'required|min:5|
max:400'
]);
$all=$request->all();//
Получаем все данные из формы в
массив
$all['article_id']=$id;//
Добавляем в массив id статьи
Comments::create($all);//
Сохраняем в базу
return back()->with
('message','Спасибо за
комментарий. После проверки он
будет опубликован');
}
}
И сам метод show
public function show ()
{
$comments = Comments :: all ();
return view
( 'admin.comments.show' ,
[ 'comments' => $comments ]);
}
И теперь добавим вид,
который будет отображать все
комментарии подряд resources/
views/admin/comments/
show.blade.php
@extends ( 'admin.main' )
@section ( 'content' )
< table >
< tr >
< td >Автор</ td >
< td > Email </ td >
< td >Комментарий</ td >
< td >Дата</ td >
< td >Статус</ td >
< td >Действие</ td >
</ tr >
@foreach ( $comments as $comment )
< tr >
< td >{{ $comment -> author }}</ td >
< td >{{ $comment -> email }}</ td >
< td >{{ $comment -> content }}</ td>
< td >{{ $comment -> created_at }}</
td>
< td >{{ $comment -> public }}</ td >
< td >< a href = "{{action
('CommentsController@delete',
['id'=>$comment-
>id])}}" >Удалить</ a >
< a href = "{{action
('CommentsController@published',
['id'=>$comment-
>id])}}" >Опубликовать</ a >
</ td >
</ tr >
@endforeach
</ table >
@endsection
И маршрут
Route::get('comments','CommentsController@show');
Я сразу добавлю маршруты,
для удаления комменатрия и
для публикации
Route :: get( 'comments/delete/
{id}' , 'CommentsController@delete' );
Route :: get( 'comments/published/
{id}' , 'CommentsController@published' );
И доделываем контролер
CommentsController.php
public function delete ( $id )
{
$comment = Comments:: find( $id );
$comment -> delete ();
return back ();
}
public function published ( $id )
{
$comment = Comments:: find( $id );
$comment -> public = 1;
$comment -> save();
return back ();
}
Теперь перейдем по адресу
site.ru/adminzone/comments
Мы должны увидеть таблицу
со всеми комментариями.
Который мы можем удалять или
публиковать.
Что здесь плохого? Мы не
видим к какой статье относится
комментарий. Чисто
теоритически, каким sql
запросом можно получить все
данные о комментарии, а
также название статьи? На
голом SQL — это будет так
select c.*, a.title from articles a, comments c where
c.article_id=a.id;
Как такое сделать с
помощью Eloquent? Разочарую,
нормально никак…. Можно
через жопу. Для этого будем
использовать связь один к
одному.
Допишим метод в модели
Comments
<?php
namespace App;
use Illuminate\Database\Eloquent
\Model;
class Comments extends Model
{
protected $table="comments";
protected $fillable=
['author','email','content','article_id'];
public function article()
{
return $this->hasOne('App
\Article','id','article_id');
}
}
И переделаем вид
show.blade.php
@extends ( 'admin.main' )
@section ( 'content' )
< table >
< tr >
< td >Статья</ td >
< td >Автор</ td >
< td > Email </ td >
< td >Комментарий</ td >
< td >Дата</ td >
< td >Статус</ td >
< td >Действие</ td >
</ tr >
@foreach ( $comments as $comment )
< tr >
< td >{{ App\ Comments:: find
( $comment -> article_id )-
> article-> title }}</ td > <!--
здесь изврат -->
< td >{{ $comment -> author }}</ td >
< td >{{ $comment -> email }}</ td >
< td >{{ $comment -> content }}</ td>
< td >{{ $comment -> created_at }}</
td>
< td >{{ $comment -> public }}</ td >
< td >< a href = "{{action
('CommentsController@delete',
['id'=>$comment-
>id])}}" >Удалить</ a >
< a href = "{{action
('CommentsController@published',
['id'=>$comment-
>id])}}" >Опубликовать</ a >
</ td >
</ tr >
@endforeach
</ table >
@endsection
Это кашмарное решение! Т.е.
при выводе каждого
комментария, делается запрос в
базу. 100 комментариев, 100
запросов в базу, 500
комменатриев… ну вы поняли.
Надо признать, что Eloquent
имеет ограничения. Для
сложных запросов, я
предпочитаю использовать
Query Builder.
Переделаем модель Commetns и
добавим свой метод, например,
FullComments, который будет
использоваться, только в
админке, для получения полной
таблицы с комментариями.
<?php
namespace App;
use DB;
use Illuminate\Database\Eloquent
\Model;
class Comments extends Model
{
protected $table="comments";
protected $fillable=
['author','email','content','article_id'];
static public function
FullComments()
{
return $comments=DB::table
('comments') //делаем выборку
из таблицы comments
->join
('articles','articles.id','=','comments.article_id
') // добавляем к выборке
таблицу comments с условием
->select
('comments.*','articles.title
as article') // указываем, что
будем выбирать, из comments
выбираем все, а из article,
только название title
->get();
//запрос будет такой "select
c.*, a.title from comments c
join articles a on
c.article_id=a.id;"
}
}
Обратите внимание, что
добавилось use DB в шапке.
Метод FullComments я сделал
статическим, что бы проще его
было вызывать.
Переделываем наш вид
show.blade.php
@extends ( 'admin.main' )
@section ( 'content' )
< table >
< tr >
< td >Статья</ td >
< td >Автор</ td >
< td > Email </ td >
< td >Комментарий</ td >
< td >Дата</ td >
< td >Статус</ td >
< td >Действие</ td >
</ tr >
@foreach ( $comments as $comment )
< tr >
< td >{{ $comment -> article }}</ td>
< td >{{ $comment -> author }}</ td >
< td >{{ $comment -> email }}</ td >
< td >{{ $comment -> content }}</ td>
< td >{{ $comment -> created_at }}</
td>
< td >{{ $comment -> public }}</ td >
< td >< a href = "{{action
('CommentsController@delete',
['id'=>$comment-
>id])}}" >Удалить</ a >
< a href = "{{action
('CommentsController@published',
['id'=>$comment-
>id])}}" >Опубликовать</ a >
</ td >
</ tr >
@endforeach
</ table >
@endsection
И контролер
CommentsController.php, метод
show
public function show ()
{
$comments = Comments :: FullComments
(); //вот здесь и пригодился
static метод
return view
( 'admin.comments.show' ,
[ 'comments' => $comments ]);
}
Вот теперь все красиво. Все
комментарии с названием
статьи выводятся одним
запросом. С комментариями
вроде,как все, основной костяк
готов. Но есть еще куча мест,
которые можно улучшить.
Например, сейчас не выводятся
ошибки, если комментарий не
прошел валидацию. Вообще
валидация — это тема
отдельной статьи, которую я
планирую написать. Во вторых
нужно защитить наши
«админские» методы в
контролере CommetnsController
(publised, delete). И еще, в
любом блоге, при выводе
последних статей на главной
странице, хочется видеть
количество комментариев. Как
это можно сделать?
С помощью Query Builder. Для
этого в модели Article.php
нужно добавить новый метод,
пусть будет называться preview
static public function preview ()
{
return $articles = DB :: table
( 'articles' )
-> where
( 'articles.public' , '=' , '1' )
-> leftJoin( 'comments' , function
( $query )
{
$query -> on
( 'comments.article_id' , '=' , 'articles.id' )
-> where
( 'comments.public' , '=' , '1' );
})
-> select ( 'articles.*' , DB :: raw
( 'count(comments.id) as
commentsCount' ))
-> groupBy ( 'articles.id' )
-> get ();
}
// запрос будет вот такой
select a . title , c . public , count
( c . id ) commentsCount from
articles a left join comments c
on (c . article_id = a . id and
a . public = 1) group by a . id ;
помощью Eloquent? Разочарую,
нормально никак…. Можно
через жопу. Для этого будем
использовать связь один к
одному.
Допишим метод в модели
Comments
<?php
namespace App;
use Illuminate\Database\Eloquent
\Model;
class Comments extends Model
{
protected $table="comments";
protected $fillable=
['author','email','content','article_id'];
public function article()
{
return $this->hasOne('App
\Article','id','article_id');
}
}
И переделаем вид
show.blade.php
@extends ( 'admin.main' )
@section ( 'content' )
< table >
< tr >
< td >Статья</ td >
< td >Автор</ td >
< td > Email </ td >
< td >Комментарий</ td >
< td >Дата</ td >
< td >Статус</ td >
< td >Действие</ td >
</ tr >
@foreach ( $comments as $comment )
< tr >
< td >{{ App\ Comments:: find
( $comment -> article_id )-
> article-> title }}</ td > <!--
здесь изврат -->
< td >{{ $comment -> author }}</ td >
< td >{{ $comment -> email }}</ td >
< td >{{ $comment -> content }}</ td>
< td >{{ $comment -> created_at }}</
td>
< td >{{ $comment -> public }}</ td >
< td >< a href = "{{action
('CommentsController@delete',
['id'=>$comment-
>id])}}" >Удалить</ a >
< a href = "{{action
('CommentsController@published',
['id'=>$comment-
>id])}}" >Опубликовать</ a >
</ td >
</ tr >
@endforeach
</ table >
@endsection
Это кашмарное решение! Т.е.
при выводе каждого
комментария, делается запрос в
базу. 100 комментариев, 100
запросов в базу, 500
комменатриев… ну вы поняли.
Надо признать, что Eloquent
имеет ограничения. Для
сложных запросов, я
предпочитаю использовать
Query Builder.
Переделаем модель Commetns и
добавим свой метод, например,
FullComments, который будет
использоваться, только в
админке, для получения полной
таблицы с комментариями.
<?php
namespace App;
use DB;
use Illuminate\Database\Eloquent
\Model;
class Comments extends Model
{
protected $table="comments";
protected $fillable=
['author','email','content','article_id'];
static public function
FullComments()
{
return $comments=DB::table
('comments') //делаем выборку
из таблицы comments
->join
('articles','articles.id','=','comments.article_id
') // добавляем к выборке
таблицу comments с условием
->select
('comments.*','articles.title
as article') // указываем, что
будем выбирать, из comments
выбираем все, а из article,
только название title
->get();
//запрос будет такой "select
c.*, a.title from comments c
join articles a on
c.article_id=a.id;"
}
}
Обратите внимание, что
добавилось use DB в шапке.
Метод FullComments я сделал
статическим, что бы проще его
было вызывать.
Переделываем наш вид
show.blade.php
@extends ( 'admin.main' )
@section ( 'content' )
< table >
< tr >
< td >Статья</ td >
< td >Автор</ td >
< td > Email </ td >
< td >Комментарий</ td >
< td >Дата</ td >
< td >Статус</ td >
< td >Действие</ td >
</ tr >
@foreach ( $comments as $comment )
< tr >
< td >{{ $comment -> article }}</ td>
< td >{{ $comment -> author }}</ td >
< td >{{ $comment -> email }}</ td >
< td >{{ $comment -> content }}</ td>
< td >{{ $comment -> created_at }}</
td>
< td >{{ $comment -> public }}</ td >
< td >< a href = "{{action
('CommentsController@delete',
['id'=>$comment-
>id])}}" >Удалить</ a >
< a href = "{{action
('CommentsController@published',
['id'=>$comment-
>id])}}" >Опубликовать</ a >
</ td >
</ tr >
@endforeach
</ table >
@endsection
И контролер
CommentsController.php, метод
show
public function show ()
{
$comments = Comments :: FullComments
(); //вот здесь и пригодился
static метод
return view
( 'admin.comments.show' ,
[ 'comments' => $comments ]);
}
Вот теперь все красиво. Все
комментарии с названием
статьи выводятся одним
запросом. С комментариями
вроде,как все, основной костяк
готов. Но есть еще куча мест,
которые можно улучшить.
Например, сейчас не выводятся
ошибки, если комментарий не
прошел валидацию. Вообще
валидация — это тема
отдельной статьи, которую я
планирую написать. Во вторых
нужно защитить наши
«админские» методы в
контролере CommetnsController
(publised, delete). И еще, в
любом блоге, при выводе
последних статей на главной
странице, хочется видеть
количество комментариев. Как
это можно сделать?
С помощью Query Builder. Для
этого в модели Article.php
нужно добавить новый метод,
пусть будет называться preview
static public function preview ()
{
return $articles = DB :: table
( 'articles' )
-> where
( 'articles.public' , '=' , '1' )
-> leftJoin( 'comments' , function
( $query )
{
$query -> on
( 'comments.article_id' , '=' , 'articles.id' )
-> where
( 'comments.public' , '=' , '1' );
})
-> select ( 'articles.*' , DB :: raw
( 'count(comments.id) as
commentsCount' ))
-> groupBy ( 'articles.id' )
-> get ();
}
// запрос будет вот такой
select a . title , c . public , count
( c . id ) commentsCount from
articles a left join comments c
on (c . article_id = a . id and
a . public = 1) group by a . id ;
Kaito (24.09.2015 в 15:13)
$user = new User ; //Вызываем модель $user -> name = 'John' ; $user -> save();
а вот этим я заинтересовался
$user = new User ; //Вызываем модель $user -> name = 'John' ; $user -> save();
а вот этим я заинтересовался
Создаем объект из класса, вставляем в значение имя Джон, вызываем функцию save.
Насколько понимает мой нубский мозг
[sukurich] (24.09.2015 в 15:28)
Kaito (24.09.2015 в 15:13)
$user = new User ; //Вызываем модель $user -> name = 'John' ; $user -> save();
а вот этим я заинтересовался
Создаем объект из класса, вставляем в значение имя Джон, вызываем функцию save.
Насколько понимает мой нубский мозг
Kaito (24.09.2015 в 15:13)
$user = new User ; //Вызываем модель $user -> name = 'John' ; $user -> save();
а вот этим я заинтересовался
Создаем объект из класса, вставляем в значение имя Джон, вызываем функцию save.
Насколько понимает мой нубский мозг
Я это понял, вопрос был в реализации
[sukurich] (24.09.2015 в 15:28)
Kaito (24.09.2015 в 15:13)
$user = new User ; //Вызываем модель $user -> name = 'John' ; $user -> save();
а вот этим я заинтересовался
Создаем объект из класса, вставляем в значение имя Джон, вызываем функцию save.
Насколько понимает мой нубский мозг
Kaito (24.09.2015 в 15:13)
$user = new User ; //Вызываем модель $user -> name = 'John' ; $user -> save();
а вот этим я заинтересовался
Создаем объект из класса, вставляем в значение имя Джон, вызываем функцию save.
Насколько понимает мой нубский мозг
все тут laravel.ru
Comments::create($all);
можно и так сохранить)) с авто заполнением!
Kaito, потому что такой код я давно изобрел 5лет назад шас все шагают нового совершенство!
mir007, потому что такой код я давно изобрел 5лет назад шас все шагают нового совершенство!
262110938 (24.09.2015 в 18:37)
mir007, потому что такой код я давно изобрел 5лет назад шас все шагают нового совершенство!
mir007, потому что такой код я давно изобрел 5лет назад шас все шагают нового совершенство!
а ну к продемонстрируй свой код
[sukurich], зачем мне демонстрировать код! Который и хватит лепить бумажек из говна
262110938 (24.09.2015 в 18:33)
Kaito, потому что такой код я давно изобрел 5лет назад шас все шагают нового совершенство!
Kaito, потому что такой код я давно изобрел 5лет назад шас все шагают нового совершенство!
зайди сюда laravel.ru и скажи что это говно фреймворк по твоему?