commit()
который отвечает за вычисление изменений в сохранённых в UoW объектах и синхронизацию этих изменений с хранилищем (базой данных).commit()
паттерна Unit of Work для вычисления разницы между исходными данными и накопленными изменениями. class Tweet
{
private $id;
private $content;
public function __construct(int $id, string $content)
{
$this->id = $id;
$this->content = $content;
}
public function getId(): int
{
return $this->id;
}
public function getContent(): string
{
return $this->content;
}
public function setContent(string $content): void
{
$this->content = $content;
}
}
CREATE TABLE tweets (
id INTEGER PRIMARY KEY,
content VARCHAR(255) NOT NULL
)
class UnitOfWork
{
private $connection;
private $identityMap;
private $data;
public function __construct(\PDO $connection)
{
$this->connection = $connection;
$this->identityMap = [];
$this->data = [];
}
public function find(int $id): Tweet
{
if (isset($this->identityMap[$id])) {
return $this->identityMap[$id];
}
$query = $this->connection->prepare('SELECT * FROM tweets WHERE id = ?');
$query->execute([ $id ]);
if (false === $data = $query->fetch()) {
throw new \Exception(\sprintf('Tweet with id "%d" not found.', $id));
}
$id = (int) $data['id'];
// Исходные данные сохраняются для того, чтобы в дальнейшем вычислить изменения.
$this->data[$id] = $data;
$tweet = new Tweet($id, $data['content']);
$this->identityMap[$id] = $tweet;
return $tweet;
}
public function commit(): void
{
// Вообще говоря, лучше вычислить все изиенения, создать один "большой" запрос
// и выполнить его внутри транзакции, но для простоты мы сделаем для каждого
// изменения отдельный запрос
$query = $this->connection->prepare('UPDATE tweets SET content = ? WHERE id = ?');
foreach ($this->identityMap as $tweet) {
if ($tweet->getContent() !== $this->data[$tweet->getId()]['content']) {
$query->execute([ $tweet->getContent(), $tweet->getId() ]);
}
}
}
}
var readMoreBtn = document.querySelector(".js-btn-readmore"),
readMoreContent = document.querySelector(".js-description-info");
readMoreBtn.addEventListener("click", function(event) {
event.preventDefault();
readMoreContent.classList.toggle("js-readmore-show");
this.textContent = this.textContent === 'Подробнее' ? 'Скрыть' : 'Подробнее';
});
они пользуется самописными браузерами
выкупленные айпи сервера
на каком железе сидят спецслужбисты, работники антивирусных компаний типа касперского?
То есть его нет?
<?php
/**
* Простой роутер
* @devg
*/
final class RouterLite {
public static $routes = array();
private static $params = array();
public static $requestedUrl = '';
/**
* Добавить маршрут
*/
public static function addRoute($route, $destination=null) {
if ($destination != null && !is_array($route)) {
$route = array($route => $destination);
}
self::$routes = array_merge(self::$routes, $route);
}
/**
* Разделить переданный URL на компоненты
*/
public static function splitUrl($url) {
return preg_split('/\//', $url, -1, PREG_SPLIT_NO_EMPTY);
}
/**
* Текущий обработанный URL
*/
public static function getCurrentUrl() {
return (self::$requestedUrl?:'/');
}
/**
* Обработка переданного URL
*/
public static function dispatch($requestedUrl = null) {
// Если URL не передан, берем его из REQUEST_URI
if ($requestedUrl === null) {
$uri = reset(explode('?', $_SERVER["REQUEST_URI"]));
$requestedUrl = urldecode(rtrim($uri, '/'));
}
self::$requestedUrl = $requestedUrl;
// если URL и маршрут полностью совпадают
if (isset(self::$routes[$requestedUrl])) {
self::$params = self::splitUrl(self::$routes[$requestedUrl]);
return self::executeAction();
}
foreach (self::$routes as $route => $uri) {
// Заменяем wildcards на рег. выражения
if (strpos($route, ':') !== false) {
$route = str_replace(':any', '(.+)', str_replace(':num', '([0-9]+)', $route));
}
if (preg_match('#^'.$route.'$#', $requestedUrl)) {
if (strpos($uri, '$') !== false && strpos($route, '(') !== false) {
$uri = preg_replace('#^'.$route.'$#', $uri, $requestedUrl);
}
self::$params = self::splitUrl($uri);
break; // URL обработан!
}
}
return self::executeAction();
}
/**
* Запуск соответствующего действия/экшена/метода контроллера
*/
public static function executeAction() {
$controller = isset(self::$params[0]) ? self::$params[0]: 'DefaultController';
$action = isset(self::$params[1]) ? self::$params[1]: 'default_method';
$params = array_slice(self::$params, 2);
return call_user_func_array(array($controller, $action), $params);
}
}
?>
<?php
// маршруты (можно хранить в конфиге приложения)
// можно использовать wildcards (подстановки):
// :any - любое цифробуквенное сочетание
// :num - только цифры
// в результирующее выражение записываются как $1, $2 и т.д. по порядку
$routes = array(
// 'url' => 'контроллер/действие/параметр1/параметр2/параметр3'
'/' => 'MainController/index', // главная страница
'/contacts' => 'MainController/contacts', // страница контактов
'/blog' => 'BlogController/index', // список постов блога
'/blog/:num' => 'BlogController/viewPost/$1' // просмотр отдельного поста, например, /blog/123
'/blog/:any/:num' => 'BlogController/$1/$2' // действия над постом, например, /blog/edit/123 или /blog/dеlete/123
'/:any' => 'MainController/anyAction' // все остальные запросы обрабатываются здесь
));
// добавляем все маршруты за раз
RouterLite::addRoute($routes);
// а можно добавлять по одному
RouterLite::addRoute('/about', 'MainController/about');
// непосредственно запуск обработки
RouterLite::dispatch();
?>
объединить его с первым SSD чтобы это был как единый логический диск P (Projects) состоящий из 2-х SSD-шников. И можно ли сделать это не очищая первый диск от проектов?
192.168.1.101 example.com www.example.com
ipfonfig /flushdns
service firewalld stop
if (!in_array($_REQUEST['token'],[
'vremenniitoken' // нужен для ботов и недоброжелателей
])) {
die();
}
header('Content-Type: application/json');
echo file_get_contents('http://url/?' . http_build_query($_REQUEST['params']));