<?php
function getArrayValueByPath($array, $path, $separator = "/")
{
// Разбиваем путь на ключи
$keys = explode($separator, $path);
// Текущий уровень массива - начинаем с корня
$current = $array;
foreach ($keys as $key) {
// Если ключа нет в массиве, то выбрасываем исключение
if (!isset($current[$key])) {
throw new \Exception(
"Ключ $key не найден в массиве по адресу '$path'"
);
}
// Переходим к следующему уровню вложенности массива
$current = $current[$key];
}
// Возвращаем значение по заданному пути
return $current;
}
// Использование функции:
$arr = [
"k1" => [
"k2" => [
"k3" => [
"k4" => "v",
],
],
],
];
$result = getArrayValueByPath($arr, "k1/k2/k3");
var_dump($result);
/** Результат выполнения:
array(1) {
["k4"]=>
string(1) "v"
}
*/
Объясни принципы SOLID. Используй примеры на PHP. Объясняй как десятилетнему ребёнку
// SendMessageParams - Represents parameters of sendMessage method.
type SendMessageParams struct {
// BusinessConnectionID - Optional. Unique identifier of the business connection on behalf of which the
// message will be sent
BusinessConnectionID string `json:"business_connection_id,omitempty"`
// ChatID - Unique identifier for the target chat or username of the target channel (in the format
// @channel_username)
ChatID ChatID `json:"chat_id"`
// MessageThreadID - Optional. Unique identifier for the target message thread (topic) of the forum; for
// forum supergroups only
MessageThreadID int `json:"message_thread_id,omitempty"`
// Text - Text of the message to be sent, 1-4096 characters after entities parsing
Text string `json:"text"`
// ParseMode - Optional. Mode for parsing entities in the message text. See formatting options
// (https://core.telegram.org/bots/api#formatting-options) for more details.
ParseMode string `json:"parse_mode,omitempty"`
// Entities - Optional. A JSON-serialized list of special entities that appear in message text, which can be
// specified instead of parse_mode
Entities []MessageEntity `json:"entities,omitempty"`
// LinkPreviewOptions - Optional. Link preview generation options for the message
LinkPreviewOptions *LinkPreviewOptions `json:"link_preview_options,omitempty"`
// DisableNotification - Optional. Sends the message silently
// (https://telegram.org/blog/channels-2-0#silent-messages). Users will receive a notification with no sound.
DisableNotification bool `json:"disable_notification,omitempty"`
// ProtectContent - Optional. Protects the contents of the sent message from forwarding and saving
ProtectContent bool `json:"protect_content,omitempty"`
// MessageEffectID - Optional. Unique identifier of the message effect to be added to the message; for
// private chats only
MessageEffectID string `json:"message_effect_id,omitempty"`
// ReplyParameters - Optional. Description of the message to reply to
ReplyParameters *ReplyParameters `json:"reply_parameters,omitempty"`
// ReplyMarkup - Optional. Additional interface options. A JSON-serialized object for an inline keyboard
// (https://core.telegram.org/bots/features#inline-keyboards), custom reply keyboard
// (https://core.telegram.org/bots/features#keyboards), instructions to remove a reply keyboard or to force a
// reply from the user
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
}
// ReplyParameters - Describes reply parameters for the message that is being sent.
type ReplyParameters struct {
// MessageID - Identifier of the message that will be replied to in the current chat, or in the chat chat_id
// if it is specified
MessageID int `json:"message_id"`
// ChatID - Optional. If the message to be replied to is from a different chat, unique identifier for the
// chat or username of the channel (in the format @channel_username). Not supported for messages sent on behalf
// of a business account.
ChatID ChatID `json:"chat_id,omitempty"`
// AllowSendingWithoutReply - Optional. Pass True if the message should be sent even if the specified
// message to be replied to is not found. Always False for replies in another chat or forum topic. Always True
// for messages sent on behalf of a business account.
AllowSendingWithoutReply bool `json:"allow_sending_without_reply,omitempty"`
// Quote - Optional. Quoted part of the message to be replied to; 0-1024 characters after entities parsing.
// The quote must be an exact substring of the message to be replied to, including bold, italic, underline,
// strikethrough, spoiler, and custom_emoji entities. The message will fail to send if the quote isn't found in
// the original message.
Quote string `json:"quote,omitempty"`
// QuoteParseMode - Optional. Mode for parsing entities in the quote. See formatting options
// (https://core.telegram.org/bots/api#formatting-options) for more details.
QuoteParseMode string `json:"quote_parse_mode,omitempty"`
// QuoteEntities - Optional. A JSON-serialized list of special entities that appear in the quote. It can be
// specified instead of quote_parse_mode.
QuoteEntities []MessageEntity `json:"quote_entities,omitempty"`
// QuotePosition - Optional. Position of the quote in the original message in UTF-16 code units
QuotePosition int `json:"quote_position,omitempty"`
}
id, ticket, reply_message := db.GetTicketAndMessage(message.ReplyToMessage.MessageID, user.ID)
if ticket == nil {
_, _ = bot.SendMessage(&telego.SendMessageParams{
ChatID: telego.ChatID{ID: message.Chat.ID},
Text: "This ticket or message does not exist.",
ReplyParameters: &telego.ReplyParameters{
MessageID: message.MessageID
},
ParseMode: "HTML",
})
return
}
package main
import (
"fmt"
"os/exec"
"strings"
)
func getGroups() ([]string, error) {
var groups []string
patch := "/groups"
cmd := exec.Command("whoami", patch)
output, err := cmd.Output()
if err != nil {
return nil, err
}
lines := strings.Split(string(output), "\n")
for _, line := range lines {
if strings.HasPrefix(line, "S-1-5-21") {
groups = append(groups, line)
}
}
return groups, nil
}
func main() {
groups, err := getGroups()
if err != nil {
fmt.Printf("Ошибка получения групп пользователя: %v\n", err)
return
}
fmt.Println("Группы пользователя:", groups)
}
class ClassWithPrivate {
#privateField;
publicField;
constructor() {
this.#privateField = "Доступ только изнутри класса";
}
}
const instance = new ClassWithPrivate();
instance.publicField = "Доступ извне класса";
instance.#privateField; // Ошибка: SyntaxError: Private field '#privateField' must be declared in an enclosing class
class Animal {
constructor(name) {
this.speed = 0;
this.name = name;
}
run(speed) {
this.speed = speed;
alert(`${this.name} бежит со скоростью ${this.speed}.`);
}
stop() {
this.speed = 0;
alert(`${this.name} стоит.`);
}
}
class Rabbit extends Animal {
hide() {
alert(`${this.name} прячется!`);
}
stop() {
super.stop(); // вызываем родительский метод stop
this.hide(); // и затем hide
}
}
let rabbit = new Rabbit("Белый кролик"); // используется конструктор родителя
rabbit.run(5); // Белый кролик бежит со скоростью 5.
rabbit.stop(); // Белый кролик стоит. Белый кролик прячется!
<html>
<body onload="Load()">
<dialog></dialog>
<script>
function Load() {
setTimeout(() => {
// Создаём колбэк, функцию, которая будет вызываться только после нажатия на кнопку
const callback = function () {
alert("!");
};
Myconfirmselect(
"Готовы?" +
"¤" +
"Да" +
"¥" +
"alert('Да');" +
"º" +
"Нет" +
"¥" +
"alert('Нет');",
callback, // Передаём колбэк в функцию создания диалога
);
}, 500);
}
function Myconfirmselect(VarInput, callback) {
const dialog = document.querySelector("dialog");
dialog.innerHTML += `
<div>
<textarea></textarea>
</div>
`;
const textarea = dialog.querySelector("textarea");
const div = dialog.querySelector("div");
dialog.style.textAlign = "center";
textarea.style.width = "100%";
textarea.style.textAlign = "center";
textarea.style.resize = "none";
textarea.readOnly = true;
textarea.value = VarInput.split("¤")[0];
for (
let i = 0;
i < VarInput.split("¤")[1].split("º").length;
i++
) {
const VarButton = document.createElement("button");
VarButton.textContent = VarInput.split("¤")[1]
.split("º")
[i].split("¥")[0];
VarButton.id = VarInput.split("¤")[1]
.split("º")
[i].split("¥")[1];
VarButton.style.marginLeft = "10px";
VarButton.style.marginTop = "10px";
VarButton.addEventListener("click", () => {
eval(event.target.id);
// Вызов того самого callback после нажатия на кнопку
callback();
//ButtonClosealert();
});
div.appendChild(VarButton);
}
function ButtonClosealert() {
dialog.style.animation = "AnimFormHide 0.1s both";
setTimeout(() => {
dialog.style.textAlign = "initial";
const div = dialog.querySelector("div");
dialog.removeChild(div);
dialog.close();
}, 100);
}
dialog.style.animation = "AnimFormShow 0.25s both";
dialog.showModal();
}
</script>
<style>
@keyframes AnimFormShow {
0% {
transform: translateY(-150%);
}
}
@keyframes AnimFormHide {
100% {
transform: translateY(-150%);
display: none;
}
}
dialog,
#DialogCycle {
border: 2px solid black;
border-radius: 15px;
}
dialog div,
#DialogCycle div {
position: initial;
}
dialog::backdrop,
#DialogCycle::backdrop {
background: rgba(0, 0, 0, 0.6);
}
</style>
</body>
</html>
package app
import (
"fmt"
"io"
"log/slog"
"os"
)
// SetupLogger создаёт логгер на основании конфига
// Конфигурируем дефолтный slog и возвращаем функцию закрытия файла логов,
// если был выбран файл как место логгирования.
func SetupLogger(cfg config.Config) func() error {
closer := func() error { return nil }
level := cfg.LogLevel
var w io.Writer
switch cfg.LogOutput {
case config.LogOutputStderr:
w = os.Stderr
case config.LogOutputStdout:
w = os.Stdout
case config.LogOutputFile:
w, closer = getFileWriter(cfg)
}
var handler slog.Handler
switch cfg.LogFormat {
case config.LogFormatText:
handler = slog.Handler(slog.NewTextHandler(w, &slog.HandlerOptions{Level: level}))
case config.LogFormatJSON:
handler = slog.Handler(slog.NewJSONHandler(w, &slog.HandlerOptions{Level: level}))
}
slog.SetDefault(slog.New(handler))
return closer
}
// getFileWriter возвращает файл, куда писать логи и функцию закрытия этого файла
func getFileWriter(cfg config.Config) (*os.File, func() error) {
logDir := fmt.Sprintf("%s/%s", cfg.VarDir, cfg.LogDir)
err := os.MkdirAll(logDir, 0755)
if err != nil {
panic(fmt.Sprintf("error creating directory: %s; %v", logDir, err))
}
filename := fmt.Sprintf("%s/%s.log", logDir, cfg.AppEnv)
f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
panic(fmt.Sprintf("error opening file: %s %v", filename, err))
}
return f, f.Close
}
package main
import "app"
func main() {
// .....
closeLogFile := app.SetupLogger(cfg)
defer closeLogFile()
// ...
}