Ниже приведен пример метода «store» моего контроллера Admin / MoviesController. Это уже кажется довольно большим, и метод «обновления» будет еще больше.
Алгоритм это:
Мои вопросы:
Есть ли лучшие практики? Я говорю не о MVC, а о возможностях Laravel. На данный момент, чтобы сохранить некоторую логику за сценой, я использую только Запрос на проверку.
public function store(CreateMovieRequest $request) {
$movie = Movies::create($request->except('poster'));
/* Uploading poster */
if ($request->hasFile('poster')) {
$poster = \Image::make($request->file('poster'));
$poster->fit(250, 360, function ($constraint) {
$constraint->upsize();
});
$path = storage_path() . '/images/movies/'.$movie->id.'/';
if(! \File::exists($path)) {
\File::makeDirectory($path);
}
$filename = time() . '.' . $request->file('poster')->getClientOriginalExtension();
$poster->save($path . $filename);
$movie->poster = $filename;
}
/* If 'Meta Title' is empty, then fill it with the name of the movie */
if ( empty($movie->seo_title) ) {
$movie->seo_title = $movie->title;
}
/* If 'Meta Description' is empty, then fill it with the description of the movie */
if ( empty($movie->seo_description) ) {
$movie->seo_description = $movie->description;
}
// Apply all changes
$movie->save();
/* Parsing comma separated string of genres
* and attaching them to movie */
if (!empty($request->input('genres'))) {
$genres = explode(',', $request->input('genres'));
foreach($genres as $item) {
$name = mb_strtolower(trim($item), 'UTF-8');
$genre = Genre::where('name', $name)->first();
/* If such genre doesn't exists in 'genres' table
* then we create a new one */
if ( empty($genre) ) {
$genre = new Genre();
$genre->fill(['name' => $name])->save();
}
$movie->genres()->attach($genre->id);
}
}
/* Parsing comma separated string of countries
* and attaching them to movie */
if (!empty($request->input('countries'))) {
$countries = explode(',', $request->input('countries'));
foreach($countries as $item) {
$name = mb_strtolower(trim($item), 'UTF-8');
$country = Country::where('name', $name)->first();
if ( empty($country) ) {
$country = new Country();
$country->fill(['name' => $name])->save();
}
$movie->countries()->attach($country->id);
}
}
/* Parsing comma separated string of directors
* and attaching them to movie */
if (!empty($request->input('directors'))) {
$directors = explode(',', $request->input('directors'));
foreach($directors as $item) {
$name = mb_strtolower(trim($item), 'UTF-8');
// Actors and Directors stored in the same table 'actors'
$director = Actor::where('fullname', trim($name))->first();
if ( empty($director) ) {
$director = new Actor();
$director->fill(['fullname' => $name])->save();
}
// Save this relation to 'movie_director' table
$movie->directors()->attach($director->id);
}
}
/* Parsing comma separated string of actors
* and attaching them to movie */
if (!empty($request->input('actors'))) {
$actors = explode(',', $request->input('actors'));
foreach($actors as $item) {
$name = mb_strtolower(trim($item), 'UTF-8');
$actor = Actor::where('fullname', $name)->first();
if ( empty($actor) ) {
$actor = new Actor();
$actor->fill(['fullname' => $name])->save();
}
// Save this relation to 'movie_actor' table
$movie->actors()->attach($actor->id);
}
}
// Updating IMDB and Kinopoisk ratings
if (!empty($movie->kinopoisk_id)) {
$content = Curl::get('http://rating.kinopoisk.ru/'.$movie->kinopoisk_id.'.xml');
$xml = new \SimpleXMLElement($content[0]->getContent());
$movie->rating_kinopoisk = (double) $xml->kp_rating;
$movie->rating_imdb = (double) $xml->imdb_rating;
$movie->num_votes_kinopoisk = (int) $xml->kp_rating['num_vote'];
$movie->num_votes_imdb = (int) $xml->imdb_rating['num_vote'];
$movie->save();
}
return redirect('/admin/movies');
}
Вам нужно подумать о том, как вы могли бы повторно использовать код, если вам нужно использовать его в других классах или модулях проекта. Для начала вы можете сделать что-то вроде этого:
Модель фильма, может быть улучшен для того, чтобы:
Посмотрите, как Movie реализует функции:
class Movie{
public function __construct(){
//If 'Meta Title' is empty, then fill it with the name of the movie
$this->seo_title = empty($movie->seo_title)
? $movie->title
: $otherValue;
//If 'Meta Description' is empty,
//then fill it with the description of the movie
$movie->seo_description = empty($movie->seo_description)
? $movie->description
: $anotherValue;
$this->updateKinopoisk();
}
/*
* Parsing comma separated string of countries and attaching them to movie
*/
public function attachCountries($countries){
foreach($countries as $item) {
$name = mb_strtolower(trim($item), 'UTF-8');
$country = Country::where('name', $name)->first();
if ( empty($country) ) {
$country = new Country();
$country->fill(['name' => $name])->save();
}
$movie->countries()->attach($country->id);
}
}
/*
* Update Kinopoisk information
*/
public function updateKinopoisk(){}
/*
* Directors
*/
public function attachDirectors($directors){ ... }
/*
* Actores
*/
public function attachActors($actors){ ... }
/*
* Genders
*/
public function attachActors($actors){ ... }
}
плакат, Вы можете рассмотреть возможность использования поставщика услуг (я покажу этот пример, потому что я не знаю вашу модель плаката
похоже):
public class PosterManager{
public static function upload($file, $movie){
$poster = \Image::make($file);
$poster->fit(250, 360, function ($constraint) {
$constraint->upsize();
});
$path = config('app.images') . $movie->id.'/';
if(! \File::exists($path)) {
\File::makeDirectory($path);
}
$filename = time() . '.' . $file->getClientOriginalExtension();
$poster->save($path . $filename);
return $poster;
}
}
Конфиг файл
Попробуйте использовать файлы конфигурации для хранения соответствующих констант / данных приложения, например, для хранения пути к изображениям фильмов:
'images' => storage_path() . '/images/movies/';
Теперь вы можете позвонить $path = config('app.images');
во всем мире. Если вам нужно изменить путь, необходима только настройка файла конфигурации.
Контроллеры как внедренный класс.
Наконец, контроллер используется как класс, где вам нужно только ввести код:
public function store(CreateMovieRequest $request) {
$movie = Movies::create($request->except('poster'));
/* Uploading poster */
if ($request->hasFile('poster')) {
$file = $request->file('poster');
$poster = \PosterManager::upload($file, $movie);
$movie->poster = $poster->filename;
}
if (!empty($request->input('genres'))) {
$genres = explode(',', $request->input('genres'));
$movie->attachGenders($genders);
}
// movie->attachDirectors();
// movie->attachCountries();
// Apply all changes
$movie->save();
return redirect('/admin/movies');
}
Других решений пока нет …