Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Один вопрос, а зачем воять свой велосипед? Конфиг кешируется, а не считывается каждый раз заново. Конфигурирование в ларавеле максимально прост.
Но я бы хотел использовать более простой синтаксис для собственных конфигураций, и в первую очередь это JSON5.
Проще чем ассоциативный массив? Не думаю. Если вы используете любую систему контроля версий, предположу что ваш конфиг туда тоже попадит, что не есть хорошо.
Конечно же вы можете делать как вы посчитаете нужным, но если у вас хотя бы 1000 запросов в секунду ни о какой производительности я бы не заморачивался
Смотрите ваш код, проблема явно не в ларавел. Вы инициализируете или вызываете код с ваших "setings" где-то раньше.
Конфиг кешируется. А чем вас решение c .env не устроило? Прописываете несколько подключений и при запросах указываете имя подключения. И с точки безопасности в коде даже если это в рантайме хардкодить доступы любого характера очень скверная привычка.
Если вы используете тот же гит, в комите доступы лежат.
В модели
protected $primaryKey = "ID";
Из реального проекта вырезка кода. Пробуйте, документацию почитайте
class BotApi
{
protected $botToken;
protected $httpUrl;
protected $client;
/** @var Api */
protected $api;
/**
* BotApi constructor.
* @throws \Telegram\Bot\Exceptions\TelegramSDKException
*/
public function __construct()
{
$this->botToken = config('telegram.bot_token');
$this->httpUrl = "[url]https://api.telegram.org/bot[/url]" . $this->botToken . "/";
$this->client = new Client($this->httpUrl);
$this->api = new Api($this->botToken);
}
/**
* @return Api
*/
public function getApi()
{
return $this->api;
}
public function sendMessage($message, $chat_id, $keyboard = [['0. Назад']])
{
$reply_markup = $this->api->replyKeyboardMarkup([
'keyboard' => $keyboard,
'resize_keyboard' => false,
'one_time_keyboard' => false
]);
$this->api->sendMessage([
'chat_id' => $chat_id,
'text' => $message,
'reply_markup' => $reply_markup
]);
}
}
Я не могу получить 'chat_id'.
public function __construct(BotApi $bot)
{
$this->bot = $bot;
}
public function webhook()
{
/** @var Update $update */
$update = $this->bot->getApi()->getWebhookUpdates();
$message = trim($update->getMessage()->getText());
$data = [
'update_id' => $update->getUpdateId(),
'message_id' => $update->getMessage()->getMessageId(),
'chat_id' => $update->getMessage()->getChat()->getId(),
'userName' => $update->getMessage()->getChat()->getUsername(),
'text' => $update->getMessage()->getText(),
'photo' => $update->getMessage()->getPhoto()
];
}
Я бы на вашем месте создал класс, в сервис контейнере зарегистрировал его как синглтон, заполнял нужными свойствами в миддлеваре и через внедрение зависимостей получал бы где-угодно.
В вашем случае профит близится к нулю. Конструктор нужен для первоначальной инициализации класса. Например логика лежит по нескольким методам, которым нужны какие-то общие какие-то первоначальные данные.
https://developers.facebook.com/tools/explorer, выбираете приложение и маркеры доступа.
Подставляете и получаете токен.
https://graph.facebook.com/v2.11/oauth/ … client_id=[апп айди]&client_secret=[секретный ключ приложения]&fb_exchange_token=[маркер доступа]
Не претендую на единственное верное и правильное решение. В моем случае надо было быстро и что бы работало. Работает. Если кто-то может подсказать иное решение - с благодарностью почитаю.
Токены фб живут 60 дней, если в группу постите. У одного из клиентов сделали постинг в твиттер, фб сразу оттуда подтягивает и с токенами проблем нет. Но это уже
как вы пожелаете.
Ставите через композер, почитайте официальные доки:
waavi/url-shortener
thujohn/twitter
facebook/graph-sdk
Код выдернул прям с проекта. Если не поймете пишите
protected function publishTwitter(SocialPublishing $item)
{
SocialLog::newInstance()->info("app", $item->toArray());
/** @var Apartment $apartment */
$apartment = $item->apartment()->first();
if(!is_null($apartment)) {
$transform = (new ApartmentTransformer())->transformBasic($apartment, "ca");
$twitterPost = \Twitter::postTweet([
'status' => $transform->title . " " . UrlShortener::driver('google')->shorten($transform->url),
'format' => 'object'
]);
$item->twitterId = $twitterPost->id_str;
$item->twitterStatus = 1;
$item->save();
return $item;
}
return null;
}
protected function publishFacebook(SocialPublishing $item)
{
SocialLog::newInstance()->info("app", $item->toArray());
/** @var Apartment $apartment */
$apartment = $item->apartment()->first();
if(!is_null($apartment)) {
$transform = (new ApartmentTransformer())->transformBasic($apartment, "ca");
$fb = new Facebook([
'app_id' => config('social.facebook.appId'),
'app_secret' => config('social.facebook.app_secret'),
'default_graph_version' => config('social.facebook.default_graph_version')
]);
$groupId = config('social.facebook.fb_group_id');
$parts[] = $transform->typeApartmentOperations;
$parts[] = $transform->bedRoomsValue;
$parts[] = $transform->locationsValue;
$parts[] = $transform->price;
$linkData = [
'link' => $transform->url,
// 'link' => "[url]http://pisos.ad/anunci-9857/pis-lloguer-encamp-andorra[/url]",
'message' => implode(", ", $parts),
];
try {
// Returns a `Facebook\FacebookResponse` object
$response = $fb->post("/{$groupId}/feed", $linkData, config('social.facebook.default_access_token'));
$graphNode = $response->getGraphNode();
$item->fbId = $graphNode['id'];
$item->fbStatus = 1;
$item->save();
} catch(FacebookResponseException $e) {
SocialLog::newInstance()->info("FacebookResponseException: " . $e->getMessage());
SocialLog::newInstance()->info($e->getTraceAsString());
return null;
} catch(FacebookSDKException $e) {
SocialLog::newInstance()->info("FacebookSDKException: " . $e->getMessage());
SocialLog::newInstance()->info($e->getTraceAsString());
return null;
}
return $item;
}
return null;
}
@foreach ($users as $user) {
{{ $user->name }};
}
так я не усложняю это требования разработки. Склад один а баз будет 33? Это как раз и будет вызывать глобальные трудности.
Вчитайтесь внимательно, что я вам про бд написал.
Перенесите локигу из уровня приложения в бд (триггеры) или транзакции
static function getImgColor($id)
{
$color = DB::table('colors')->where('id', $id)->first();
if(!is_null($color)) {
$img = ' <a class="light" data-title="' . $color->title . '" href="/' . $color->img . '">
<img class="example-image" src="/' . $color->img . '" alt="">
<p class="color_name">' . $color->title . '</p>
</a>';
return $img;
}
return "";
}
А так вас не устроит?
Path Customization
When a user is successfully authenticated, they will be redirected to the /home URI. You can customize the post-authentication redirect location by defining a redirectTo property on the LoginController, RegisterController, and ResetPasswordController
Разве нельзя использовать snake_case?
Можно конечно, но если у вас структура бд уже создана не вами или возможно предполагается использовать бд совместно с другими сервисами написанными на c# например. Там есть свои договоренности и по именованию полей, методов и свойств. Конечно все можно переопределить атрибутами и тд, но зачем? Я работаю очень часто с laravel и asp.net, net core, поэтому для меня использовать кэмел кейс как-то более эстетично. Это все субьективно и зависит от команды разработчиков.
Спасибо за труд. В целом все хорошо описано для начинающего, а вот с именованием столбцов в бд вопрос довольно относительный и в зависит от используемой бд. Например, работая с sqlserver практически всегда имена полей в camel case с ключами вида ИмяМоделиId или ИмяМоделиID.
SPR, это конечно хорошо. Но, если у вас очень простое приложение и метод контроллера укладывается в 10-15 строк без необходимости где-либо переиспользовать, то не вижу смысла размазывать код, усложняя себе жить и плодить кучу классов.
Ко всем бест практикам нужно прийти, а это понимание появляется отнюдь не сразу. Например, поставил задачу перед жуниором написать простой парсер хмл, на базе уже существующего кода. В примере использовались интерфейсы, абстрактные классы, инжектились через ioc. Так вот он пытался по строкам сделать тоже самое буквально и шаг влево, шаг вправо - пожимал плечами, мол не знаю, не работает и тд.
На практике часто использую Request только в контроллере, сформировал нужный мне пакет (это или класс или массив, вопрос предпочтений)
/**
* Return pagination list of the apartments
* @param Request $request
* @param $language
* @param int $page
* @param int $pageSize
* @return \Illuminate\Http\JsonResponse
*/
public function getApartmentsJson(Request $request, $language, $page = 1, $pageSize = 10)
{
$pLang = $this->getLanguage($language);
//get filter value
$data = $request->all();
$request = (new ApartmentRequest())
->setReference(array_get($data, 'reference'))
->setTypeOperation(array_get($data, 'typeOperation'))
->setTypeApartment(array_get($data, 'typeApartment'))
->setProvince(array_get($data, 'province'))
->setAreaPlotMin(array_get($data, 'areaPlotMin'))
->setAreaPlotMax(array_get($data, 'areaPlotMax'))
->setBedrooms(array_get($data, 'bedrooms'))
->setPriceMin(array_get($data, 'priceMin'))
->setPriceMax(array_get($data, 'priceMax'))
->setOrderBy(array_get($data, 'orderBy'));
return response()->json($this->getApartments($request, $pLang, $page, $pageSize));
}
И дальше пакет гоняю как захочется.
/**
* Return list of the apartments, using request can use filter and order functionality
* @param ApartmentRequest $request
* @param PLanguage $language
* @param int $page
* @param int $pageSize
* @return ApartmentResult
*/
public function getApartments(ApartmentRequest $request, PLanguage $language, $page = 1, $pageSize = 1)
{
if($pageSize > 50)
$pageSize = 10;
$shortName = $language->shortName;
$builder = $this->builder($request);
// if run after get() return 0;
$countRow = $builder->count();
$client = Auth::user();
$transformer = new ApartmentTransformer();
$apartments = $builder->skip(($page - 1) * $pageSize)->take($pageSize)->get()->transform(function(Apartment $item) use ($transformer, $shortName, $client) {
return $transformer->transformBasic($item, $shortName, $client);
});
$result = new ApartmentResult($apartments, new Page($countRow, $page, $pageSize), $language);
return $result;
}
В большинстве случаев вы правы, однако с таким подходом нужно писать все с нуля. И как показывает мой опыт, в вашем собственном велосипеде ошибки будут, хотя бы потому что вы используете язык написанный не вами, среду созданную не вами и еще куча факторов где другие могут накосячить. Так как по моему уже опыту, программирование - это написание кода, с минимальными затратами времени по-возможности и попыткой избежать (пофиксить) багов, оставленных не мною. И потом, как вы сказали, с ростом опыта возникает способность мыслить и создать что-то свое. До тех пор пока работает все относительно хорошо, я бы предпочел потратить время на отдых и в дали от работы.
Тема бесконечна для холивара, все учатся на ошибках. Моя самая дорогая ошибка мне обошлась в 3 млн. руб, поэтому я параноидально отношусь только к критически важным частям процесса. В остальном, если могу время сэкономить - то почему нет?
Любые инструменты для автоматизации будут забирать у тебя степень свободы и контроля. Чтобы от них был толк, проекту нужна критическая масса. ...это стрельба из пушек по воробьям...
Ну не знаю, тут я с вами не соглашусь. Перешел на deployer и очень доволен. Да, отнял время на чтение документации и тесты во время настройки. Но это окупилось с лихвой. Если нужно исправление или запуск миграции или выполнить еще что-либо, создать кастомную команду и тд. Разработка локально, есть тестовая среда, есть продакшн. Выкатка кода на них всего в одну команду. Возможность откатиться на предыдущую версию тоже одной командой. К слову во время деплоя, если была ошибка подмена в проде не произойдет.
Другой вопрос, если разработчик все еще новичок в ларе, стоит повременить.
Зачем? Я бы создал 2 таблицы, Основное меню (табл1) и дети этого меню (табл2) с парент_ид. Повесил бы форейгн кей и забыл бы про обеспечения целостности. А так вы рискуете убить запись родителя и оставить всех детей, это раз. Вам потребуется повесить логику обеспечения целостности в бэкенд, это два. Вы можете получить циклическую ссылку, это три. Аргументов не достаточно?
Ваше решение не логично и нарушает все принципы нормализации бд. С другой стороны, если вы хотите хранить в бд переводы с всех таблиц, добавьте поле типа таблицы в таблицу с переводами, а в основную модель метод который возвращает по ид и этому полю-типу строки.