ПредишенСледващото

Преди известно време аз попитах как да се направи за съхранение на генерираното от потребителите съдържание в различни бази данни, както и наскоро същия този въпрос дойде отново във форума:

Prompt като цяло, как да се приложи динамичен превключване между бази данни според свързан потребителя. Това означава, че ако влезете в профила на потребителя User 1, а след това поставете на DB1, ако User 2 да DB2.

Така че, ние сме за прилагане на поддръжка на множество връзки. Когато се работи през Mapper данни могат да бъдат прехвърлени потребителско име директно в хранилището методи:

и не може да мине друга връзка $ db в настоящите методи в ActiveRecord спаси. deleteAll и други подобни, които аргумент не взема $ db и изцяло разчитат на статичен метод:

и работи само в рамките на тази единствена връзка статично :: getDb ().

Вземете предвид някои ключ база данни опции.

За демонстрацията, задайте yii2 ап-основното приложение и изпълнете следната команда:

за създаване и изпълнение на миграцията:

И добавя към тази маса модел:

за съхранение се извършва в правилния базата данни.

Но сега има няколко проблема. Те се усложнява от необходимостта да се направи, ако, например, вложени транзакции. Това ще трябва да се помни стария $ oldId преди операцията и да го върне на мястото, след като:

Първият проблем - естетиката: необходимо е да се впише един куп навсякъде извън код.

Вторият - не-атомен. Вместо един ред е необходимо да се подкрепят и трите. И по този начин, е необходимо да се има предвид за точността на тяхната писмена форма, в противен случай можете да забравите или обърка линии и променливи.

Третият - нарушение на капсулиране. Сега getActiveId () метод трябва да се направи публично, така че всичко, което той може да тегли да си спомни старата държава.

Четвърто - наличието на глобални променливи:

Нашата компонент има обществена метод switchId ($ номер). позволява на вътрешното състояние на компонента и да е външен код. Такова разположение на обществеността "глобална променлива" може да доведе до проблема с достъпността на всички: в някакъв момент ще бъде Не е ясно кой и кога е включен и които са го забравили, "въведе".

За да се избегне Последният проблем, добър компонент не трябва да се съхранява вътре в насочва или към които са извън държавата на мястото на различни модули, които го използват, не се прекъсне работата хаотично превключване на другия.

Но какво, ако все още трябва да сменям? Функционалният подход се реализира с помощта на непроменими (неизменен) обекти. За да направите това, поставете () метод и switchId () вместо промените на полето, ние трябва само да създадете нов обект с другите клонинг $ компоненти и $ ID:

полета на обектите, са посочени в проектирането и никога няма да се променят. Вместо да променяте областта тук, в нова личност () създава нов обект с новите данни. Сега, ако различните модули за кандидатстване някъде в опита си да променят ID, те ще получат копие и не засягат останалите модули, които използват техните индивидуални клонове:

Така че е възможно naplodit желания брой независими един от друг компоненти. Но защо?

При нормална код - няма нужда. Но ако се опитат да въведат мултитрединга в PHP7 честен с pthreads. където в контролера на конзолата ще предизвика множество нишки едновременно switchId () в същото Yii :: $ АРР> локатор. ще видите невероятно объркване. Вместо това, можете да се даде възможност на всяка нишка своя независима клонинг $ локатор. или, по-правилно, за да се отърве от условията на съхранение в «запис" метод switchId на (). използвате само "четат" от GET ( "db", $ UserId) за извличане на желаната връзка.

Така че, в функционалния подход се осъществява достъп до всичко само за четене, както и с такива ActiveRecord резби не се реализира. Ние не може да се съхранява няколко свързващи обекти в рамките на различни инстанции, извлечени $ пост. две, за да се обадите спасяване ():

обектно записан в различни бази данни, като $ post1 и $ post2 потрепване при запазване на същия статичен статично :: getDb ():

и всички стоящи винаги има като цяло едно копие. Той е бил в опита си да направи няколко вариации на една и съща осъзнават, че singletons - зло.

Pozhtomu за смяна на глобалната свързаност ние направихме една чудовищна версия на оригинала:

На второ място, като структура, както казахме, неудобно да се използва. Може ли всички тези дейности по-лесно и да извършват с едно обаждане? И как да се избегне правописни грешки и забравяне програмист?

Това е всичко, което може да се опрости процеса на разработване на нашия блок код:

Нека doWith () метод вътре превключва идентификатор изпълним нашата функция и след всичко, което се връща:

Тя е по-удобно да се използва и по-малко шанс за нещо объркан. И по този начин е възможно да се премахне метод switchId. getActiveId метод да се направи лично.

Ние сме преминали през глобална променлива извън switchId ($ номер) състояние в рамките на компонент. Ние не можем да се тревожи за това, което някой е случайно промените стойността във вградения код и да забравите да го върна.

За резби такъв хак няма да работи, тъй като обектът е все още вътре промените в doWork на повикване () и всеки поток ще наруши съседи. Но за еднонишкови производителност, ние сме внедрили пълна емулация рамките Сингълтън статичен метод getDb () в ActiveRecord.

Сега е ред на изпълнението на доставчика.

Приликата със стандартната freymvorkovskim ServiceLocator ни дава възможност да използваме този клас директно като основа за нашата компонент. Otnasleduemsya от него и замени метода GET () и ясен ():

Вътре buildDefinition на метод (), не можем да се обърне директно към определенията на частния родителския клас масив като $ това -> _ компоненти [$ ID]. така да се възползват, като се обадите getComponents (). И тук ние сме внедрили пълно обхождане на дефинициите на компонентите чрез array_walk_recursive. да бъде в състояние да замени дори в вложени масиви.

На следващо място, ние трябва да се направи интерфейс детектор активен потребител:

и неговата проста реализация в Yii2:

Свързани статии

Подкрепете проекта - споделете линка, благодаря!