namespace app\components;
use yii\web\UrlRuleInterface;
use yii\base\BaseObject;
class CarUrlRule extends BaseObject implements UrlRuleInterface
{
public function createUrl($manager, $route, $params)
{
if ($route === 'car/index') {
if (isset($params['manufacturer'], $params['model'])) {
return $params['manufacturer'] . '/' . $params['model'];
} elseif (isset($params['manufacturer'])) {
return $params['manufacturer'];
}
}
return false; // данное правило не применимо
}
public function parseRequest($manager, $request)
{
$pathInfo = $request->getPathInfo();
if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches)) {
// Ищем совпадения $matches[1] и $matches[3]
// с данными manufacturer и model в базе данных
// Если нашли, устанавливаем $params['manufacturer'] и/или $params['model']
// и возвращаем ['car/index', $params]
}
return false; // данное правило не применимо
}
}
$utms = [
'utm_source' => $_POST['utm_source'] ?? null,
'utm_medium' => $_POST['utm_medium'] ?? null,
'utm_campaign' => $_POST['utm_campaign'] ?? null,
'utm_term' => $_POST['utm_term'] ?? null,
'utm_content' => $_POST['utm_content'] ?? null,
];
// отфильтрует значения по empty
$utms = array_filter($utms);
// отфильтрует только null
$utms = array_filter($utms, fn($val) => $vall !== null)
@app.before_request
и делаем следующее:db = SQLAlchemy(app)
with app.app_context():
from .models import *
db.create_all()
create_default_admin()
@app.cli.command('init_db')
def init_db():
from .models import *
db.create_all()
@app.cli.command('init_admin')
def init_admin():
from .models import User
db.session.add(User(username='admin', ...))
db.session.commit()
>>> flask --app project.app init_db
>>> flask --app project.app init_admin
pydantic.error_wrappers.ValidationError: 1 validation error for InlineKeyboardMarkup
inline_keyboard
field required (type=value_error.missing)
class aiogram.types.inline_keyboard_markup.InlineKeyboardMarkup(*,
inline_keyboard: List[List[InlineKeyboardButton]], // required
**extra_data: Any
)
flush()
в процессе обработки preUpdate
приводит к бесконечной рекурсии, ибо обработчик события вызывается в процессе выполнения предыдущего вызова flush()
.persist()
, remove()
и т.п. в процессе обработки событий доктрины может привести к неожиданным результатам. Данные просто могут быть не сохранены, как минимум. Крайне не рекомендую менять какие-либо данные в Entity, EM/UoW при обработке событий доктрины.OrderStatusChanged
. Но лучше использовать более конкретные события вроде OrderCompleted
и OrderCanceled
. flush()
.$this->em->flush();
$this->events->dispatch(new OrderCompleted($order->id));
// или
$this->em->flush();
$this->notificationCreator->createChangeStatusNotification($order->getCustomer());
public function preUpdate(PreUpdateEventArgs $args)
{
$entity = $args->getObject();
if (!$entity instanceof Order) {
return;
}
$this->logger->info($entity);
$onlyStatusChanged = count($args->getEntityChangeSet()) === 1 && $args->hasChangedField('status');
if ($onlyStatusChanged) {
$this->notificationsCreator->createChangeStatusNotification($entity->getCustomer());
}
// много кода...
}
@else
для @auth
?@auth
// ...
@endauth
@guest
// ...
@endguest
-- если пользователь уже существует, то просто игнорировать
INSERT INTO 'users' (user_id) VALUES (?) ON CONFLICT(user_id) DO NOTHING
-- если пользователь уже существует, то обновить ему `referrer_id`
INSERT INTO 'users' (user_id, referrer_id) VALUES (?, ?)
ON CONFLICT(user_id) DO UPDATE SET referrer_id = excluded.referrer_id
// избавляемся от возможных дубликатов
$numbers = collect($numbers)->unique();
// pluck('num') вернет нам список значений атрибута num, а не список моделей
$existingNumbers = Model::query()->whereIn('num', $numbers->toArray())->pluck('num');
// с помощью diff получаем элементы, которых нет в $existingNumbers
$newNumbers = $existingNumbers->diff($numbers)->mapWithKeys(function ($value, $key) {
// ['one', 'two'] => [['num' => 'one'], ['num' => 'two']]
return [$key => ['num' => $value]];
});
Model::query()->getConnection()->transaction(function () use ($newNumbers) {
Model::query()->insert($newNumbers->toArray());
});
// избавляемся от возможных дубликатов
$newNumbers = collect($numbers)->unique();
Model::query()->toBase()->whereIn('num', $numbers->toArray())
->chunk(500000, function ($existingNumbers) use (&$newNumbers) {
// с помощью diff получаем элементы, которых нет в $existingNumbers
$newNumbers = $newNumbers->diff($existingNumbers);
});
// ['one', 'two'] => [['num' => 'one'], ['num' => 'two']]
$newNumbers = $newNumbers->mapWithKeys(function ($value, $key) {
return [$key => ['num' => $value]];
});
Model::query()->getConnection()->transaction(function () use ($newNumbers) {
Model::query()->insert($newNumbers->toArray());
});
ON CONFLICT
, если СУБД поддерживает подобное. Например, у SQLite - ON CONFLICT DO
, у MySQL - INSERT IGNORE
. Это позволит избавиться от выгрузки данных из БД, что уменьшит потребление памяти приложением и сократит количество запросов.Query::insertOrIgnore()
, который будет глушить все ошибки от некоторых БД, но для некоторых не поддерживается. Поддерживаемые БД: MySQL, SQLite, PostreSQL.$numbers = collect($numbers)->unique()->mapWithKeys(function ($value, $key) {
return [$key => ['num' => $value]];
});
Model::query()->getConnection()->transaction(function () use ($numbers) {
Model::query()->insertOrIgnore($numbers->toArray());
});
class A:
__data = [] // список будет общий для всех экземпляров класса A
class A:
def __init__(self):
self.__data = []
tap
не подходило из-за отключения DHCP на роутере2.https://git.io/vpn
, который пришлось редактировать для замены зашитой в нем сети 10.8.0.0
на другую в связи с наличием пересечения данной сети с другой на одном из роутеров.>>> wget https://git.io/vpn -O openvpn-install.sh
>>> sudo bash openvpn-install.sh
UDP
.nano /etc/openvpn/server/server.conf
, удаляем все строки, начинающиеся на push
, и добавляем следующее:ifconfig-pool-persist ipp.txt
client-config-dir /etc/openvpn/server/ccd
client-to-client
route 192.168.0.0 255.255.255.0
push 'route 192.168.0.0 255.255.255.0'
route 192.168.1.0 255.255.255.0
push 'route 192.168.1.0 255.255.255.0'
192.168.0.0/24
) клиента.sudo mkdir /etc/openvpn/server/ccd
.iroute 192.168.0.0 255.255.255.0
iroute 192.168.1.0 255.255.255.0
1
, соответствующую опции 1) Add a new client
.>>> sudo bash openvpn-install.sh
push 'route ...'
. @Get('findOne/:username')
async getUserByUsername(
@Param('username') username: string,
): Promise<UserEntity['id'] | undefined> {
return await this.usersService.findOne(username);
}
// с использованием read-only properties
class CustomerDTO {
public final integer id;
public final string name;
public CustomerDTO(integer id, string name) {
this.id = id;
this.name = name;
}
}
// с использованием геттеров (getters)
class CustomerDTO {
private integer id;
private string name;
public CustomerDTO(integer id, string name) {
this.id = id;
this.name = name;
}
public integer getId() {
return this.id;
}
public string getName() {
return this.name;
}
}
class Customer {
private integer id;
private string firstName;
private string lastName;
private integer walletBalance; // кошелек здесь ради примера
public Customer(integer id, string firstName, string lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.walletBalance = 0;
}
public integer getId() {
return this.id;
}
public string getFirstName() {
return this.firstName;
}
public string getLastName() {
return this.lastName;
}
public string getFullName() {
return this.firstName + " " + this.lastName;
}
public void rename(string firstName, string lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public void takeMoney(Money money) {
this.walletBalance += money.amount;
}
public Money giveMoney(integer amount) throws InsufficientFunds {
if (this.walletBalance < amount) {
throw new InsufficientFunds();
}
this.walletBalance -= amount;
return Money(amount);
}
}
есть dto которая указывает как валидировать данные от клиента
у нас есть entity которая описывает то как данные хранятся в бд
как называется то что позволяет обрезать данные отправляемые на клиент
serializer.serialize(new CustomerDTO(1, "John Smith")); // -> {"id": 1, "name": "John Smith"}
$array = [
[
"" => "что то не нужное",
"brand" => "Бренд",
"code" => "Артикул",
"price" => "цена",
"quantity" => "кол-во",
"name" => "нейм",
],
];
$filter = function ($value, $key) {
return !empty($key);
};
$result = array_map(function ($value) use ($filter) {
return array_filter($value, $filter, ARRAY_FILTER_USE_BOTH);
}, $array);