Verification: a143cc29221c9be0

Php array search all values

Замена подстроки

Пример: заменим bbb на zzz:

$str = 'aaa bbb ccc bbb ddd';

$result = str_replace('bbb', 'zzz', $str); 

echo $result; // результат: aaa zzz ccc zzz ddd

Мы заменили "bbb" на "zzz" и в $result запишется строка "aaa zzz ccc zzz ddd". У нас было 2 вхождения подстроки bbb и мы заменили их на zzz.

А что если нам нужно также заменить и ccc на zzz? Мы бы конечно могли запустить функцию 2 раза, в первый раз заменив первую подстроку, а второй раз другую, но можно просто указать массив подстрок поиска первым параметром.

Пример: заменим bbb и ccc на zzz:

$str = 'aaa bbb ccc bbb ddd';

$result = str_replace(['bbb', 'ccc'], 'zzz', $str); 

echo $result; // результат:  aaa zzz zzz zzz ddd

Что если нам нужно заменить bbb на zzz, а ccc на www?

Мы конечно снова можем запустить функцию 2 раза, но оптимальнее с точки зрения производительности будет и вторым параметром передать массив. В первом массиве будут подстроки, которые мы ищем, а во втором те, на которые заменяем.

Пример: заменяем bbb на zzz, а ccc на www:

$str = 'aaa bbb ccc bbb ddd';

$result = str_replace(['bbb', 'ccc'], ['zzz', 'www'], $str); 

echo $result; // результат:  aaa zzz www zzz ddd

Результат у нас правильный, но читабельность конечно страдает. А представьте если бы мы указывали сразу 50 таких строк для замены? И потом когда мы добавляем или заменяем строку, ее приходилось бы искать в 2 местах.

Более читабельным был бы код:

$str = 'aaa bbb ccc bbb ddd';

$replaces = [
    'bbb' => 'zzz',
    'ccc' => 'www',
];

$result = str_replace(array_keys($replaces), array_values($replaces), $str);

echo $result; // результат:  aaa zzz www zzz ddd

Тут нам помогли функции array_keys и array_values которые вернули все ключи и все значения соответственно. Кстати для подобной замены вам не обязательно использовать функцию str_replace, а можно воспользоваться strtr, и тогда наш код выглядел бы еще более просто:

$str = 'aaa bbb ccc bbb ddd';

$result = strtr($str, [
    'bbb' => 'zzz',
    'ccc' => 'www',
]);

echo $result; // результат:  aaa zzz www zzz ddd

У функции str_replace также есть четвертый параметр $count, в котором мы ничего не передаем, а наоборот получаем количество вхождений.

Таким образом если дополнить наш пример:

$str = 'aaa bbb ccc bbb ddd';

$result = str_replace('bbb', 'zzz', $str, $count); 

echo $result; // результат: aaa zzz ccc zzz ddd

echo 'Вхождений: ' . $count; //  Вхождений: 2

Обязательно прочитайте подробную документацию: https://www.php.net/manual/ru/function.str-replace.php

Удаление подстроки

Хоть это и очевидно, давайте проговорим еще момент с удалением строк. Чтобы удалить подстроку нужно просто заменить ее на пустоту (пустую строку).

Удалим xx из нашей строки:

str_replace('xx', '', 'aa xx bb'); // вторым параметром у нас идет пустая строка.

Другие примеры

Рассмотрим еще несколько примеров:

// Порядок замены
$str     = "Строка 1\nСтрока 2\rСтрока 3\r\nСтрока 4\n";
$order   = array("\r\n", "\n", "\r");
$replace = '
'; // Обрабатывает сначала \r\n для избежания их повторной замены. echo $newstr = str_replace($order, $replace, $str); // Выводит F, т.к. A заменяется на B, затем B на C, и так далее... // В итоге E будет заменено F, так как замена происходит слева направо. $search = array('A', 'B', 'C', 'D', 'E'); $replace = array('B', 'C', 'D', 'E', 'F'); $subject = 'A'; echo str_replace($search, $replace, $subject); // Выводит: яблорехкорех орех (по вышеуказанной причине) $letters = array('я', 'о'); $fruit = array('яблоко', 'орех'); $text = 'я о'; $output = str_replace($letters, $fruit, $text); echo $output;

Эта функция не поддерживает регулярные выражения, но для этого есть другая функция: preg_replace()

Более мощная альтернатива: preg_replace

С помощью функции preg_replace вы можете осуществлять замену по регулярном выражению. Если вам не хватает возможностей str_replace, то обратите внимание на эту функцию.

Ссылка на документацию: https://www.php.net/manual/ru/function.preg-replace.php

Введение

Аксессоры, мутаторы и приведение атрибутов к типам позволяют преобразовывать значения атрибутов Eloquent, когда вы извлекаете экземпляр модели или присваиваете их экземпляру модели. Например, вы можете использовать шифровальщик Laravel, чтобы зашифровать значение при его сохранении в базу данных, а затем автоматически расшифровать атрибут при доступе к нему в модели Eloquent. Или вы можете преобразовать строку JSON, которая хранится в вашей базе данных, в массив при доступе к ней через вашу модель Eloquent.

Аксессоры и мутаторы (Accessors and Mutators)

Определение аксессора (Accessor)

Аксессор преобразует значение атрибута экземпляра Eloquent при обращении к нему. Чтобы определить метод доступа, создайте метод get{Attribute}Attribute в вашей модели, где {Attribute} – это имя столбца, к которому вы хотите получить доступ, в «верхнем» регистре.

В этом примере мы определим аксессор для атрибута first_name. Аксессор будет автоматически вызван Eloquent при попытке получить значение атрибута first_name:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    
    public function getFirstNameAttribute($value)
    {
        return ucfirst($value);
    }
}

Как видите, исходное значение столбца передается аксессору, что позволяет вам манипулировать и возвращать значение. Чтобы получить доступ к значению аксессора, вы можете просто получить доступ к атрибуту first_name экземпляра модели:

use App\Models\User;

$user = User::find(1);

$firstName = $user->first_name;

Вы не ограничены взаимодействием с одним атрибутом в вашем аксессоре. Вы также можете использовать аксессор для возврата новых вычисленных значений из существующих атрибутов:


public function getFullNameAttribute()
{
    return "{$this->first_name} {$this->last_name}";
}
Если вы хотите, чтобы эти вычисленные значения были добавлены к представлениям массива / JSON вашей модели, вам нужно будет добавить их.

Определение мутатора (Mutator)

Мутатор преобразует значение атрибута в момент их присвоения экземпляру Eloquent. Чтобы определить мутатор, определите метод set{Attribute}Attribute в вашей модели, где {Attribute} – это имя столбца, к которому вы хотите получить доступ, в «верхнем» регистре.

Определим мутатор для атрибута first_name. Этот мутатор будет автоматически вызываться, когда мы попытаемся присвоить значение атрибута first_name модели:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    
    public function setFirstNameAttribute($value)
    {
        $this->attributes['first_name'] = strtolower($value);
    }
}

Мутатор получит значение, заданное для атрибута, что позволит вам манипулировать этим значением и устанавливать желаемое значение во внутреннем свойстве $attributes модели Eloquent. Чтобы использовать наш мутатор, нам нужно только установить атрибут first_name для модели Eloquent:

use App\Models\User;

$user = User::find(1);

$user->first_name = 'Sally';

В этом примере метод setFirstNameAttribute будет вызываться со значением Sally. Затем, мутатор применит к имени функцию strtolower и установит полученное значение во внутреннем массиве $attributes.

Приведение атрибутов к типам

Приведение атрибутов обеспечивает функциональность, аналогичную аксессорам и мутаторам, но без необходимости определения каких-либо дополнительных методов вашей модели. Вместо этого свойство $casts вашей модели представляет удобный способ преобразования атрибутов в распространенные типы данных.

Свойство $casts должно быть массивом, где ключ – это имя преобразуемого атрибута, а значение – это тип, к которому вы хотите привести столбец. Поддерживаемые типы преобразования:

  • array
  • boolean
  • collection
  • date
  • datetime
  • decimal:
  • double
  • encrypted
  • encrypted:array
  • encrypted:collection
  • encrypted:object
  • float
  • integer
  • object
  • real
  • string
  • timestamp

Чтобы продемонстрировать преобразование атрибутов, давайте преобразуем атрибут is_admin, который хранится в нашей базе данных в виде целого числа (0 или 1), в логическое значение:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    
    protected $casts = [
        'is_admin' => 'boolean',
    ];
}

После определения типизации, атрибут is_admin всегда будет преобразован в логическое значение при доступе к нему, даже если базовое значение хранится в базе данных как целое число:

$user = App\Models\User::find(1);

if ($user->is_admin) {
    
}
Атрибуты, которые имеют значение null, не будут преобразованы. Кроме того, вы никогда не должны определять типизацию (или атрибут), имя которого совпадает с именем отношения.

Преобразование в массив и JSON

Преобразование в array особенно полезно при работе со столбцами, которые хранятся как сериализованный JSON. Например, если ваша база данных имеет поле типа JSON или TEXT, содержащее сериализованный JSON, то добавленная типизация array этому атрибуту автоматически десериализует атрибут модели Eloquent в массив PHP при обращении к нему:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    
    protected $casts = [
        'options' => 'array',
    ];
}

Как только типизация определена, вы можете получить доступ к атрибуту options, и он будет автоматически десериализован из JSON в массив PHP. Когда вы устанавливаете значение атрибута options, данный массив будет автоматически сериализован обратно в JSON для сохранения:

use App\Models\User;

$user = User::find(1);

$options = $user->options;

$options['key'] = 'value';

$user->options = $options;

$user->save();

Чтобы обновить одно поле JSON-атрибута с помощью краткого синтаксиса, используйте оператор -> при вызове метода update:

$user = User::find(1);

$user->update(['options->key' => 'value']);

Типизация ArrayObject и Collection

Хотя типизации стандартного array достаточно для многих приложений, но у него есть некоторые недостатки. Поскольку типизация array возвращает примитивный тип, невозможно напрямую изменить смещение массива. Например, следующий код вызовет ошибку PHP:

$user = User::find(1);

$user->options['key'] = $value;

Чтобы решить эту проблему, Laravel предлагает типизацию AsArrayObject, которая преобразует ваш атрибут JSON в класс ArrayObject. Эта функция реализована с использованием реализации пользовательской типизации Laravel, которая позволяет Laravel интеллектуально кешировать и преобразовывать измененный объект таким образом, что отдельные смещения могли быть изменены без ошибок PHP. Чтобы использовать типизацию AsArrayObject, просто назначьте его атрибуту:

use Illuminate\Database\Eloquent\Casts\AsArrayObject;


protected $casts = [
    'options' => AsArrayObject::class,
];

Точно так же Laravel предлагает типизацию AsCollection, которая преобразует ваш атрибут JSON в экземпляр Laravel Collection:

use Illuminate\Database\Eloquent\Casts\AsCollection;


protected $casts = [
    'options' => AsCollection::class,
];

Типизация даты

По умолчанию Eloquent преобразует столбцы created_at и updated_at в экземпляры Carbon, расширяющего класс DateTime PHP и предоставляющего набор полезных методов. Вы можете типизировать дополнительные атрибуты даты, определив дополнительные преобразования даты в массиве свойств вашей модели $cast. Обычно даты следует приводить с использованием типизации datetime.

При определении типизации date или datetime вы также можете указать формат даты. Этот формат будет использоваться, когда модель сериализуется в массив или JSON:


protected $casts = [
    'created_at' => 'datetime:Y-m-d',
];

Когда столбец типизирован как дата, вы можете установить его значение в виде временной метки форматов UNIX, строки даты (Y-m-d), строки даты-времени или экземпляров DateTime / Carbon. Значение даты будет правильно преобразовано и сохранено в вашей базе данных:

Вы можете настроить формат сериализации по умолчанию для всех дат вашей модели, переопределив метод serializeDate вашей модели. Этот метод не влияет на форматирование дат для их сохранения в базе данных:


protected function serializeDate(DateTimeInterface $date)
{
    return $date->format('Y-m-d');
}

Чтобы указать формат, который следует использовать при фактическом сохранении дат модели в вашей базе данных, вы должны определить свойство $dateFormat вашей модели:


protected $dateFormat = 'U';

Типизация во время запроса

Иногда может потребоваться применить типизацию при выполнении запроса, например, при выборе сырого значения из таблицы. Например, рассмотрим следующий запрос:

use App\Models\Post;
use App\Models\User;

$users = User::select([
    'users.*',
    'last_posted_at' => Post::selectRaw('MAX(created_at)')
            ->whereColumn('user_id', 'users.id')
])->get();

Атрибут last_posted_at результатов этого запроса будет простой строкой. Было бы замечательно, если бы мы могли применить типизацию datetime этого атрибута при выполнении запроса. К счастью, мы можем добиться этого с помощью метода withCasts:

$users = User::select([
    'users.*',
    'last_posted_at' => Post::selectRaw('MAX(created_at)')
            ->whereColumn('user_id', 'users.id')
])->withCasts([
    'last_posted_at' => 'datetime'
])->get();

Конфигурационный файл

Для работы скрипта используется практически тот же самый конфигурационный файл. Его содержание приведено в Листинге 1.

Листинг 1. Конфигурационный файл скрипта phpldapread.php

#LDAP сервер для подключения ldap_server=10.54.200.1 #Base DN для подключения ldap_basedn="dc=shelton,dc=int" #Bind DN для подключения [email protected] #Пароль для пользователя, от имени которого будет выполняться подключение ldap_password="cXdlcnR5YXNkZgo 1" #Фильтр отбора записей. Он означает: отобрать объекты типа Пользователь, # у которых не установлено свойство "Заблокировать учетную запись" ldap_common_filter="(&(!(userAccountControl:1.2.840.113556.1.4.803:=2)) (sAMAccountType=805306368))" #Игнорировать перечисленных пользователей - это системные объекты ignore_list="SQLAgentCmdExec,SMSService,SMSServer_001, wsus" #Каталог, куда будет сохранен файл etcdir=/tmp #Имя файла со списком sarglist=sargusers

Зависимости, вспомогательные функции

Для работы скрипта потребуются дополнительные компоненты pear-Config и pear-Console_Getopt, а также расширение языка php-ldap. Pear-Config потребуется для чтения конфигурационного файла, pear-Console_Getopt - для разбора параметров командной строки. Надо сказать, рассматривается не весь скрипт: такие вопросы, как чтение конфигурационного файла, отображение справки или разбор командной строки являются вопросами уже достаточно хорошо описанными, поэтому соответствующие функции будут опущены, полную версию скрипта можно скачать с . Рассмотрено будет только то, что непосредственно относится к чтению данных из AD, как сервера LDAP, и некоторые нестандартные вспомогательные функции.

Функция обратного преобразования пароля приведена в Листинге 2. Вся роль так называемой "защиты" - предотвратить случайную утечку (ту, что называется eyedropper) и не более того.

Листинг 2. Функция обратного преобразования пароля.

/* * Обратное преобразование пароля * @param string $converted преобразованный пароль * @return string $passwd пароль в текстовой форме */ function demux_passwd($converted) { $_conved = explode(" ", $converted); $_passwd = ""; if ($_conved != 0) for (;$_conved != 0; $_conved--) { $_conved = $_conved . "="; } $_passwd = base64_decode($_conved); return rtrim($_passwd); }

Ничего особо интересного, конечно же, здесь нет: как уже было сказано в предыдущих частях, в конфигурационном файле хранится пароль, преобразованный в base64, заполнители отброшены и заменены числом. Эта функция выполняет обратное преобразование.

Функция перекодировки из UTF-8 в KOI8-R приведена в Листинге 3. Необходимость в этой функции возникает вследствие того, что консоль во FreeBSD не использует UTF-8.

Листинг 3. Функция перекодировки строки из UTF-8 в KOI8-R

/* * Перекодировать строку из UTF-8 в KOI8-R * @param string $source строка в кодировке UTF-8 * @return string $dest строка в кодировке KOI8-R */ function _from_utf8($source) { $converted = iconv("UTF-8", "KOI8-R", $source); return($converted); }

Кроме того, используется совершенно неинтересная функция safe_logger, в задачу которой входит вывод сообщений в лог или на консоль с завершением или без завершения работы скрипта. Все эти функции сохранены в файле utils.php.

Подключение к AD

Для подключения к AD используется функция ldap_server_connect, приведенная в Листинге 4. Функция выполняет все операции по подключению и возвращает идентификатор соединения для работы с сервером. Функция сохранена в отдельный файл ldapquery.php

Листинг 4. Функция подключения к серверу AD

require_once $PATH_LIB."/utils.php"; /* * Подключение к серверу LDAP * @param array $_config массив параметров конфигурации * @return resource $ldapconn идентификатор соединения с LDAP-сервером */ function ldap_server_connect($_config) { // Получить пароль в текстовом виде $_ldap_pwd = demux_passwd($_config["root"]["ldap_password"]); // Установить соединение с сервером if (!$ldapconn = ldap_connect($_config["root"]["ldap_server"])) safe_logger(sprintf("Невозможно подключиться к LDAP-серверу %s", $_config["root"]["ldap_server"]), "DIE"); // Для подключения к AD Windows 2003 и выше нужно установить эти опции ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0); // Авторизоваться на сервере ldap_bind($ldapconn, $_config["root"]["ldap_binddn"], $_ldap_pwd); return $ldapconn; }

На что хотелось бы обратить внимание здесь.

Во-первых, опции LDAP_OPT_PROTOCOL_VERSION ("версия протокола") и LDAP_OPT_REFERRALS ("отключить реферальные ссылки") должны быть обязательно установлены соответственно в 3 и 0 - без них можно увидеть странное: авторизация на сервере пройдет, но любой поиск будет возвращать ровно нуль записей.

Во-вторых, Bind DN должен быть задан в точности как в конфигурационном файле и никаким другим образом. Неверным будет в том числе и указание полного DN.