Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Отправил запрос в скайп.
Зачем сливать контроллеры?
А если изменится логика работы блога и новостей?
Опять разбивать?
Есть такая практика, как разделение логического функционала.
1. Модели разные используются
2. Может изменится логика
3. Роуты разные.
Сделать один общий абстракт? Так уж лучше общий трейт.
Но я не вижу смысла... ни абстракта, ни трейта.
Так как в контроллере много разного может быть... модели, валидаторы, ФормРеквесты, возвращаемый результат. Очень часто бывало так, что сегодня это схожий функционал, а завтра надо добавить пару строчек в одном из вариантов.
Вот и выходит, что чтобы объединить схожий функционал в контроллерах, необходимо продумать как будет реализована передача входящих данные, передача нужной модели, и возможность возвращать необходимые результат (вьюхи, json и прочее).
Я задумывался над подобными вопросами... но пришел к выводу, что это не имеет смысла. Лучше иметь несколько нормально описанных контроллера, чем общий абстракт или фасад... от контроллеров всё равно не уйти. Их по любому придется реализовывать в файлах.
Я обычно писал так:
namespace App\Http\Controllers\Admin;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;
use App\Classes\Models\User;
use App\Classes\Models\Payment;
use App\Http\Controllers\Controller;
1. Корень
2. Фрейм
3. Апп общее
4. Модуль
Когда начал писать под php7, стал писать в таком виде:
namespace App\Http\Controllers\Admin;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\{Validator, Auth, Config};
use App\Http\Controllers\Controller;
use App\Classes\Models\{User, Payment};
Классы, которые объявлены в корневом пространстве, я обычно не добавляю, а использую в виде \Exception...
try {
...
} catch( \Exception $e ) {
...
}
Исключения только тогда, когда таково требование стилизации заказчика или компании с которой я работаю.
Есть мнение, что если человек пишет тексты на естественном языке с ошибками, то это также ухудшает его восприятие, скорость и так далее. Вы так не думаете?
Да, в Ваших словах есть львиная доля правды. Но в данный момент мы пишем используя клавиатуру, что уже является не вполне естественным и конечно имеют место быть рефлекторные огрехи.
И в Нашем Великом Русском Языке очень много не естественных для нашего языка слов, позаимствованных у других народов с совсем другой фонемой.
Первично - это логика и содержание
Абсолютно с Вами согласен! Но! Если всё слитно и смазано написано, воспринять логику и содержание сложно.
А вот когда всё "удобно-читаемо", понимать описанную логику и содержание куда приятней и проще.
Это как говорить внятно, четко и громко вместо шепеляво, быстро и тихо.
Забавно, а для меня логичнее всегда ставить статические члены в начале класса.
В данном случае соглашусь с Вами. Но я говорю о коммерческом варианте кода, который был описан давно.
С другой стороны... всегда описываются в начале первично-важное, а затем остальное.
В классах первичным считаются (на сколько я знаю) локальные методы и свойства, а уж затем наследуемые и статика.
Но и тут можно спорить вечно.
PROCEDURE Install* (T: Task);
VAR t: Task;
BEGIN t := PrevTask;
WHILE (t.next # PrevTask) & (t.next ff T) DO t := t.next END;
IF t.next = PrevTask THEN T.next := PrevTask; t.next := T END
END Install;
Вот честно... ключевые слова в верхнем регистре мало встречал в Delphi... возможно в начальных версиях и попадалось такое безобразие... но с 3й версии точно не попадалось... даже в сторонних компонентах.
Вот так обычно было:
function Encrypt(const InString: string; StartKey, MultKey, AddKey: Integer): string;
var
i: Byte;
begin
Result := '';
for i := 1 to Length(InString) do
begin
Result := Result + Char( Byte(InString[ i ]) xor (StartKey shr 8) );
StartKey := ( Byte(Result[ i ]) + StartKey ) * MultKey + AddKey;
end;
end;
Мне это напоминает...
- "Я езжу на ВАЗе и мне не нравятся ваши Мерседесы! Наши автомобили лучшие в мире!"
Но!
- "Если кормить волка овсом всю жизнь, он будет считать, что это лучшая еда. Но стоит ему попробовать мясо, он больше не будет есть овёс!"
Я не буду спорить... но вот пример из фреймворка Laravel:
public function url($path)
{
$adapter = $this->driver->getAdapter();
if (method_exists($adapter, 'getUrl')) {
return $adapter->getUrl($path);
} elseif ($adapter instanceof AwsS3Adapter) {
return $this->getAwsUrl($adapter, $path);
} elseif ($adapter instanceof RackspaceAdapter) {
return $this->getRackspaceUrl($adapter, $path);
} elseif ($adapter instanceof LocalAdapter) {
return $this->getLocalUrl($path);
} else {
throw new RuntimeException('This driver does not support retrieving URLs.');
}
}
В коммерческом виде было бы так:
public function url( $path )
{
$adapter = $this->driver
->getAdapter();
if( method_exists($adapter, 'getUrl') ) {
return $adapter->getUrl( $path );
} else if( $adapter instanceof AwsS3Adapter ) {
return $this->getAwsUrl( $adapter, $path );
} else if( $adapter instanceof RackspaceAdapter ) {
return $this->getRackspaceUrl( $adapter, $path );
} else if( $adapter instanceof LocalAdapter ) {
return $this->getLocalUrl( $path );
} else {
throw new RuntimeException(
'This driver does not support retrieving URLs.'
);
}
}
Разве так не лучше?
Зачем было исковеркивать PSR-1/PSR-2 и обзывать эту смесь "коммерческим" кодом?
Коммерческий код появился за долго до появления всяких PSRов и над стилизацией работали куча оченб грамотных людей. В то время как PSR появился позже и много было заимствовано из коммерческого кода с изменениями.
Коммерческих код не использовался на PHP никогда... только на C (C++) и Pascal'е.
И на сколько я знаю, PSR был принят сообществом только потому, что нужно было стандартизировать стилизацию кода на PHP. И принят он был чисто условно на пальцах... типа "А давайте так писать?", а давайте!
Над коммерческим кодом работали и доводили до идеала. Над PSR никто не работал... просто притянули за уши с других языков... по большей части с C++.
Я программирую ещё с 1987 года на С и C++, на Delphi с 1995. И был владельцем BBS (Maximus 3.0 с фидо ретранслятором)... и об интернете тогда ещё никто "слыхом не слыхива"... я не говорю уже о PHP и PSR.
Но то, что я вижу сейчас в PSR меня удивляет.
Вот и хочется показать людям более понятную стилистику, которая "слизывается мозгом" и не приходится напрягать глаза и мозги, что бы понять, что же там написано.
Давным давно, когда люди забивали гвозди использую ASM и готовили DOS на Quick C...
О чём это я? А!
Да, есть такое понятие как "Коммерческий код". Это некая форма стилизации кода для лучшего восприятия кода мозгом.
Такой вид форматирования сильно облегчает понимание сути описанного в коде алгоритма.
К сожалению о нём забили, а многие даже и не слышали.
Данный вид форматирования был создан группой людей (из FidoNet). Использовался он для написания коммерческих программ, которые продаются вместе с исходным кодом.
На сегодняшний день почти все используют PSR и не задумываются о таких вещах, как скорость восприятия чужого кода на интуитивном уровне.
Вот и хочу Вам... рассказать... или напомнить... или предложить стиль кода "Коммерческий".
Чем он отличается и какие правила он применяет:
Большинство пишет код так:
class Text {
const TEST = 1;
public static $test = '';
public $filename = '';
public $name = '';
private $a;
protected $b;
public functuion getA() {
if(self::$test == self::TEST) {
return $this->a;
}
/* Или такой вариант
if (self::$test == self::TEST) {
return $this->a;
}
*/
return null;
}
}
Коммерческий код выглядит так:
class Text
{
// Константы всегда в начале
const TEST = 1;
// Затем всегда паблик
public $filename = '';
public $name = '';
// Потом протектед
protected $b;
// и приватные
private $a;
// Далее так же и статические
public static $test = '';
// Такое же правило относится и к методам
public functuion getA()
{
// Обязательно if( пробел условие пробел )
// if( - мозг воспринимает лучше чем if (
// условия типа
// if(!$data) или if (! $data)
// воспринимается хуже чем if( !$data )
if( self::$test == self::TEST ) {
return $this->a;
}
return null;
}
}
все переменные и свойства в snake_case
все методы в lowerCamelCase
все функции (процедуры) в snake_case
все имена классов в UpperCamelCase
описание последовательности вызова методов:
return $users->default()
->actived()
->get();
а не:
return $users->default()->actived()->get();
все простые условия типа:
if( self::$test == self::TEST ) {
return $this->a;
}
return null;
должны описываться так:
return ( self::$test == self::TEST ) ? $this->a : null;
почему скобки? для визуального отделения условия от логики;
При длинных вариантах:
return ( self::$test == self::TEST ) ? $users->default()->actived()->get() : $users->actived()->get();
Надо писать так:
return ( self::$test == self::TEST )
? $users->default()->actived()->get()
: $users->actived()->get();
Это будет восприниматься быстрей и понятней.
Я часто встречаю записи такого вида и они просто неудобно-читабельны:
return $this->response($this->presenter->full($infraction));
или:
$infraction->users()->attach($original->users->pluck('id'));
И исправляю их на:
return $this->response(
$this->presenter->full(
$infraction
)
);
и:
$infraction->users()
->attach(
$original->users
->pluck('id')
);
Так воспринимается куда более быстрей.
Много всего, но Коммерческий код воспринимается всеми программистами (и профи и новичками) с одинаковой скоростью и лёгкостью.
Что скажете?
А зачем return; в конце если это void да ещё конец метода?
Что такое SnapshotsTeamspeakVirtualServers? Модель?
Что такое new TeamSpeak( $this->instance_id )? Тоже модель?
Почему не
if( ($data = $this->GetAllServersSnapshots()) && is_array($data) )
{
SnapshotsTeamspeakVirtualServers::create( $data );
}
Много не понятного... нельзя просто взять и ответить почему небо синее...
Утечка может происходить из-за вновь создающегося объекта(ов) и хранящегося в памяти...
Типа
return self::$a[] = new Obj();
А данный метод может вообще не причём.
Проще, но только новичку. Читабельнее только для того, кто только что это написал. Другому разработчику или автору кода через несколько месяцев прочитать это будет довольно сложно.
Если всё (код) нормально оформлено и грамотно прокоментированно, никаких проблем не будет. Вся логика по шагам будет видна сразу и не придётся искать где данные перебиваются. А другому разработчику так вообще проще-простого, зашел по роуту и всё увидел.
Вобщем, на вкус и цвет все фломастеры разные.
Просто я уже много раз сталкивался (и не только на Laravel) с тем, что приходится очень долго искать где и почему меняется 1 на 2. Вот именно в таких "дебрях"... в контроллере 2 строчки... и начинаешь 2 часа рыться по коду, вместо того, что бы сделать работу.
В таких случаях нужно использовать преобразователи (mutators), значения по умолчанию и т.д.
А если зависимость значений куда более сложна... и важна очередность проверки с различными переключениями в зависимости от появившихся логических изменений, а не единичные. где в зависимости от определенных входящих данных будет зависеть значение некоторых переменных, а уже от их значений зависит другие значения? Как тогда?
Мутаторов не всегда достаточно, array_merge тоже не всегда подойдёт... ведь важна последовательность логики.
Вот и выходит, что категоричность в данном случае не однозначна. Ваш вариант хорош, но не однозначен. В крупных проектах очень часто при сохранении данных нужно учитывать различные факторы которые в зависимости от логических изысканий могут меняться в процессе вычисления значений.
Конечно, часть логики можно вынести на фронт, что-то в валидатор/реквест, что-то убрать в дефолты и часть в модели, но этого бывает не достаточно и потом очень сложно искать, что и где не так.
Проще и "читабельней" всю логику описать в контроллере, в одном месте и в случае необходимости не рыться в куче файлах, а просто в контроллере поменять логику.
А так получается ООП программирование ради ООП программирования.
Можно сказать просто я хочу домой... а можно рассписать как Вы хотите в одном месте, почему Вы хотите домой в другом, в третьем как Вы будите идти домой, в четвёртом по какой дороге... а в итоге, если кто-то после Вас полезет в код, будет долго искать где у Вас описание цвета сандалей, в которых вы идёте домой.
Отлично написано! Респект автору!
Но всё же есть некие... так сказать "несогласия":
1. Название переменных и свойств классов таки правильней писать в snake case. И это не только на PHP. Но на PHP принято всеми. Lower Camel Case всё же для методов.
2. Вот здесь:
$category->article()->create($request()->all());
Тоже не согласен. В большинстве простых случаем это Верно, но частенько бывает необходимость расставлять значения по условиям.
Если не заполнено это поле и заполнено то поле, значит значение в 1... А если не заполнены оба, значит 2... или если заполнено То без Этого, значит 3...
Таких примеров масса в средних и больших проектах и тогда обработку, и приведение данных правильней (на мой взгляд) делать в контроллере... ведь он для этого и создан.
тогда получается что-то вроде:
$category->article()->create([
'title' => $request->title,
'date' => $request->date ? $request->date : now(),
]);
Короткий и читаемый синтаксис.
Да и более того, в Laravel каждый раз добавляется много хелперов которые мало документированы... изучайте код.
Или создавайте свои хелперы типа:
if( !function_exists('is_auth') ) {
function is_auth()
{
return auth()->check();
}
}
if( !function_exists('is_ajax') ) {
function is_ajax()
{
return \Request::ajax();
}
}
Добавлю ещё пару-тройку хелперов авторизации:
auth()->check(); // \Auth::check();
auth()->user();
auth()->id();
И добавлю от себя...
- "Правильное описание модели и связанных с ней релейшенов это уже 30% приложения!"
Я бы всё таки заводил пользователя (Admin или Superuser) в миграции с заданным паролем.
На Laravel пишу где-то года 3. На PHP больше 10 лет. В основном Backend с MySQL (MariaDB), но есть опыт с jQuery + Bootstrap. Хочется найти интересный проект и приятную команду. Живу в Домодедово (Московская область), езжу на авто. Желательно не дальше полутора часов езды.
Хочется найти работу на долгие годы.
Шорткоды нужны для того чтобы человек, который работает в редакторе мог в определенный момент вставить нужный функционал в контент из текстового редактора путем вставки в него шорткода, например пусть cats - это котики, давайте ка выведем вот на этой странице котиков, и вставляет шорткод - [cats]. При чем тут циклы с массивами, в теле функции шорткода можно реализовать все что угодно, а вот как внедрить сам механизм, пока не знаю, пока есть идея по распарсиванию контента на предмет шорткода, может кто-нибудь знает более элегантное решение, кстати формат шорткодов не обязательно в скобках, это для примера.
Старые добрые BB коды... Судя по вопросу, как я понимаю, контент хранится в базе... тогда только парсить... или писать быблиотеку для создания шорткодв... что бы можно было привязывать короткий код к методам классов... типа:
\BB::add('cats', function() {
});
или
\BB::add('cats', '\App\Lib\Cats', 'getCatList');
А после получения текста из базы, сделать:
$text = \BB::make( $post->content );
Ну, по крайней мере, я бы что-то вроде этого сделал...