Kako podesiti pametne telefone i računare. Informativni portal
  • Dom
  • Windows 7, XP
  • Uklanjanje označenih objekata, zamjena veza. Redovna i upravljana aplikacija

Uklanjanje označenih objekata, zamjena veza. Redovna i upravljana aplikacija

U posljednje vrijeme bilo je mnogo članaka o nedostacima Bitrixa i njihovim opovrganjima. Pošto je opijanje išlo ovako, dodaću svojih 5 centi.
U komentarima na članke napisali su da nedostaje konkretnosti, primjera i detaljnijeg pregleda.

Ovaj članak je pokušaj da se napiše ova recenzija. Iako ne, ovo je više objava mržnje i bola (možda čak i malo kukanja). Ovo je proširena verzija posta o nedostacima pištolja. Pokušaću da opišem većinu stvari koje iritiraju mene i moje kolege u Bitrixu. Pokušat ću u jednom postu sabrati sve one nedostatke koji svakodnevno izazivaju mnogo boli. Na kraju ću pokušati izvući zaključke.

Ko sam ja? Da, generalno, običan programer. Sa Bitrix-om radim od novembra 2010. (5,5 godina). Radni samo sa Bitrixom, nije napravio niti jedan komercijalni projekat koristeći drugi CMS, nije koristio okvire za kreiranje web stranica. Po delatnosti se uglavnom bavim internet prodavnicama, njihovim kreiranjem, podrškom i razvojem.

TL;DR

Bitrix - UG, ne biste trebali ulaziti u ovaj bazen osim ako nije apsolutno neophodno.

Umjesto uvoda

Prvo, predlažem da provedete misaoni eksperiment. Hajde da pokušamo da uzmemo dva backend developera približno istih godina i sa približno istim radnim iskustvom (recimo 1 - 1,5 godina), samo tako da je jedan sve ovo vreme radio sa 1C-Bitrixom, a drugi sa Symfony ( na primjer). Lako možete uporediti sa kojim skupom tehnologija je jedan radio sve ovo vreme, a sa kojim je radio drugi, i koji skup znanja su na kraju dobili tokom tog vremena.

U slučaju Symfony programera, to će biti: php5/7 + duboko razumijevanje OOP-a, općenito prihvaćenih obrazaca dizajna (MVC, DI, Factory, Repository barem), sposobnost razvoja Unit testova, korištenje predložaka (barem twig) ), ORM (sa Doctrine), composer, git, PSR standardi, iskustvo rada sa konzolom i pisanje konzolnih aplikacija, osnovne vještine u postavljanju web servera.

U slučaju 1C-Bitrix programera, to će biti php5, html/css + javascript/jquery (nema mehanizama za šablone izvan kutije, a Bitrix stavlja logiku u šablone, kako god neko rekao, morat ćete petljaj s tim), možda git (a to uvelike zavisi od kompanije, neki dinosaurusi se još pile u proizvodnji preko FTP-a), ako imaš sreće - malo sql-a i... to je sve?

Razumijem da je sve ovo vrlo individualno i da okolina osobe može igrati veoma važnu ulogu. Ali ovdje govorim o tome na šta se programeri sistema tjeraju da rade iz kutije. U većini slučajeva, Bitrix programer je mnogo inferiorniji u vještinama u odnosu na programere za druge okvire/CMS – i to je neosporna činjenica. A sve zato što Bitrix u početku daje previše slobode u nedostatku jasne arhitekture, dokumentacije i ispravnih rješenja, dok Symfony nudi sve što vam treba.

Samo jednom je u našu kompaniju došla iskusna osoba koja nije iz sveta 1C-Bitrix-a (u regionu) i bila je za glavu iznad svojih kolega sa istim iskustvom, jednostavno zbog činjenice da je prethodno bio stavljen na pravi put.
I sama sam takva. Nažalost, od samog početka sam bio prevaren istim marketinškim glupostima i završio sam u ne baš dobrom okruženju. I sam razumijem i osjećam da moje kolege sa sličnim radnim iskustvom, ali u istom Symfonyju, imaju širi pogled, a to je vrlo jaka nuspojava Bitrixa.
Sve ovo sugerira da ako se želite razvijati u svijetu web razvoja, onda definitivno ne biste trebali odabrati Bitrix kao osnovu.

Upoređujući ova dva programera, želim da skrenem pažnju na okvir u koji nas sistem tera i slobodu koju pruža. I Bitrix i Symfony - oba pružaju gotovo neograničenu fleksibilnost, a u principu na svakom od njih možete stvoriti proizvod apsolutno bilo koje složenosti. Međutim, sistem bi trebao pomoći programeru da riješi probleme, umjesto da stavlja žbice u kotače. I ovdje Bitrix gubi mnogo.

Marketing

Želim odmah da kažem nekoliko reči o ovome, jer... ovo je glavna komponenta uspjeha Bitrixa.
Možemo reći da je cijeli Bitrix, pa i dokumentacija za programere, prožeta duhom marketinga. Čak i tamo pišu da je njihov proizvod “toliko kul da ga cijene i poštuju svi naši partneri” (dokaz, blok “Struktura”). Bitrix zapošljava dobre trgovce koji kompetentno znaju kako prezentirati svoj proizvod. Svakih šest mjeseci organizuju konferencije za partnere na kojima govore o tome šta je urađeno i kakvi su im planovi. Kao što praksa pokazuje, ovi planovi se nikada ne ostvaruju na vrijeme i vrlo često su izdanja ili nepotpuna ili puna grešaka.
Na primjer, senzacionalno refaktoriranje prodajnog modula čije je izlazak kasnilo više od godinu dana, a čak je i posljednji datum izlaska (23.12.2015.) promašen za 3 mjeseca, a nova trgovina i BUS (Bitrix) izd. “Upravljanje sajtom”) verzija 16 objavljena je tek krajem marta 2016. Ali kao rezultat toga, nakon ažuriranja, korisnici ne samo da nisu dobili nove funkcije. Korisnici su dobili uglavnom neoperabilnu trgovinu i gomilu novog nedokumentiranog koda za pokretanje.
Novim alatima daju tako glasna imena da svi znaju: Kompozitna lokacija - x100 ubrzanje; Highload blocks; Bitrix BigData. U stvari, ove riječi kriju sasvim obične stvari koje ne odgovaraju svom nazivu.
A ovakav pristup se, nažalost, svuda može vidjeti. Izvana, proizvod izgleda kao bombon koji ste kupili, instalirali i koristili. Ali ako se odmaknete od standardne isporuke uz Bitrix - to je to, održavanje funkcionalnosti tijekom ažuriranja pretvara se u pakao.
Međutim, pre svega, tema marketinga će se najverovatnije pojaviti u ovom postu više puta.

Arhitektura

Deset godina, Bitrix se očajnički doveo u ćorsokak. Svaka nova karakteristika u proizvodu objavljena je u skladu sa interesima poslovanja, bez odgovarajućeg razvoja sa tehničke tačke gledišta. I, naravno, sve je to raslo kao gruda snijega.
Ako razmislite o tome, Bitrix nema arhitekturu kao takvu. Ne postoje čak ni opšteprihvaćena, formulisana pravila koja bi omogućila da se prati ova arhitektura. Na kursu za programere, u odjeljku Arhitektura proizvoda, kaže se da Bitrix prati MVC arhitekturu i daje dijagram:

Odmah želim reći da se ovaj MVC jako razlikuje od klasične verzije. Ovdje je vrlo jaka zamjena koncepata, ovdje zapravo nema MVC-a, jednostavno postoji neka vrsta apstraktne podjele na module, komponente i šablone komponenti. I cijela lokacija je izgrađena od ovih cigli. Ali svaka od ovih cigli može preuzeti različite zadatke, pa su stoga usko povezane.
Pokušat ću detaljnije pogledati svaki od ovih aspekata arhitekture.

M - Model ili API

Teško mi je da procenim sistemski API kao model. Da, API pruža interfejs za pristup podacima i omogućava vam da njima manipulišete. Ali Bitrix API vam omogućava da radite ne samo s podacima, već i sa predlošcima, kao i sa zahtjevima korisnika. Pa dobro... to je samo moje mišljenje.
Trenutno, Bitrix ima 2 API opcije. Konvencionalno se mogu podijeliti na star I novo. Novi API se zove D7 (iskreno, ne sjećam se zašto, ali Rižikov je o tome govorio na jednoj od partnerskih konferencija).

Stari API je kolekcija antišablona, ​​užasnih primjera lošeg koda. U Bitrixu se oduvijek smatralo normalnim pozivati ​​nestatičke metode statički, i obrnuto, zahtijevati stanje kada je to neprikladno. Na primjer, dobro poznati CIBlockElement::GetList je možda jedna od najčešće korištenih metoda u razvoju. Njegova implementacija sadrži više od 500 linija koda, koristi globalne vrijednosti, gradi zastrašujuće, kolosalne upite i sadrži nerealan, jednostavno nečitljiv, nedokumentovan kod.

Hajde da pogledamo

Funkcija GetList($arOrder=array("SORT"=>"ASC"), $arFilter=array(), $arGroupBy=false, $arNavStartParams=false, $arSelectFields=array()) ( /* Kombinacije filtera: CHECK_PERMISSIONS= "N" - provjerite dozvole trenutnog korisnika za infoblok MIN_PERMISSION="R" - kada se provjere dozvole, onda minimalni nivo pristupa SHOW_HISTORY="N" - dodajte stavke historije na listu SHOW_NEW="N" - ako ne dodajte historijske stavke, zatim dodajte nove, ali neobjavljene elemente */ globalno $DB, $USER; $MAX_LOCK = intval(COption::GetOptionString("workflow","MAX_LOCK_TIME","60")); $uid = is_object($USER)? intval($USER->GetID()): 0; $formatActiveDates = CPageOption::GetOptionString("iblock", "FORMAT_ACTIVE_DATES", "-") != "-"; $shortFormatActiveDates = CPageOption::GetOptionString("iblock" , "FORMAT_ACTIVE_DATES", "SHORT"); $arIblockElementFields = array("ID"=>"BE.ID", "TIMESTAMP_X"=>$DB->DateToCharFunction("BE.TIMESTAMP_X"), "TIMESTAMP_X_UNIX"=>" UNIX_TIMESTAMP(BE.TIMESTAMP_X)", "MODIFIED_BY"=>"BE.MODIFIED_BY", "DATE_CREATE"=>$DB->DateToCharFunction("BE.DATE_CREATE"), "DATE_CREATE_UNIX"=>"UNIX_TIMESTAMP(BE.DATE_CREATE)"" , "CREATED_BY"=>"BE.CREATED_BY", "IBLOCK_ID"=>"BE.IBLOCK_ID", "IBLOCK_SECTION_ID"=>"BE.IBLOCK_SECTION_ID", "ACTIVE"=>"BE.ACTIVE", "ACTIVE_FROM"=> ($formatActiveDates ? $DB->DateToCharFunction("BE.ACTIVE_FROM", $shortFormatActiveDates) : "IF(EXTRACT(HOUR_SECOND FROM BE.ACTIVE_FROM)>0, ".$DB->DateToCharFunction("BE.ACTIVE_FROM", "FULL")." , ".$DB->DateToCharFunction("BE.ACTIVE_FROM", "SHORT").")"), "ACTIVE_TO"=>($formatActiveDates ? $DB->DateToCharFunction("BE.ACTIVE_TO", $shortFormatActiveDates) : "IF(EXTRACT(HOUR_SECOND FROM BE.ACTIVE_TO)>0, ".$DB->DateToCharFunction("BE.ACTIVE_TO", "FULL").", ".$DB->DateToCharFunction("BE.ACTIVE_TO", " SHORT").")"), "DATE_ACTIVE_FROM"=>($formatActiveDates ? $DB->DateToCharFunction("BE.ACTIVE_FROM", $shortFormatActiveDates) : "IF(EXTRACT(HOUR_SECOND FROM BE.ACTIVE_FROM)>0, ". $DB->DateToCharFunction("BE.ACTIVE_FROM", "FULL").", ".$DB->DateToCharFunction("BE.ACTIVE_FROM", "SHORT").")"), "DATE_ACTIVE_TO"=>($). formatActiveDates ? $DB->DateToCharFunction("BE.ACTIVE_TO", $shortFormatActiveDates) : "IF(EXTRACT(HOUR_SECOND FROM BE.ACTIVE_TO)>0, ".$DB->DateToCharFunction("BE.ACTIVE_TO)", "FULL .", ".$DB->DateToCharFunction("BE.ACTIVE_TO", "SHORT").")"), "SORT"=>"BE.SORT", "NAME"=>"BE.NAME", " PREVIEW_PICTURE"=>"BE.PREVIEW_PICTURE", "PREVIEW_TEXT"=>"BE.PREVIEW_TEXT", "PREVIEW_TEXT_TYPE"=>"BE.PREVIEW_TEXT_TYPE", "DETAIL_PICTURE"=>"BE. DETAIL_PICTURE", "DETAIL_TEXT"=>"BE.DETAIL_TEXT", "DETAIL_TEXT_TYPE"=>"BE.DETAIL_TEXT_TYPE", "SEARCHABLE_CONTENT"=>"BE.SEARCHABLE_CONTENT", "WF_STATUS_ID"=>"BE.W_PARENT_ID", "WF_STATUS_ID"=>"BE.W. =>"BE.WF_PARENT_ELEMENT_ID", "WF_LAST_HISTORY_ID"=>"BE.WF_LAST_HISTORY_ID", "WF_NEW"=>"BE.WF_NEW", "LOCK_STATUS"=>"if (BE.WF_DATE_LOCK je null, "zeleno", ako( DATE_ADD(BE.WF_DATE_LOCK, interval ".$MAX_LOCK." MINUTE) "BE.WF_LOCKED_BY", "WF_DATE_LOCK"=>$DB->DateToCharFunction("BE.WF_DATE_LOCK"), "WF_COMMENTS"=>"BE.WF_COMMENTS", "IN_SECTIONS"=>"BE.IN_SECTIONS", "SHOW_COUNTER"= >"BE.SHOW_COUNTER", "SHOW_COUNTER_START"=>$DB->DateToCharFunction("BE.SHOW_COUNTER_START"), "CODE"=>"BE.CODE", "TAGS"=>"BE.TAGS", "XML_ID" =>"BE.XML_ID", "EXTERNAL_ID"=>"BE.XML_ID", "TMP_ID"=>"BE.TMP_ID", "USER_NAME"=>"concat("(",U.LOGIN,") ", ifnull(U.NAME,"")," ",ifnull(U.LAST_NAME,""))", "LOCKED_USER_NAME"=>"concat("(",UL.LOGIN,"") ",ifnull(UL. IME ","")," ",ifnull(UL.LAST_NAME,""))", "CREATED_USER_NAME"=>"concat("(",UC.LOGIN,"") ",ifnull(UC.NAME," "), " ",ifnull(UC.LAST_NAME,""))", "LANG_DIR"=>"L.DIR", "LID"=>"B.LID", "IBLOCK_TYPE_ID"=>"B.IBLOCK_TYPE_ID" , "IBLOCK_CODE "=>"B.CODE", "IBLOCK_NAME"=>"B.NAME", "IBLOCK_EXTERNAL_ID"=>"B.XML_ID", "DETAIL_PAGE_URL"=>"B.DETAIL_PAGE_URL", "LIST_PAGE_URL"=> "B. LIST_PAGE_URL", "CANONICAL_PAGE_URL"=>"B.CANONICAL_PAGE_URL", "CREATED_DATE"=>$DB->DateFormatToDB("GGGG.MM.DD", "BE.DATE_CREATE"), "BP_PUBLISHED"=>"ako (BE. WF_STATUS_ID = 1, "Y", "N")",); unset($shortFormatActiveDates); unset($formatActiveDates); $bDistinct = lažno; CIBlockElement::PrepareGetList($arIblockElementFields, $arJoinProps, $bOnlyCount, $bDistinct, $arSelectFields, $sSelect, $arAddSelectFields, $arFilter, $sWhere, $sSectionWhere, $arGieldsWhere, $arGieldsBroy, $FieldsBroy rder, $arSqlOrder, $arAddOrderByFields, $arIBlockFilter, $arIBlockMultProps, $arIBlockConvProps, $arIBlockAllProps, $arIBlockNumProps, $arIBlockLongProps); $arFilterIBlocks = isset($arFilter["IBLOCK_ID"])? array($arFilter["IBLOCK_ID"]): array(); //********************OD DIJELA****************************** ** *************** $sFrom = ""; foreach($arJoinProps["FPS"] kao $iblock_id => $iPropCnt) ( $sFrom .= "tttINNER JOIN b_iblock_element_prop_s".$iblock_id." FPS".$iPropCnt." ON FPS".$iPropCnt.".IBLOCK_ BE.IDn"; $arFilterIBlocks[$iblock_id] = $iblock_id; ) foreach($arJoinProps["FP"] kao $propID => $db_prop) ( $i = $db_prop["CNT"]; if($db_prop[ "bFullJoin"]) $sFrom .= "tttINNER JOIN b_iblock_property FP".$i." NA FP".$i.".IBLOCK_ID = B.ID I ". (IntVal($propID)>0? "FP". $i.".ID=".IntVal($propID)."n": " FP".$i.".CODE="".$DB->ForSQL($propID, 200).""n") ; else $sFrom .= "tttLEFT JOIN b_iblock_property FP".$i." NA FP".$i.".IBLOCK_ID = B.ID I ". (IntVal($propID)>0? " FP".$i. ".ID=".IntVal($propID)."n": "FP".$i.".CODE="".$DB->ForSQL($propID, 200). ""n"); if($db_prop["IBLOCK_ID"]) $arFilterIBlocks[$db_prop["IBLOCK_ID"]] = $db_prop["IBLOCK_ID"]; ) foreach($arJoinProps["FPV"] ​​kao $ propID = > $db_prop) ( $i = $db_prop["CNT"]; if($db_prop["MULTIPLE"]=="Y") $bDistinct = true; if($db_prop["VERSION"]==2 ) $ strTable = "b_iblock_element_prop_m".$db_prop["IBLOCK_ID"]; else $strTable = "b_iblock_element_property"; if($db_prop["bFullJoin"]) $sFrom .= "tttINNER JOIN ".$strT". $i ." NA FPV".$i."IBLOCK_PROPERTY_ID = FP".$db_prop["JOIN"].".ID I FPV".$i.".IBLOCK_ELEMENT_ID = BE.IDn"; inače $sFrom .= "tttLEFT JOIN ".$strTable." FPV".$i." NA FPV".$i.".IBLOCK_PROPERTY_ID = FP".$db_prop["JOIN"].".ID AND FPV".$i.". IBLOCK_ELEMENT_ID = BE.IDn"; if($db_prop["IBLOCK_ID"]) $arFilterIBlocks[$db_prop["IBLOCK_ID"]] = $db_prop["IBLOCK_ID"]; ) foreach($arJoinProps["FPEN"] kao $propID => $db_prop) ( $i = $db_prop["CNT"]; if($db_prop["VERSION"] == 2 && $db_prop["MULTIPLE"] == "N") ( if($db_prop[" bFullJoin" ]) $sFrom .= "tttINNER JOIN b_iblock_property_enum FPEN".$i." NA FPEN".$i.".PROPERTY_ID = ".$db_prop["ORIG_ID"]." I FPS".$db_prop["JOIN". "] ".PROPERTY_".$db_prop["ORIG_ID"]." = FPEN".$i.".IDn"; else $sFrom .= "tttLEFT JOIN b_iblock_property_enum FPEN".$i." NA FPEN".$i.".PROPERTY_ID = ".$db_prop["ORIG_ID"].." I FPS".$db_prop["JOIN"] . ".PROPERTY_".$db_prop["ORIG_ID"]." = FPEN".$i.".IDn"; ) else ( if($db_prop["bFullJoin"]) $sFrom .= "tttINNER JOIN b_iblock_property_enum FPEN".$i." NA FPEN".$i."PROPERTY_ID = FPV".$db_prop["JOIN"]. ".IBLOCK_PROPERTY_ID AND FPV".$db_prop["JOIN"].".VALUE_ENUM = FPEN".$i.".IDn"; else $sFrom .= "tttLEFT JOIN b_iblock_property_enum FPEN".$i." NA FPEN-u". $i.".PROPERTY_ID = FPV".$db_prop["JOIN"].".IBLOCK_PROPERTY_ID I FPV".$db_prop["JOIN"].".VALUE_ENUM = FPEN".$i.".IDn"; ) ako ($db_prop["IBLOCK_ID"]) $arFilterIBlocks[$db_prop["IBLOCK_ID"]] = $db_prop["IBLOCK_ID"]; ) foreach($arJoinProps["BE"] kao $propID => $db_prop) ( $i = $db_prop["CNT"]; $sFrom .= "tttLEFT JOIN b_iblock_element BE".$i." ON BE".$ i.".ID = ". ($db_prop["VERSION"]==2 && $db_prop["MULTIPLE"]=="N"? "FPS".$db_prop["JOIN"].".PROPERTY_". $db_prop["ORIG_ID"] :"FPV".$db_prop["JOIN"]..VALUE_NUM"). ($arFilter["SHOW_HISTORY"] != "Y"? " I ((BE.WF_STATUS_ID=1 I BE .WF_PARENT_ELEMENT_ID JE NULL)".($arFilter["SHOW_NEW"]=="Y"? " ILI BE.WF_NEW="Y"": "").")": "")."n"; if ((( $db_prop["bJoinIBlock"]) $sFrom .= "tttLEFT JOIN b_iblock B".$i." NA B".$i."ID = BE".$i."IBLOCK_IDn"; if($db_prop [ "bJoinSection"]) $sFrom . = "tttLEFT JOIN b_iblock_section BS".$i." NA BS".$i."ID = BE".$i.".IBLOCK_SECTION_IDn"; if($db_prop["IBLOCK_ID"]) $arFilterIBlocks[$db_prop["IBLOCK_ID"]] = $db_prop["IBLOCK_ID"]; ) foreach($arJoinProps["BE_FPS"] kao $iblock_id => $db_prop) ( $sFrom .= "tttLEFT JOIN b_iblock_element_prop_s".$iblock_id." JFPS".$db_prop["CNT"]." ON JFPS".$). db_prop["CNT"].".IBLOCK_ELEMENT_ID = BE".$db_prop["JOIN"].".IDn"; if($db_prop["IBLOCK_ID"]) $arFilterIBlocks[$db_prop["IBLOCK_ID"]] = $ db_prop["IBLOCK_ID"]; ) foreach($arJoinProps["BE_FP"] kao $propID => $db_prop) ( $i = $db_prop["CNT"]; list($propID, $link) = explode("~ ", $propID, 2); if($db_prop["bFullJoin"]) $sFrom .= "tttINNER JOIN b_iblock_property JFP".$i." NA JFP".$i."IBLOCK_ID = BE".$db_prop[ "JOIN"].".IBLOCK_ID I ". (IntVal($propID)>0? " JFP".$i.".ID=".IntVal($propID)."n": " JFP".$i. ".CODE="".$DB->ForSQL($propID, 200).""n"); else $sFrom .= "tttLEFT JOIN b_iblock_property JFP".$i." NA JFP".$i.". IBLOCK_ID = BE".$db_prop["JOIN"].".IBLOCK_ID I ". (IntVal($propID)>0? " JFP".$i.".ID=".IntVal($propID)."n" : " JFP".$i.".CODE="".$DB->ForSQL($propID, 200).""n"); if($db_prop["IBLOCK_ID"]) $arFilterIBlocks[$db_prop[" IBLOCK_ID"]] = $db_prop["IBLOCK_ID"]; ) foreach($arJoinProps["BE_FPV"] ​​kao $propID => $db_prop) ( $i = $db_prop["CNT"]; list($propID, $link) = explode("~", $propID, 2) ; if($db_prop["MULTIPLE"]=="Y") $bDistinct = true; if($db_prop["VERSION"]==2) $strTable = "b_iblock_element_prop_m".$db_prop["IBLOCK_ID"] ; else $strTable = "b_iblock_element_property"; if($db_prop["bFullJoin"]) $sFrom .= "tttINNER JOIN ".$strTable." JFPV".$i." NA JFPV".$i.".IBLOCK_PROPERTY_ID = JFP" .$db_prop["JOIN"].".ID I JFPV".$i.".IBLOCK_ELEMENT_ID = BE".$db_prop["BE_JOIN"].".IDn"; else $sFrom .= "tttLEFT JOIN " .$ strTable." JFPV".$i." NA JFPV".$i."IBLOCK_PROPERTY_ID = JFP".$db_prop["JOIN"].".ID AND JFPV".$i."IBLOCK_ELEMENT_ID = BE" .$ db_prop["BE_JOIN"].".IDn"; if($db_prop["IBLOCK_ID"]) $arFilterIBlocks[$db_prop["IBLOCK_ID"]] = $db_prop["IBLOCK_ID"]; ) foreach($arJoinProps[ "BE_FPEN "] kao $propID => $db_prop) ( $i = $db_prop["CNT"]; list($propID, $link) = explode("~", $propID, 2); if($db_prop[ "VERSION "] == 2 && $db_prop["MULTIPLE"] == "N") ( if($db_prop["bFullJoin"]) $sFrom .= "tttINNER PRIDRUŽENJE b_iblock_property_enum JFPEN".$i." NA JFPEN" .$ i.".PROPERTY_ID = ".$db_prop["ORIG_ID"].." I JFPS".$db_prop["JOIN"].".PROPERTY_".$db_prop["ORIG_ID"].." = JFPEN" .$i. ".IDn"; else $sFrom . = "tttLEFT JOIN b_iblock_property_enum JFPEN".$i." NA JFPEN".$i.".PROPERTY_ID = ".$db_prop["ORIG_ID"].." I JFPS".$db_prop["JOIN"].".PROPERTY_ " .$db_prop["ORIG_ID"]." = JFPEN".$i.".IDn"; ) else ( if($db_prop["bFullJoin"]) $sFrom .= "tttINNER JOIN b_iblock_property_enum JFPEN".$i." NA JFPEN".$i."PROPERTY_ID = JFPV".$db_prop["JOIN"]. ".IBLOCK_PROPERTY_ID AND JFPV".$db_prop["JOIN"].".VALUE_ENUM = JFPEN".$i.".IDn"; else $sFrom .= "tttLEFT JOIN b_iblock_property_enum JFPEN".$i." NA JFPEN-u". $i.".PROPERTY_ID = JFPV".$db_prop["JOIN"].".IBLOCK_PROPERTY_ID I JFPV".$db_prop["JOIN"].".VALUE_ENUM = JFPEN".$i.".IDn"; ) ako ($db_prop["IBLOCK_ID"]) $arFilterIBlocks[$db_prop["IBLOCK_ID"]] = $db_prop["IBLOCK_ID"]; ) if(strlen($arJoinProps["BES"])) ( $sFrom .= "ttt".$arJoinProps["BES"]."n"; ) if(strlen($arJoinProps["FC"])) ( $sFrom .= "ttt".$arJoinProps["FC"]."n"; $bDistinct = $bDistinct || (isset($arJoinProps["FC_DISTINCT"]) && $arJoinProps["FC_DISTINCT"] == "Y "); ) if($arJoinProps["RV"]) $sFrom .= "tttLEFT JOIN b_rating_voting RV ON RV.ENTITY_TYPE_ID = "IBLOCK_ELEMENT" I RV.ENTITY_ID = BE.IDn"; if($arJoinProps["RVU"]) $sFrom .= "tttLEFT JOIN b_rating_vote RVU NA RVU.ENTITY_TYPE_ID = "IBLOCK_ELEMENT" I RVU.ENTITY_ID = BE.ID I RVU.USER_ID = ".$uid."n"; if($arJoinProps["RVV"]) $sFrom .= "ttt".($arJoinProps["RVV"]["bFullJoin"]? "INNER": "LEFT")." PRIDRUŽITE se b_rating_vote RVV NA RVV.ENTITY_TYPE_ID = = "IBLOCK_ELEMENT" I RVV.ENTITY_ID = BE.IDn"; //******************** KRAJ OD DIJELA************************** ********** ****************** $bCatalogSort = netačno; if(count($arAddSelectFields)>0 || count($arAddWhereFields)>0 || count($arAddOrderByFields)>0) ( if(CModule::IncludeModule("catalog")) ( $res_catalog = CCatalogBuildProduct::GetQuery(GetQuery $arAddOrderByFields, $arAddWhereFields, $arAddSelectFields); if($sGroupBy=="" && !$bOnlyCount && !(is_object($this) && isset($this->strField))) $sSelect ."= $res_catalog["= $res_catalog "]." "; $sFrom .= str_replace("LEFT JOIN", "ntttLEFT JOIN", $res_catalog["FROM"])."n"; //$sWhere .= $res_catalog["WHERE"]." "; premješteno u MkFilter if(is_array($res_catalog["ORDER"]) && count($res_catalog["ORDER"])) ( $bCatalogSort = true; foreach($res_catalog["ORDER"] kao $i=>$ val) $arSqlOrder[$i] = $val; ) ) ) $i = array_search("CREATED_BY_FORMATTED", $arSelectFields); if ($i !== false) ( if ($sSelect && $sGroupBy=="" && !$bOnlyCount && !(is_object($this) && isset($this->strField))) ( $sSelect .= " ,UC. IME UC_NAME, UC.LAST_NAME UC_LAST_NAME, UC.SECOND_NAME UC_SECOND_NAME, UC.EMAIL UC_EMAIL, UC.ID UC_ID, UC.LOGIN UC_LOGIN"; ) ostalo ( unset($arSelectFields[$i]); ) ) $sOr"; foreach($arSqlOrder kao $i=>$val) ( if(strlen($val)) ( if($sOrderBy=="") $sOrderBy = " ORDER BY "; inače $sOrderBy .= ","; $sOrderBy .= $val." "; ) ) $sSelect = trim($sSelect, ", tnr"); if(strlen($sSelect)<= 0) $sSelect = "0 as NOP "; $bDistinct = $bDistinct || (isset($arFilter["INCLUDE_SUBSECTIONS"]) && $arFilter["INCLUDE_SUBSECTIONS"] == "Y"); if($bDistinct) $sSelect = str_replace("%%_DISTINCT_%%", "DISTINCT", $sSelect); else $sSelect = str_replace("%%_DISTINCT_%%", "", $sSelect); $sFrom = " b_iblock B INNER JOIN b_lang L ON B.LID=L.LID INNER JOIN b_iblock_element BE ON BE.IBLOCK_ID = B.ID ".ltrim($sFrom, "tn") .(in_array("USER_NAME", $arSelectFields)? "tttLEFT JOIN b_user U ON U.ID=BE.MODIFIED_BYn": "") .(in_array("LOCKED_USER_NAME", $arSelectFields)? "tttLEFT JOIN b_user UL ON UL.ID=BE.WF_LOCKED_BYn": "") .(in_array("CREATED_USER_NAME", $arSelectFields) || in_array("CREATED_BY_FORMATTED", $arSelectFields)? "tttLEFT JOIN b_user UC ON UC.ID=BE.CREATED_BYn": "")." "; $strSql = " FROM ".$sFrom." WHERE 1=1 " .$sWhere." ".$sGroupBy." "; if(isset($this) && is_object($this) && isset($this->strField)) ( $this->sFrom = $sFrom; $this->sWhere = $sWhere; vrati "SELECT ".$sSelect.$strSql; ) if($bOnlyCount) ( $res = $DB->Query(" SELECT ".$sSelect.$strSql, false, "FILE: ".__FILE__."
LINE: ".__LINE__); $res = $res->Fetch(); return $res["CNT"]; ) if(is_array($arNavStartParams)) ( $nTopCount = intval($arNavStartParams["nTopCount"]) ; $nElementID = intval($arNavStartParams["nElementID"]); if($nTopCount > 0) ( $strSql = "SELECT ".$sSelect.$strSql.$sOrderBy." LIMIT ".$nTopCount; $res = $ DB->Query($strSql); ) elseif($nElementID > 0 && $sGroupBy == "" && $sOrderBy != "" && strpos($sSelect, "BE.ID") !== false && !$bCatalogSort ) ( $nPageSize = intval($arNavStartParams["nPageSize"]); if($nPageSize > 0) ( $DB->Query("SET @rank_e=0"); $DB->Query("SET @rank_r= 0"); $DB->Query(" SELECT ".$sSelect." ,@rank_r:=@rank_r+1 AS rang1 ,if (BE.ID = ".$nElementID.", @rank_e:=@rank_r, null) rank2 ".$strSql.$sOrderBy." "); $DB->Query("SET @rank_r=0"); $res = $DB->Query(" SELECT * FROM (SELECT ".$sSelect. " ,@rank_r:=@rank_r+1 AS RANK ".$strSql.$sOrderBy." LIMIT 18446744073709551615) el0 GDJE el0.RANK između @rank_e-$nPageSize i @rank_e+$nPageSize "); ) else ( $DB->Query("SET @rank=0"); $res = $DB->Query(" SELECT * FROM (SELECT ".$sSelect." ,@rank:=@rank+1 AS RANK ".$strSql.$sOrderBy." LIMIT 18446744073709551615) el0 WHERE el0.ID = ".$nElementID." "); ) ) else ( if($sGroupBy == "") ( $res_cntery = $DB->Qu "SELECT COUNT(".($bDistinct? "DISTINCT BE.ID": ""x"").") kao C ".$strSql); $res_cnt = $res_cnt->Fetch(); $cnt = $res_cnt ["C"]; ) else ( $res_cnt = $DB->Query("SELECT "x" ".$strSql); $cnt = $res_cnt->SelectedRowsCount(); ) $strSql = "SELECT ".$sSelect .$strSql.$sOrderBy; $res = novi CDBResult(); $res->NavQuery($strSql, $cnt, $arNavStartParams); ) ) else//if(is_array($arNavStartParams)) ( $strSql = "SELECT ".$sSelect.$strSql.$sOrderBy; $res = $DB->Query($strSql, false, "FILE: ".__FILE__."
LINE: ".__LINE__); ) $res = novi CIBlockResult($res); $res->SetIBlockTag($arFilterIBlocks); $res->arIBlockMultProps = $arIBlockMultProps; $res->arIBlockConvProps = $arIBlockConvProps; $res-> arIBlockAllProps = $arIBlockAllProps; $res->arIBlockNumProps = $arIBlockNumProps; $res->arIBlockLongProps = $arIBlockLongProps; vrati $res; )

Kao što možete pretpostaviti, ova metoda prima listu elemenata informacijskog bloka iz baze podataka, a za dobivanje liste nije potrebno kreiranje instance klase CIBlockElement. Međutim, za dodavanje elementa informacijskog bloka potrebno je stanje i to samo da bi se zabilježila informacija o posljednjoj grešci koja se dogodila u javnom svojstvu klase.

Stari API intenzivno koristi globalne varijable kao što su $APPLICATION, $USER, $DB. Oni su primjeri određenih klasa, a u dokumentaciji su se s ponosom nazivali singletonima, iako sada više nisam našao ove riječi.
Da biste generirali grešku, na primjer, u rukovateljima događaja, trebate koristiti metodu $APPLICATION->ThrowException() koja zapravo ne baca izuzetke.

Javna funkcija ThrowException($msg, $id = false) ( $this->ResetException(); if(is_object($msg) && (is_subclass_of($msg, "CApplicationException") || (strtolower(get_class($msg)) =="capplicationexception"))) $this->LAST_ERROR = $msg; inače $this->LAST_ERROR = novi CApplicationException($msg, $id); )

I da - sva ta ljepota se i dalje koristi u razvoju novih projekata, jer... D7 još uvijek ne podržava sve karakteristike starog API-ja. Isti modul infobloka i dalje vam omogućava da izvršite samo odabir entiteta, a ne u potpunosti. Još nije moguće kreirati novi element ili ažurirati postojeći koristeći novi API.

Novi API je već donekle drugačiji od starog. Prvo, sav kod iz novog kernela je podijeljen u prostore imena, gdje postoji jasna ovisnost o modulu. Na primjer, analog CIBlockElement::GetList iz nove jezgre je BitrixIblockElementTable::getList, gdje je korijenski imenski prostor ime dobavljača, a sljedeći prostor imena je ime modula. Da bi ovo funkcioniralo, Bitrix je napisao vlastiti autoloader, BitrixMainLoader::autoLoad, koji uopće nije kompatibilan sa PSR-0/4.

Zapravo, kod autoloadera u obliku jedne funkcije

Javna statička funkcija autoLoad($className) ( $file = ltrim($className, "\"); // popraviti web env $file = strtr($file, static::ALPHA_UPPER, static::ALPHA_LOWER); static $documentRoot = null; if ($documentRoot === null) $documentRoot = static::getDocumentRoot(); if (isset(self::$arAutoLoadClasses[$file])) ( $pathInfo = self::$arAutoLoadClasses[$file]; if ($pathInfo["module"] != "") ( $m = $pathInfo["module"]; $h = isset(self::$arLoadedModulesHolders[$m]) ? self::$arLoadedModulesHolders[$m ] : "bitrix"; include_once($documentRoot."/".$h."/modules/".$m."/" .$pathInfo["file"]); ) else ( require_once($documentRoot.$pathInfo ["file"]); ) return; ) if (preg_match("#[^\\/a-zA-Z0-9_]#", $file)) return; if (substr($file, -5) = = "tabela") $file = substr($file, 0, -5); $file = str_replace("\", "/", $file); $arFile = eksplodirati("/", $datoteka); ako ($arFile === "bitrix") ( array_shift($arFile); if (empty($arFile)) return; $module = array_shift($arFile); if ($module == null ||prazno($arFile) ) povratak; ) else ( $module1 = array_shift($arFile); $module2 = array_shift($arFile); if ($module1 == null || $module2 == null || prazno($arFile)) return; $module = $module1 .".".$module2; ) if (!isset(self::$arLoadedModulesHolders[$module])) return; $filePath = $documentRoot."/".self::$arLoadedModulesHolders[$module].."/modules/".$module."/lib/".implode("/", $arFile).".php" ; if (file_exists($filePath)) require_once($filePath); )

Novi API pokazuje veliku ljubav prema Singletonu:

  • BitrixMainApplication::getInstance - instanca aplikacije
  • BitrixMainConfigConfiguration::getInstance - instanca klase za upravljanje konfiguracijama
  • BitrixMainPageAsset::getInstance - Instanca Asset managera
  • BitrixMainEventManager::getInstance - menadžer događaja

Možda će u budućnosti sve ovo dobiti svoj ServiceLayer (postoji određeni BitrixMainServiceManager u novom jezgru, koji još nije korišten i nije dokumentiran). Ali još je malo nade.

ORM je još jedna od inovacija D7, a ovo je nešto što može tvrditi da je pravi model! Možete razlikovati ORM klasu entiteta od bilo koje druge klase po njenom imenu. Klasa entiteta uvijek mora završavati sa tablicom (ElementTable, SectionTable, OrderTable, itd.). Štaviše, paradoksalno, ime datoteke sa ORM klasom entiteta ne bi trebalo da se završava u tabeli. Na primjer, za ElementTable moramo kreirati element.php datoteku. Snimak ekrana ispod prikazuje sadržaj direktorija lib (D7 autoload radi samo u ovom direktoriju) iblock modula. Pokušajte na oko utvrditi šta su ORM entiteti, a šta obične klase sa poslovnom logikom.


ORM, uglavnom, još nije ništa posebno. Omogućava vam da opišete tabele baze podataka u obliku klasa i omogućava vam da izvršite upite na tim tabelama i povežete ih međusobno. Ne postoji ActiveRecord ili Repository i ne očekuje se.

Primjer tipične klase ORM entiteta za element infobloka

*

  • ID obavezan *
  • TIMESTAMP_X datum i vrijeme opciono *
  • MODIFIED_BY int opciono *
  • DATE_CREATE datum i vrijeme opciono *
  • CREATED_BY int opciono *
  • IBLOCK_ID int obavezan *
  • IBLOCK_SECTION_ID int opciono *
  • ACTIVE bool opciono zadano "Y" *
  • ACTIVE_FROM datum i vrijeme opciono *
  • ACTIVE_TO datum i vrijeme opciono *
  • SORT int opciono zadano 500 *
  • NAME string(255) obavezan *
  • PREVIEW_PICTURE int opciono *
  • PREVIEW_TEXT string opciono *
  • PREVIEW_TEXT_TYPE enum ("tekst", "html") opcioni zadani "tekst" *
  • DETAIL_PICTURE int opciono *
  • DETAIL_TEXT string opciono *
  • DETAIL_TEXT_TYPE enum ("tekst", "html") opcioni zadani "tekst" *
  • SEARCHABLE_CONTENT string opciono *
  • WF_STATUS_ID int opciono default 1 *
  • WF_PARENT_ELEMENT_ID int opciono *
  • WF_NEW enum ("N", "Y") opciono *
  • WF_LOCKED_BY int opciono *
  • WF_DATE_LOCK datum i vrijeme opciono *
  • WF_COMMENTS string opciono *
  • IN_SECTIONS bool opciono zadano "N" *
  • XML_ID string(255) opciono *
  • KOD niz (255) opciono *
  • TAGS string(255) opciono *
  • TMP_ID string(40) opciono *
  • WF_LAST_HISTORY_ID int opciono *
  • SHOW_COUNTER int opciono *
  • SHOW_COUNTER_START datum i vrijeme opciono *
  • PREVIEW_PICTURE_FILE referenca na (@link BitrixFileFileTable) *
  • DETAIL_PICTURE_FILE referenca na (@link BitrixFileFileTable) *
  • IBLOCK referenca na (@link BitrixIblockIblockTable) *
  • WF_PARENT_ELEMENT referenca na (@link BitrixIblockIblockElementTable) *
  • IBLOCK_SECTION referenca na (@link BitrixIblockIblockSectionTable) *
  • MODIFIED_BY_USER referenca na (@link BitrixUserUserTable) *
  • CREATED_BY_USER referenca na (@link BitrixUserUserTable) *
  • WF_LOCKED_BY_USER referenca na (@link BitrixUserUserTable) * * * @package BitrixIblock **/ klasa ElementTable proširuje MainEntityDataManager ( const TYPE_TEXT = "text"; const TYPE_HTML = "html"; /** * Vraća ime DB tablice za entitet. * * @return string */ javna statička funkcija getTableName( ) ( return "b_iblock_element"; ) /** * Vraća definiciju mape entiteta. * * @return array */ javna statička funkcija getMap() ( return array("ID" => new MainEntityIntegerField("ID", array("primary) " => true, "autocomplete" => true, "title" => Loc::getMessage("ELEMENT_ENTITY_ID_FIELD"),)), "TIMESTAMP_X" => novo MainEntityDatetimeField("TIMESTAMP_X", array("default_value" => novo MainTypeDateTime(), "title" => Loc::getMessage("ELEMENT_ENTITY_TIMESTAMP_X_FIELD"),)), "MODIFIED_BY" => novo MainEntityIntegerField("MODIFIED_BY", array("title" => Loc::getMessage("MODIFIED_EDBY)") ,)), "DATE_CREATE" => novo MainEntityDatetimeField("DATE_CREATE", array("default_value" => new MainTypeDateTime(), "title" => Loc::getMessage("ELEMENT_ENTITY_DATE_CREATE_FIELD"),)), "CREATED > new MainEntityIntegerField("CREATED_BY", array("title" => Loc::getMessage("ELEMENT_ENTITY_CREATED_BY_FIELD"),)), "IBLOCK_ID" => novo MainEntityIntegerField("IBLOCK_ID", array => true, "required" title" => Loc::getMessage("ELEMENT_ENTITY_IBLOCK_ID_FIELD"),)), "IBLOCK_SECTION_ID" => novo MainEntityIntegerField("IBLOCK_SECTION_ID", array("title" => Loc::getMessage("ELECK_ENT_SECTION_DIB))," ACTIVE" => novo MainEntityBooleanField("ACTIVE", array("values" => array("N", "Y"), "default_value" => "Y", "title" => Loc::getMessage("ELEMENT_ENTITY_ACTIVE_FIELD "),)), "ACTIVE_FROM" => novi MainEntityDatetimeField("ACTIVE_FROM", array("title" => Loc::getMessage("ELEMENT_ENTITY_ACTIVE_FROM_FIELD"),)), "ACTIVE_TO" => novi MainEntityDatetimeField("ACTIVEDatetimeField(", array("title" => Loc::getMessage("ELEMENT_ENTITY_ACTIVE_TO_FIELD"),)), "SORT" => novo MainEntityIntegerField("SORT", array("default_value" => 500, "title" => Loc::getMessage ("ELEMENT_ENTITY_SORT_FIELD"),)), "NAME" => novo MainEntityStringField("NAME", array("required" => true, "validation" => array(__CLASS__, "validateName"), "title" => Loc ::getMessage("ELEMENT_ENTITY_NAME_FIELD"),)), "PREVIEW_PICTURE" => novo MainEntityIntegerField("PREVIEW_PICTURE", array("title" => Loc::getMessage("ELEMENT_ENTITY_PREVIEW_PICTURE_FIELD"),)" =>novi PREGLED_TEXT MainEntityTextField("PREVIEW_TEXT", array("title" => Loc::getMessage("ELEMENT_ENTITY_PREVIEW_TEXT_FIELD"),)), "PREVIEW_TEXT_TYPE" => novo MainEntityEnumField("PREVIEW_TEXT_TYPE", array("values" => array(self:> TYPE_TEXT, self::TYPE_HTML), "default_value" => self::TYPE_TEXT, "title" => Loc::getMessage("ELEMENT_ENTITY_PREVIEW_TEXT_TYPE_FIELD"),)), "DETAIL_PICTURE" => novi MainEntityIntegerField("DETAIL_ray_ray" "title" => Loc::getMessage("ELEMENT_ENTITY_DETAIL_PICTURE_FIELD"),)), "DETAIL_TEXT" => novo MainEntityTextField("DETAIL_TEXT", array("title" => Loc::getMessage("ELEMENT_ENTITY_DETAIL")FIELD_TEXT), "DETAIL_TEXT_TYPE" => novo MainEntityEnumField("DETAIL_TEXT_TYPE", array("values" => array(self::TYPE_TEXT, self::TYPE_HTML), "default_value" => self::TYPE_TEXT, "title" => Loc:: getMessage("ELEMENT_ENTITY_DETAIL_TEXT_TYPE_FIELD"),)), "SEARCHABLE_CONTENT" => novo MainEntityTextField("SEARCHABLE_CONTENT", array("title" => Loc::getMessage("ELEMENT_ENTITY_SEARCHABEL_USTEST"), "NewFID_SEARCHABELDWF"), "NewFID_USFID" tegerField( "Wf_status_id", Array ("Title" => Loc :: getmessage ("Element_entity_wf_status_id_field"),)), "WF_PARENT_ELEMENT_ID" => Novo MainentityintegerField , Array ("Title" => Loc :: Getmessage ("Element_part_)" ), "WF_NEW" => novo MainEntityEnumField("WF_NEW", array("values" => array("N", "Y"), "title" => Loc::getMessage("ELEMENT_ENTITY_WF_NEW_FIELD") ,)), "WF_LOCKED_BY" => novo MainEntityIntegerField("WF_LOCKED_BY", array("title" => Loc::getMessage("ELEMENT_ENTITY_WF_LOCKED_BY_FIELD"),)), "WF_DATE_LOCK" => novi MainEntityDatetimeField("titleDatetimeField" > Loc::getMessage("ELEMENT_ENTITY_WF_DATE_LOCK_FIELD"),)), "WF_COMMENTS" => novo MainEntityTextField("WF_COMMENTS", array("title" => Loc::getMessage("ELEMENT_ENTITY_WF_COMMENTS_FIELD)),FIELD ="_COMMENTS_EC" > new MainEntityBooleanField("IN_SECTIONS", array("values" => array("N", "Y"), "title" => Loc::getMessage("ELEMENT_ENTITY_IN_SECTIONS_FIELD"),)), "XML_ID " => novo MainEntityStringField("XML_ID", array("validation" => array(__CLASS__, "validateXmlId"), "title" => Loc::getMessage("ELEMENT_ENTITY_XML_ID_FIELD"),)), "CODE" => novi MainEntity"String ", array("validation" => array(__CLASS__, "validateCode"), "title" => Loc::getMessage("ELEMENT_ENTITY_CODE_FIELD"),)), "TAGS" => novo MainEntityStringField("TAGS ", array( "validation" => array(__CLASS__, "validateTags"), "title" => Loc::getMessage("ELEMENT_ENTITY_TAGS_FIELD"), "TMP_ID" => new MainEntityStringField("TMP_ID", array( "validation" => array( __CLASS__, "va

    I primjer rada sa ovim entitetom

    //Odabir podataka $dbElements = BitrixIblockElementTable::query() ->setFilter(["IBLOCK_ID" => CATALOG_IBLOCK_ID, "ACTIVE" => "Y"]) ->setSelect(["NAME", "ID", "DETAIL_PAGE_URL" ", "DATE_ACTIVE_FROM"]) ->addSelect("IBLOCK_SECTION_ID", "PARENT_SECTION") ->setLimit(10) ->addOrder("id", "DESC") ->exec(); while ($arElement = $dbElements->fetch()) ( echo "($arElement["NAME"]) - " . $arElement["DATE_ACTIVE_FROM"]->format("d.m.Y H:i:s"); ) //Dodavanje zapisa $addResult = BitrixIblockElementTable::add([ "NAME" => "Naziv novog elementa", "IBLOCK_ID" => CATALOG_IBLOCK_ID ]); if (!$addResult->isSuccess()) ( echo implode("
    " ,$addResult->getErrorMessages()); )

    Bitrix je vrlo ponosan na svoj Highload Blocks modul, koji je u potpunosti napisan pomoću D7.
    Ranije su imali samo informacijske blokove kao skladište za proizvoljan skup informacija. Informacioni blok, za one koji ne znaju, je entitet koji je pohranjen u bazi podataka kao kompleks nekoliko tabela (1 tabela za „osnovna“ polja elementa informacionog bloka i do 2 tabele za svojstva element informacionog bloka). Sva polja osnovnih elemenata svima infoblokovi su pohranjeni u jednoj tabeli. Ako imate 15 informacijskih blokova, od kojih svaki ima 500.000 elemenata, svi ovi elementi će zapravo biti u jednoj tabeli. Dodatna svojstva elemenata infobloka spajaju se iz drugih tabela. Ako se radi o informacijskim blokovima prve verzije, tada su sva svojstva svih informacijskih blokova također u jednoj tablici, a u slučaju informacijskih blokova 2.0 (zdravo, marketing) - svojstva svakog informacijskog bloka su već podijeljena u različite tabele .
    I cijela ova stvar se prirodno usporila već na relativno malim skupovima podataka. 400k elemenata u jednom informacionom bloku već prilično usporavaju rad admin panela. Marketeri u Bitrixu su razmišljali i kreirali Highload blokove! Razlika u implementaciji između konvencionalnih informacijskih blokova je minimalna. Sada, za svaki blok visokog opterećenja, kreira se sopstvena tabela + pored toga, kreira se još jedna tabela za skladištenje više vrednosti. Uobičajeni pristup kreiranju obične tabele u bazi podataka nazvali su ponosnim imenom highload jednostavno zato što usporava manje od običnih blokova informacija!
    Osim toga, unutar modula, da bi funkcionirao prema D7, klase entiteta se generiraju dinamički i procjenjuju pri svakom pogotku.To je highload.

    Gledaj u ovo

    Javna statička funkcija compileEntity($hlblock) ( globalno $USER_FIELD_MANAGER; // generiranje entiteta i upravitelja podataka $fieldsMap = array(); // dodaj ID $fieldsMap["ID"] = array("data_type" => "cijeli broj", "primary" => true, "autocomplete" => true); // izgraditi klasu datamanager $entity_name = $hlblock["NAME"]; $entity_data_class = $hlblock["NAME"]; if (!preg_match("/^ +$/i", $entity_data_class)) ( izbaci novi MainSystemException(sprintf("Nevažeći naziv entiteta `%s`.", $entity_data_class)); ) $entity_data_class .= "Tabela"; if (class_exists($entity_data_class)) ( // ponovo izgradi ako već postoji EntityBase::destroy($entity_data_class); ) else ( $entity_table_name = $hlblock["TABLE_NAME"]; // napravi sa praznom mapom $eval = " class ".$entity_data_class. " proširuje ".__NAMESPACE__."DataManager (javna statička funkcija getTableName() (vrati ".var_export($entity_table_name, true)."; ) javna statička funkcija getMap() (vraća ".var_export($fieldsMap, true)."; ) javna statička funkcija getHighloadBlock() (vrati ".var_export($hlblock, true)."; ) ) "; eval($eval); ) // zatim konfigurišite i priložite polja /** @var BitrixMainEntityDataManager $entity_data_class */ $entity = $entity_data_class::getEntity(); $uFields = $USER_FIELD_MANAGER->getUserFields_ ".$hlblock["ID"]); foreach ($uFields kao $uField) ( if ($uField["MULTIPLE"] == "N") ( // samo dodajte jedno polje $field = $USER_FIELD_MANAGER->getEntityField ($uField, $uField["FIELD_NAME"]); $entity->addField($field); foreach ($USER_FIELD_MANAGER->getEntityReferences($uField, $field) kao $reference) ( $entity->addField($reference ); ) ) else ( // izgraditi utm entitet static::compileUtmEntity($entity, $uField); ) ) return EntityBase::getInstance($entity_name); )

    Dođavola s tim, ali ti isti blokovi visokog opterećenja ne mogu ni na koji način djelovati kao alternativa običnim informacijskim blokovima. Ispostavilo se da su izmišljeni samo za skladištenje nehijerarhijskih referentnih podataka. Osim toga, modul još uvijek ne podržava takve neophodne funkcije u admin panelu, kao što je filtriranje po polju kao što je „Date“; nemoguće je pozvati HLblock entitet nekim ljudima razumljivim imenom kako se administrator ne bi uplašio svaki put kada ulazite na stranicu za uređivanje entiteta, na primjer, BrandReference. Sve ovo sugerira da je ova stvar zamišljena kao alternativa sporim blokovima informacija, ali nisu imali vremena da je završe (ili se nisu snašli, ili su išli protiv interesa poslovanja), te su na kraju pustili Poluproizvedena funkcionalnost kao nova funkcija, a trgovci su je pročešljali i učinili da izgleda lijepo, došli su na ovu ideju.

    C - Kontroler ili komponenta

    Redovna komponenta u Bitrix-u može se uporediti sa widgetima iz Yii-a. Ovo je određeni kontejner, odvojen od svih ostalih kontejnera, koji uzima neke parametre kao ulaz, obavlja neki posao i sa rezultatom rada povezuje pogled. Programeri Bitrixa duboko su uvjereni da komponente koje obezbjeđuju iz kutije rješavaju većinu problema s kojima se njihove kolege suočavaju. Ali, kao i obično, programeri uvijek ništa ne vole, a mogućnosti standardnih komponenti uvijek "malo" nedostaju. Stoga je Bitrixoids odlučio dati programerima priliku da modifikuju rezultat komponente... koristeći pogled. U direktoriju šablona komponente možete kreirati datoteku result_modifier.php, u koju možete dodati svoje podatke u rezultat komponente. A ako iznenada poželite koristiti ove podatke u drugom predlošku, morat ćete kopirati i zalijepiti ovu datoteku (ili uključiti ovu datoteku iz drugog predloška). Oduvijek me mučilo pitanje - čemu služi ovaj patos? Zašto ne biste dodali gomilu zahtjeva direktno u PHP šablon? Pokazalo se da je razlika mala.
    O čemu pričam o šablonima u dijelu o kontrolerima...

    Bitrix ima 2 tipa 2.0 komponenti (ponovo zdravo marketing) - regularne i složene. Uobičajena komponenta je widget. Kompleksna komponenta je neka vrsta kontrolera + rutera, koji na osnovu URL-a razumije koja stranica sa skupom widgeta treba biti prikazana. Operativni postupak je otprilike ovakav:

    • url kaže /catalog/bolshaya-zelenaya-shapka.html
    • koristeći mod_rewrite, Bitrix razumije da za fizički odjeljak /katalog uvijek morate uključiti datoteku /catalog/index.php
    • složena komponenta analizira URL i razumije da trebate povezati detaljnu stranicu proizvoda, nazovimo to detalj
    • složena komponenta prikuplja parametre koji su neophodni za rad njenih podređenih komponenti
    • složena komponenta povezuje svoj predložak detail.php, unutar kojeg je specificirana veza podređenih regularnih komponenti

    Ne izgleda baš lijepo, ali može funkcionirati. Međutim, nije sve tako jednostavno... Ako promenite parametre složene komponente pomoću vizuelnog uređivača, fajl sa postavkama adresiranja (urlrewrite.php) će biti prepisan od strane sistema. Štaviše, ako ste odjednom napisali nešto pogrešno tamo za druge stranice, nešto će se sigurno pokvariti bez ikakvog upozorenja. U praksi to može dovesti do gubitka funkcionalnosti čitavih dijelova stranice.
    Postavljanje parametara složene komponente može biti mukotrpno. Jedna takva komponenta lako može imati stotine ulaznih parametara, jednostavno zato što je potrebno konfigurirati parametre podređenih komponenti.
    Kompleksna komponenta - čini se da je ruter. Međutim, sve rute koje kreirate u ovoj komponenti neće biti uključene u automatski generirani sitemap.xml. Ovi linkovi neće biti uključeni u modul pretraživanja. Nećete imati načina da generirate adresu rute izvana (na primjer, želite da stavite link na stranicu sa detaljima o brendu negdje u bočnoj traci i nećete moći tražiti od rutera da generiše ovaj URL ).

    Općenito govoreći, nitko zapravo ne obavlja funkcije rutera u Bitrixu. U infoblokovima možete konfigurirati URL predložak za stranicu infobloka, stranicu odjeljka infobloka i stranicu elementa infobloka. To je to, infoblokovi više ne mogu imati stranice.
    Za forume, moguće je prilagoditi šablone nekih stranica. Može se prilagoditi za blogove. Možda se nešto može konfigurirati negdje drugdje... sve je to toliko decentralizirano da postaje prilično teško sve to spojiti.

    Redovne komponente su malo jednostavniji entiteti od složenih komponenti. Njihov zadatak je uzeti skup parametara kao ulaz, obraditi ih, uneti rezultat rada u šablon i sve keširati.
    Sva logika komponente je sadržana u datoteci component.php. Sa verzijom 12 Bitrixa (trenutno je aktualna verzija 16, prošle su 4 godine), postalo je moguće "koristiti OOP" u komponentama. Ova inovacija je da umjesto datoteke component.php možete kreirati datoteku class.php, u koju, umjesto uobičajenih noodlesa, možete napisati klasu naslijeđenu od CBitrixComponent. I ovo je bio veliki korak naprijed, jer... postalo je moguće naslijediti komponente i uopće ne koristiti result_modifier.php, a ne prakticirati copy-paste ako odjednom trebaš u velikoj mjeri prilagoditi komponentu. Ali ni ovdje još uvijek nije sve tako dobro. Od cjelokupnog skupa komponenti, samo 25-30 posto može se pohvaliti da ima klasu u svom arsenalu. Štaviše, dobra polovina njih vam jednostavno neće dati priliku da se potpuno proširite, jer... Često su napisane nelogično.
    Usput, dobri ljudi pokušavaju standardizirati, nekako pomoći programerima da pišu komponente, a postoji i odgovarajući alat

    V - Prikaz ili predlošci

    Predlošci u Bitrix-u se mogu podijeliti u nekoliko tipova:

    • Regularni i složeni 2.0 predlošci komponenti
    • Website templates
    • Predlošci za druge entitete (poštanske poruke, bilteni, web obrasci, generatori izvoza i još mnogo toga)

    Predlošci komponenti čak imaju mogućnost korištenja predložaka. U principu, možete povezati bilo koji šablonski mehanizam, ali nema pomoćnih alata iz kutije. Ako nekome treba, imam par linkova za nastavke za grančicu i oštricu, koji rade i dosta se koriste u proizvodnji. Ali čak i ovdje bitriksoidi su postali izopačeni. Predložak se može koristiti samo s komponentama. Neće biti moguće povezati predložak sa rendererom predložaka web stranice ili drugim entitetima, jer tamo nema renderera.

    Još jedna neugodna stvar u vezi sa šablonima komponenti je njihovo postavljanje. Komponenta je povezana pomoću jednostavnog dizajna

    $APPLICATION->IncludeComponent("bitrix:catalog.section", "template_name", );

    Drugi parametar je naziv predloška komponente. Dakle, ovisno o različitim uvjetima, lokacija ovog predloška može biti na najneočekivanijim mjestima:

    • bitrix/components/bitrix/catalog.section/templates/template_name
    • local/components/bitrix/catalog.section/templates/template_name
    • bitrix/templates/.default/components/bitrix/catalog.section/template_name
    • bitrix/templates/site_template/components/bitrix/catalog.section/template_name
    • local/templates/.default/components/bitrix/catalog.section/template_name
    • local/templates/site_template/components/bitrix/catalog.section/template_name
    • bitrix/components/bitrix/catalog/templates/.default/bitrix/catalog.section/template_name
    • local/templates/site_template/components/bitrix/catalog/.default/bitrix/catalog.section/template_name

    I još nisam naveo sve opcije...

    Šablon sajta se može smatrati skupom fajlova: header.php, footer.php (da, sajt ih mora imati), description.php (sistemski opis šablona sajta), template_styles.css (stilovi šablona sajta), direktorij sa predlošcima komponenti i drugom grupom manje značajnih datoteka. To je sve. I na to ne možete uticati ni na koji način, ne možete ništa učiniti. Nemoguće je pokupiti predložak.

    O drugim šablonima nema šta da se kaže. Oni su ili jednostavno pohranjeni u bazi podataka u obliku izgleda sa nekim „promjenjivim“ podacima uključenim u njega, ili je to glupa PHP datoteka koja obavlja sav posao, od preuzimanja parametara iz baze podataka do prikazivanja informacija. Na primjer, možete pogledati generator YML datoteka za tržište. Nema smisla postavljati ga ovdje, jednostavno zato što je prilično velik, oko 2k redaka. Kome treba može proguglati, nalazi se u /bitrix/modules/catalog/load/yandex_run.php

    Priroda datoteke

    Kao što je gore postalo jasno, u Bitrixu arhitektura nije baš dobra. Ali Bitrix ima još jedan važan aspekt svoje arhitekture.
    Bitrix je CMS sa pola datoteke. Mnoge stvari se kontrolišu pomoću nekih fajlova:

    • Treba vam stranica - kreirajte fajl
    • Potreban vam je skup stranica - kreirajte datoteku i povežite tamo komponentu koja radi sa infoblokovima
    • Morate postaviti naslov stranice - uredite datoteku
    • Morate postaviti naslov za sve stranice odjeljka - kreirajte poseban file.section.php u korijenu ovog odjeljka
    • Morate urediti prava - uredite datoteku .access.php
    • Postavke prije inicijalizacije sistema - u datoteci dbconn.php, .settings.php i .settings_extra.php
    • result_modifier.php, component_epilog.php, init.php, .parameters.php, .description.php ....

    I postoji ogroman broj takvih posebnih datoteka razbacanih po cijelom Bitrixu. S jedne strane, to daje određenu fleksibilnost pri radu sa sistemom. S druge strane, ovo se može pretvoriti u muku i za programera i za upravitelja stranice. Fajlovi stranica se ponekad pretvaraju u zbrku PHP koda, rasporeda i komponenti dodataka. Kao rezultat toga, vizuelni uređivač može pogrešno raščlaniti ovu datoteku, a prilikom uređivanja može lako izbjeći PHP oznake na nekim mjestima, što će dovesti do toga da stranica ne radi. Kažete - nema potrebe pisati PHP kod u takve fajlove? Da, znam. Ali Bitrix vas vrlo često i bez alternative prisiljava na to.
    I morate stalno držati informacije u svojoj glavi o tome kakve su to datoteke i koje podatke mogu sadržavati. Različite datoteke bi trebale sadržavati različite podatke s različitim strukturama i morate ih zapamtiti za svaku opciju. Traženje ovoga u dokumentaciji svaki put je težak posao.

    Pored navedenog

    Možete se beskrajno žaliti kako sve loše funkcionira u Bitrixu. Po mom mišljenju, sve ove pritužbe mogu se okarakterisati jednom frazom - "nekako ne u potpunosti". I zaista, ako Bitrixoids iznenada najavi neku funkciju, onda je nekako ne puštaju u potpunosti, ne dovršavaju, ne dovode je na pamet. Ima dosta primjera:

    • implementiran ORM - još nije završen, ne može se u potpunosti koristiti
    • Napravili smo autoloader, radi samo u modulima, a ne po standardima
    • omogućio je povezivanje šablona, ​​ali ga ne možete koristiti svuda, a ne u potpunosti
    • itd. i tako dalje.

    Ukratko, pokušaću da okarakterišem preostale probleme sa kojima se svakodnevno suočavam.

    Admin

    Ako je neko radio sa admin panelom, kreirao svoje stranice u administrativnom delu na način na koji Bitrix predlaže da to uradi, razumeće me. To je samo pakao. Za one koji nisu upoznati, Bitrix predlaže korištenje nudle datoteke za svaku stranicu. Na primjer, stranica za detaljan pregled narudžbe u admin panelu koju su napravili Bitrix programeri zauzima 4k redaka. Moj IDE počinje da usporava kada gledam sadržaj ove datoteke. Tu imate php, js i html. Dobro je da su se riješili SQL-a, iako sam siguran da je na drugim administrativnim stranicama.
    A šta je spriječilo administrativne stranice da rade koristeći iste komponente nije jasno. Jednostavno ne postoji način da prilagodite većinu administrativnih stranica. U slučaju komponenti, to bi se moglo učiniti za kratko vrijeme.
    Inače, dobri ljudi su napravili modul koji će vam pomoći da napravite administrativne stranice

    js framework

    Bitrix ima js komponentu koja djeluje kao neka vrsta klijentskog okvira. Niko od programera to ne voli iz nekoliko razloga:

    • gotovo da nije dokumentovano
    • on je monstruozan
    • u velikoj mjeri duplira jquery poznat mnogima

    Bitrix ga vrlo često koristi u svojim komponentama, izazivajući time još veći bijes među programerima. Jezgro ove biblioteke u minimiziranom obliku je 85 kb, što nije malo. Ne možete izbjeći njegovo povezivanje ako želite koristiti sve mogućnosti Bitrixa (kompozit, upravljanje imovinom).

    Copy-paste duh

    U posljednje vrijeme, sve rjeđe, ali i dalje prilično često, Bitrix vas tjera da nešto kopirate i zalijepite. Ako želite izmijeniti rad komponente, kopirajte je i zalijepite. Ako želite da kreirate sopstveni šablon za otpremanje, kopirajte i zalijepite sistemski i završite ga. Ako želite da napravite skoro isti predložak koji imate, kopirajte ga i zalijepite ga i malo promijenite. O tome čak govore i na kursevima za programere početnike. Nemam riječi.

    Upravljanje imovinom i CDN

    Zaista mi se sviđa način na koji Bitrix upravlja resursima. U principu, moguće je registrovati skup određenih "biblioteka". Svaka biblioteka je skup css/js fajlova, koji mogu zavisiti od nekih drugih biblioteka. Ako povežete biblioteku sa stranicom, tada će prije povezivanja sve ovisnosti biti riješene i sve zavisne biblioteke će biti umetnute u stranicu. Čini se da je sve u redu, samo će svaki resurs biti umetnut kao zaseban fajl u skriptu ili oznaku veze. I zahvaljujući tome, postoje stranice koje imaju 30-50 skripti i isto toliko povezanih stilskih datoteka.
    To je usrano pitanje, rekli su u Bitrixu, i napravili magičnu kvačicu koja kombinuje sve ove fajlove u jedan. I pojavile su se stranice gdje su umjesto 50 skripti bile 2, svaka od 300-500 kb. Prije nekog vremena ovo spajanje je radilo s greškama i spajalo je nekoliko puta iste resurse, ali sada se čini da je popravljeno.
    A onda su im se Bitrixoidi sklonili s puta - dodali su mogućnost upload-ovanja svih resursa na CDN server. Koji uvek padne...
    Zatim se pojavio Google Pagespeed Insights, koji je preporučio premještanje svih resursa na dno stranice. A u Bitrixu su opet napravili magični checkbox koji glupo izostavlja sve resurse u tijelu ako nisu označeni posebnim atributom.
    Oni također distribuiraju minimizirane verzije svojih skripti zajedno sa kutijom, koja se povezuje kada koristite drugi čarobni okvir za potvrdu na admin panelu.
    Općenito, nema scss-a za vas, nema TypeScript-a. Ako želite kompetentno upravljati resursima, nemojte koristiti ugrađeni Bitrix sistem, koristite webpack koji se lako može upariti sa Bitrixom.

    Više stranica/višejezično

    Ovo je vjerovatno najgora glavobolja za programera, koja traje od samog početka proizvoda. Ne možete jednostavno kreirati višejezičnu web stranicu. A ako vam treba višejezični katalog s različitim cijenama i valutama, onda se to pretvara u brašno, za koje također morate platiti urednu svotu (morat ćete izdvojiti za kupovinu dodatne licence za sljedeću jezičnu verziju stranica).
    Ako kreirate višejezičnu i viševalutu web stranicu, budite spremni na činjenicu da će se Bitrix tome vrlo agresivno oduprijeti. Postavke za više lokacija su decentralizirane na cijelom administrativnom panelu. Svaki entitet u admin panelu ima svoju zavisnost od jezičke verzije sajta. Neki entiteti možda uopće ne podržavaju ovisnosti o mjestu/jeziku, dok drugi imaju samo nedvosmislenu vezu s jezikom, tako da će ovaj entitet morati biti dupliciran, a zatim podržan.
    U osnovnoj verziji, da bi blok informacija radio na nekoliko jezika, morat ćete kreirati duplikat ovog informacijskog bloka. Ali u praksi to niko ne radi i pokušava da smisli sopstvene načine za centralno skladištenje jednog entiteta, distribuirajući njegove atribute zavisne od jezika drugim objektima za skladištenje.
    Ne možete postaviti podrazumevani jezik tokom lokalizacije. Ako imate jezičku varijablu koja opisuje neku frazu na ruskom, a ova jezička varijabla nije u engleskoj verziji, tada će se na engleskom mjestu prikazati prazan red i na to se ne može utjecati ni na koji način (u mnogim slučajevima možete ostavite ruski izraz tako da nema praznina).

    Mehanizam upravljanja pravima

    Bili su veoma pametni sa ovim podsistemom. Često je teško shvatiti zašto ste nekom entitetu dodijelili prava gledanja, ali ih korisnik ne može koristiti. Na primjer, da biste dali pravo na uređivanje informacijskog bloka, morate dati pristup direktoriju /bitrix/admin, dodijeliti prava za određeni blok informacija i dodijeliti prava u glavnom modulu. Potrebno je uraditi previše operacija da bi se izdala prava za jedan entitet. A ako nema dovoljno prava, onda bez brčkanja po izvornom kodu nema načina da se shvati zašto.

    Konfiguracija

    Bitrix nema centralizovano čvorište koje bi vam omogućilo upravljanje sistemskim postavkama. Postavke su ponovo decentralizirane u cijelom sistemu. Opcije su dostupne u postavkama modula, u postavkama komponenti, u COption-u (ne postavljaju se u admin panel). U admin panelu opcije za jedan modul mogu se rasporediti na 3-4 različite stranice, koje se nalaze na potpuno različitim mjestima. urlrewrite se može uređivati ​​preko admin panela! Sada također .settings i .settings_extra. Ponekad uopće nije jasno koji od njih ima veći prioritet, vrlo često nema dovoljno objašnjenja za opcije, a odnosi su nejasni. Ne postoji izvorni način za dijeljenje konfiguracije između programera.
    Postavke mogu biti vrlo nelogične. Ponekad dođe do apsurda... pogledajte komponentu bigdata - može li neobučena osoba to postaviti?

    Integracija sa 1C

    Ovo je stavka na listi Bitrix funkcija na koju pada prilično veliki broj kupaca. Bitrix obećava da će postaviti dvosmjernu integraciju stranice sa 1C u 2 klika, koja će trenutno isporučiti sadržaj i dokumente iz jednog sistema u drugi.
    Da, zaista jeste, ali uz nekoliko upozorenja.
    Prvo, da biste izvršili integraciju "iz kutije" bez dodatnog napora, morate učiniti sve točno kako je napisano u Bitrix dokumentaciji - izgraditi katalog na web stranici prema pravilima koja Bitrix nudi i izgraditi katalog u 1C koje Bitrix zahtijeva. U idealnom slučaju, kreirajte sve od nule, a onda će vam možda sve raditi iz kutije.
    Drugo, Bitrix nije kompatibilan sa svim 1C konfiguracijama iz kutije. Vrijedi prvo provjeriti
    Treće, ne postoji idealan svijet. Tipično, kupac koji želi web stranicu već ima maloprodajni biznis, što znači da već ima 1C, što je ogromna deponija smeća. I ovo smeće se mora baciti na lokaciju. A kako se stranica ne bi pokazala kao isto smeće, potrebno je značajno poboljšati mehanizam razmjene.
    Vrlo često se zahtjevi kupaca uvelike razlikuju od vizije proizvoda koju je formirao Bitrix tim, a zatim usavršavanje mehanizma zamjene može biti prilično skupo, uporedivo po intenzitetu rada sa razvojem jedinstvenog modula za razmjenu za konkretan slučaj.
    Stoga, ne morate gajiti iluzije da ćete moći lako integrirati svoju stranicu sa 1C. Sve su to mahinacije marketinških stručnjaka.

    Rafiniranje razmjene sa 1C također je posebna tema. Klasa CIBlockCMLImport je odgovorna za organizaciju razmjene kataloga - 5.7k redaka. Jedna od glavnih metoda koja najčešće zahtijeva proširenje je CIBlockCMLImport::ImportElement, koja sadrži više od 1k linija. Dovoljno je da ga jednom naslijedite, nekoliko puta ažurirate proizvod u dužem vremenskom periodu i možete dobiti neradnu razmjenu sa 1C. Stoga se programeri često ne zamaraju ovom klasom i pokušavaju nekako ući u proces uvoza koristeći rukovaoce događajima. Rad sa obrađivačima događaja u Bitrixu, posebno u modulu infoblokova, također nije baš ugodno iskustvo, makar samo zato što događaji istog tipa nisu jednolično raspoređeni, a neki događaji jednostavno nisu dovoljni.
    Generalno, stvari su tužne kao i ranije.

    Nedosljednost

    Ponekad mi se čini da programeri različitih modula zapravo ne komuniciraju jedni s drugima. Kada proučavate izvore kernela, nailazite na vrlo heterogena rješenja koja bi se mogla implementirati na jednom motoru, ali se iz nekog razloga različito implementiraju.
    Na primjer, možete uzeti svojstva elemenata informacijskog bloka i korisničkih polja. Oba entiteta su zapravo dodatno polje za drugi entitet. Ima vrstu, značenje i opis. Vrijednost je pohranjena u odvojenim tablicama baze podataka; one imaju otprilike sličan interfejs za pristup podacima. Pa zašto ne napraviti isti interfejs za njih?
    Krajem marta prodajni modul je ažuriran na najnoviju verziju, a obećali su i proizvoljna svojstva za narudžbe. Postoji li zaista novi, treći interfejs za rad sa proširenim svojstvima entiteta?

    Bitrix24

    Ovo je generalno posebna tema za diskusiju. Zbog ovog sistema često nastaje zabuna. Postoje 2 opcije za B24 - SaaS i Standlone. Postoji tržište za B24, ali sadrži aplikacije samo za SaaS verziju! Ako imate verziju u kutiji, kupljenu za 200 hiljada, nećete moći da instalirate tako popularne aplikacije kao što je dizajner dokumenata, a uopšte nećete moći da instalirate nijednu aplikaciju sa tržišta za Bitrix24 na svoj Bitrix24. Ovo je takav paradoks.
    Umjesto toga, tržište iz obične verzije će biti dostupno na vašem Bitrix24. Postoji mnogo više rješenja, ali su koncentrisana uglavnom na Site Management, a ne na B24.

    Bitrix24 je, kako su mi rekli u odjelu tehničke podrške, holistički sistem. Ako ometate rad standardnih komponenti sistema, budite spremni da će se ova funkcionalnost prekinuti s narednim ažuriranjima. Bitrix neće računati na vas da finalizirate komponente portala, i to uprkos činjenici da svoje klijente službeno upućuju partnerima

    Usput, modifikacija komponenti u verziji B24 u kutiji je prilično težak zadatak. Komponente koje generišu js kod, koji, koristeći ajax, pristupa php kodu, koji generiše html+js kao odgovor. Ovo je paklena mješavina u koju zaista ne želite da ronite.

    Dokumentacija

    Bitrix dokumentacija zaostaje za razvojem proizvoda 1-1,5 godina. Kod je veoma slabo pokriven phpDocs-om, i često je komentar ispred klase samo za prikaz, automatski se generiše u IDE-u.
    Sam stil prezentacije dokumentacije u zvaničnim izvorima često je previše „slobodan“, a sadržaj nekih članaka u dokumentaciji možda nema nikakve veze sa samim Bitrixom.
    Kurs za programere ima mnogo informacija, ali format u kojem se programer upoznaje sa mogućnostima sistema ne pruža nivo percepcije koji je potreban. Ako odete u Symfony Cookbook, tamo je sve izloženo, svi potrebni aspekti su opisani ovisno o verziji. Dok u Bitrixu, kurs za obuku programera sadrži, na nejasan način, strukturirane informacije o starim i novim kernelima, koje se prvo predstavljaju odvojeno, a zatim miješaju, što početnicima zadaje glavobolju.

    Organizacija procesa razvoja

    Zbog specifičnosti sistema, nije tako lako organizovati prikladan razvojni proces. Nije najnovija verzija Business edition (koja je bila pri ruci) nakon instalacije zauzima, razmislite, skoro 530 megabajta

    $ du -s *|sort -nr|cut -f 2-|dok čita a;do du -hs $a;gotovo 523M bitrix 204K upload 64K bitrixsetup.php 56K desktop_app 20K readme.html 20K licence.html 4.0K web . config 4.0K urlrewrite.php 4.0K readme.php 4.0K licence.php 4.0K install.config 4.0K index.php

    Od ovog volumena, dobra polovina su binarni programi i instalateri, koji općenito nisu potrebni za kontrolu verzija. Uopšteno govoreći, uobičajeno je da se ne verzija Bitrix jezgra. Bitrix programeri sami garantuju integritet jezgre i upravljaju zavisnostima verzija različitih modula tokom ažuriranja. Ali ovo odmah nosi barem jedan veliki nedostatak - nemoguće je implementirati potpuno funkcionalan projekat s jednim timom iz kontrole verzija; morate ga sastaviti u dijelovima: nabavite izvore kernela iz Bitrix sigurnosne kopije, a izvore programera iz git-a .
    Ni sa bazom stvari ne idu dobro. Ako sami možete koristiti migracije tokom razvoja, tada Bitrix ubacuje ažuriranja u bazu podataka koristeći obične skripte koje ne možete kontrolirati. Stoga, prilikom ažuriranja, i dalje ćete morati prenositi sigurnosne kopije baze podataka sa centralnog razvojnog hosta na druge programere.
    Dobri ljudi, opet, režu alate koji pomažu u organizaciji svega ovoga, ali nažalost još uvijek nije moguće natjerati Bitrix da se pridržava ovih pravila.
    Zvanično, Bitrix vam omogućava da imate 2 kopije jedne distribucije. Jedan je za proizvodnju, drugi za razvoj. Ako imate nekoliko programera na jednom projektu, onda ste, takoreći, odmetnik) U stvari, dovoljno je da prekinete mašinu sa Bitrixom dolazne i odlazne veze sa/na www.bitrixsoft.com, a zatim mogu prikovati onoliko kopija razvoja koliko želite, oni jednostavno neće moći sami da se ažuriraju.

    Kolege

    I poslednje pitanje koje bih želeo da se dotaknem.
    Zbog činjenice da Bitrix ima nisku barijeru za ulazak, među kompanijama koje pružaju usluge na ovom tržištu ima dosta nekvalifikovanog osoblja. Vidio sam mnogo različitih projekata tokom svoje karijere (ukupno više od sto) završenih na 1C-Bitrixu. Mogu sa sigurnošću da kažem da je 95% njih urađeno na „bagerski“ način. Vrlo rijetko smo nailazili na projekte čiji je razvoj imao smisla pristupa, ali to su bili samo neki. Ovo je sve veoma tužno.

    zaključci

    Naravno, svi nedostaci se ne mogu sagledati u jednom članku. Svakog dana nailazite na neke sitnice koje vam svakodnevno ometaju posao. Ali jednostavno je nemoguće uzeti u obzir sve takve sitnice, a vjerovatno i nema potrebe.

    Kakvi se zaključci ovdje mogu izvući? Bitrix je izuzetno složen sistem zbog činjenice da ima loše osmišljenu arhitekturu i mnoge nedostatke koji nastavljaju da žive u proizvodu dugo vremena. S druge strane, Bitrix je prilično jednostavan sistem koji zahtijeva mnogo niži nivo kvalifikacija za početak, za razliku od frameworka.
    Podržavanje ovog proizvoda je veoma nezahvalan zadatak u poređenju sa proizvodima kao što su Symfony, Laravel, Yii. Proizvod zaista voli da stavlja žbicu u točkove i neiskusnih i iskusnih programera, što se, zauzvrat, može odraziti na cenu usluga iskusnih Bitrix programera.

    Da li žalim što sam proveo toliko vremena radeći sa ovim sistemom? Radije da nego ne. Bilo bi mudrije potrošiti ovo vrijeme proučavajući nešto ispravnije i logičnije (što sada aktivno pokušavam). Ali slučajno se dogodilo da na početku mog putovanja nije bilo nikoga da me uputi u pravom smjeru.

    Ako ste početnik PHP programer, onda biste radije proučavali okvire kao što su Symfony, Laravel, Yii, ZendFramework nego Bitrix. Vjerujte mi, to će se više nego isplatiti u budućnosti. Nakon što ste savladali bilo koji od ovih okvira, neće vam biti teško da u budućnosti razvijete nešto za Bitrix. Ako nemate izbora, onda proučite Bitrix, ali u slobodno vrijeme je bolje da ipak pokušate da uronite u svijet okvira kako biste postavili svoj mozak na mjesto.

    Ako ste programer s iskustvom u Bitrixu, ali bez iskustva u drugim okvirima, onda svakako uronite u drugi svijet; otkrit ćete puno novih i korisnih znanja koja će vam pomoći da napišete mnogo bolja rješenja za 1C-Bitrix. Pokušajte koristiti rješenja iz drugih okvira u svojim projektima, srećom to nije teško učiniti zahvaljujući komponentnom pristupu potonjeg i kompozitora.

    Ako ste kupac, onda ne vjerujte Bitrix trgovcima. Ništa neće biti tako lako kao što kažu u Bitrix prezentacijama. I nemojte kriviti svoje programere za ovo, oni nemaju nikakve veze s tim. Ako želite da napravite veliku i složenu internet prodavnicu na nivou Eldorado/Mvideo/Sportmaster, onda Bitrix možda nije najbolji izbor.

    Često je tokom razvoja potrebno odabrati i izbrisati neki dio podataka označenih za brisanje. Ova potreba posebno pogađa velike baze podataka sa desetinama ili stotinama hiljada objekata označenih za brisanje. Obrada svih podataka odjednom traje jako dugo, pa je bez zgodnog alata u kojem možete jasno pregledati, odabrati i izbrisati neki dio podataka, nemoguće.

    Ova obrada je rezultat mog rada u određenom vremenskom periodu. Funkcionalnost je proširena po potrebi. Obrada radi u redovnom režimu aplikacije iu debelom klijentu upravljane aplikacije. Implementirano u obradu:

    • prikaz stabla metapodataka sa mogućnošću označavanja onih objekata baze podataka koje je potrebno izbrisati;
    • prikaz broja objekata označenih za brisanje, označenih od strane korisnika i mogućih za brisanje;
    • mogućnost uključivanja/onemogućavanja ekskluzivnog načina rada;
    • moguće je brisanje povezanih zapisa nezavisnih registara informacija;
    • mogućnost grupne zamjene pronađenih linkova;
    • prikazivanje veza do objekta koji se briše u obliku stabla. Odraz u ovom stablu strukture cikličkih (rekurzivnih) veza, isticanje ključnih veza (koje sprečavaju brisanje objekta);
    • brisanje paketa cikličkih veza u transakciji - "ili sve ili ništa", tako da "Objekat nije pronađen..." u bazi podataka;
    • mogućnost proizvoljnog odabira upita za svaki objekat metapodataka. U tom slučaju, zahtjevi za odabir mogu se kopirati. Ovo je korisno, na primjer, kada trebate izbrisati dokumente za određeni period za organizaciju; ili referentne knjige po bilo kojem kriteriju odabira;
    • očuvanje i restauracija ranije korištenih selekcija;
    • indikator napretka prilikom traženja objekata označenih za brisanje i praćenja referencijalnosti sa mogućnošću prekidanja operacije.

    Za pružanje ove funkcionalnosti, obrada aktivno koristi RAM. I, iako su poduzete mjere za optimalno korištenje RAM-a, u nekim slučajevima (velike baze podataka, veliki broj izbrisanih objekata) može doći do situacije s nedostatkom memorije. U takvim slučajevima potrebno je ograničiti listu objekata za brisanje ili se prebaciti na korištenje 64-bitnog 1C klijenta.

    Najnovija verzija 1.14. Promjene:

    • Smanjena su kašnjenja u tranziciji klijent-server na velike količine podataka;
    • Poboljšana logika za konfiguracije sa kontnim planovima bez dodijeljenih tipova podračuna .

    Verzija 1.13. Promjene:

    • Ispravljena plutajuća greška procedure obrasca pri pokušaju brisanja;
    • U redovnom obliku dodata je mogućnost označavanja povezanih linkova za brisanje. Da biste označili za brisanje, odaberite jedan ili više redova povezanih veza i odaberite “Označi za brisanje” iz kontekstnog izbornika. Povezani blok veza prikazuje stablo. Kada odaberete red u stablu i pozovete oznaku za brisanje, elementi svih podređenih redova su označeni za brisanje.
    • U redovnom obliku dodata je funkcija "Prikaži na listi" povezanog stabla veza.

    Obrada verzije 1.12. Promjene:

    • Ispravljena nekritična greška u uobičajenom obliku koja se javlja prilikom ažuriranja prikaza povezanih linkova.

    Obrada verzije 1.11. Promjene:

    • Ispravljena je greška u bojanju povezanih ključeva unosa u registar informacija.

    Obrada verzije 1.10. Promjene:

    • Vraćen je mehanizam djelovanja opcije "Brisanje zapisa registara informacija". Ova se funkcionalnost sada primjenjuje na zapise registara informacija u kojima objekt koji se briše nije glavni. Zapisi sa vodećim izbrisanim objektom se brišu automatski;
    • Onemogućeno snimanje/brisanje sa oznakom Data Exchange.Loading;
    • U stablu veza dodat je prikaz atributa "Objavljeno" i "Zastava brisanja" za povezane objekte. U normalnom obliku - u obliku slike linija, u upravljanom obliku - u obliku okvira za potvrdu.

    Obrada verzije 1.09. Promjene:

    • Ispravljena je greška u kucanju u algoritmu prilikom kontrole referencijalnosti vlasničkog imenika;
    • Promijenjen je dio koda za upravljani obrazac koji nije omogućio njegovo pokretanje na jednoj od standardnih konfiguracija;
    • Dodata kontrola nad standardnim tabelarnim dijelovima konfiguracijskih objekata.

    Obrada verzije 1.08. Promjene:

    • Implementiran rad obrade u debelom klijentu upravljane aplikacije.

    Obrada verzije 1.07. Promjene:

    • Implementiran je mehanizam za praćenje/zamjenu referenci za vanbilansne dimenzije računovodstvenih registara.

    Obrada verzije 1.06. Promjene:

    • Brisanje stabla metapodataka nakon pretraživanja je onemogućeno - sada se stablo metapodataka uvijek prikazuje;
    • Dodan mehanizam zamjene linkova.
    • Dodan prikaz ukupnog broja objekata u bazi podataka;
    • Mehanizam za brisanje je prebačen u režim razmene podataka Učitavanje = Tačno;
    • Opcija "Izbriši unose u registru detalja" sada radi za vodeće i nepočetne dimenzije.

    Promijenjena pomoć za obradu:

    Obrada se sastoji iz dva dela: Stablo obrisanih objekata (3) I Stablo veza (4) objektu koji se briše.

    U stablu izbrisanih objekata vrše se osnovne postavke za traženje izbrisanih veza. Stablo veza analizira one povezane sa izbrisanim

    objekt drugi objekti baze podataka.Obrada se kontroliše pomoću meni osnovnih radnji (1), oznake na drvetu

    objekte za brisanje i Izbornik dodatnih funkcija (2)

    1. Izbornik osnovnih radnji

    -Jasno- inicijalizira stablo metapodataka objekata, briše prethodno dobijene rezultate;

    -Nađi- traži objekte informacione baze označene za brisanje koristeći označene objekte. Pretraga se vrši pomoću imenika,

    Dokumenti, kontni planovi, planovi tipova karakteristika, planovi kalkulacija, planovi razmene, zadaci, poslovni procesi;

    -Zamjena- zamjenjuje izbrisani link onom naznačenom u koloni "Zamjena". Prilikom zamjene referenci u detaljima dimenzije registramože doći do situacije

    Kada rezultirajući skup sadrži duple redove duž dimenzija, u takvim situacijama se duplirani redovi brišu. U ovom slučaju, prioritet se daje liniji s najmanjim brojem po redu.

    -Kontrola- prati referentnu prirodu pronađenih objekata baze podataka označenih za brisanje. Kontrola se vrši prema detaljima, merenjima,

    Resursi objekata metapodataka, detalji tabelarnih delova objekata metapodataka, vrste obračuna obračunskih registara, konta i analitika računovodstvenih registara,

    Vodeći zadaci poslovnih procesa,mjerenja sekvence dokumenata.

    -Izbriši- briše označene objekte koji se mogu brisati.

    2. Izbornik dodatnih funkcija

    -Izbor- podmeni sa operacijama za odabir stabla objekata (dalje).

    -Brisanje unosa u registar informacija- omogućiti/onemogućiti mod za brisanje povezanih zapisa nezavisnih registara informacija.

    -Prikažite listu izbrisanih- kada je ova opcija uključena, prilikom brisanja će se u sistemskim porukama prikazati lista izbrisanih objekata;

    -Monopol mod- omogućiti/onemogućiti isključivi način rada baze podataka;

    -Pronađite i uklonite- tri akcije za redom se izvode na odabranim objektima metapodataka: pronađi - kontrola - brisanje.

    3. Stablo objekata

    U svom početnom stanju, predstavlja kompletnu listu metapodataka objekata.Za te objekte je potrebno postaviti oznake

    među kojima će se tražiti oni koji su označeni za brisanje.

    Izvođenjem pretrage u koloni stabla " Ukupno"Broj pronađenih objekata označenih za brisanje će se odraziti u koloni" Total links" displej

    ukupan broj veza ovog tipa objekta.

    Izvođenjem kontrole u koloni stabla " Moguće brisanje" će prikazati broj objekata koji se mogu izbrisati.

    Linije stabala su obojene zelenom ili crvenom bojom u zavisnosti od mogućnosti brisanja pronađenih objekata. Linije koje sadrže informacije su označene plavom bojom

    Koristeći kontekstni meni, stablo se može sortirati po željenom redosledu.

    Funkcije grupnog podešavanja/poništavanja kvačica rade na odabranim drvoredima.

    Potvrdni okvir " Mark" se koristi i kada se traže objekti označeni za brisanje, i kada se prati referencijalnost i zamjena linkova.

    u koloni" Odabir"Za grupe objekata, možete odrediti prilagođeni upit za dodatno filtriranje objekata pronađenih za brisanje.Dvaput kliknite na kolonu "Izbor".

    otvara prilagođeni obrazac zahtjeva

    Prilagođeni zahtjev vam omogućava da primijenite dodatni filter prilikom odabira objekata označenih za brisanje.

    Konačni odabir iz zahtjeva mora sadržavati polje pod nazivom " Veza", ovo polje će biti polje filtera.

    U obrascu konstruktora zahtjeva (7) :

    -Jasno- briše trenutni zahtjev;

    -Default- generiše novi zahtjev na osnovu tipa podataka trenutnog objekta;

    -Dobijte parametre- ažuriranje liste parametara iz zahtjeva

    Filtrirajući upiti se mogu instalirati samo na nivou 2. grupisanja stabla obrisanih objekata, tj. na nivou odjeljka metapodataka.

    4. Stablo povezanih veza

    Kada aktivirate liniju u stablu objekata, stablo veza prikazuje hijerarhijsku strukturu pronađenih veza prema objektu koji se briše.

    Kada se u strukturi stabla detektuje kružna referenca objekata, trenutni objekat koji je uključen u kružnu referencu je

    će se više puta prikazivati ​​i završavati u cikličkom referentnom stablu.

    U redovima ovog stabla linkovi koji se ne mogu izbrisati ili nisu izbrisani prema trenutnim postavkama su označeni crvenom bojom;

    koji ne dozvoljavaju da se trenutni objekat na kraju izbriše.

    Dvostrukim klikom na redove ovog stabla moguće je vidjeti povezanu vezu.

    5. Kontekstni meni stabla objekata

    Kontekstni meni stabla objekata radi prema odabranim linijama stabla.

    Dostupne akcije:

    -Postavite/uklonite kvačice- postavlja/poništava odabrane linije stabla, uključujući i podređene linije;

    -Sortiranje uzlaznim/silaznim redoslijedom- upravljanje sortiranjem drvoreda;

    -Obriši izbor- (prečica na tastaturi Ctrl-X ) upiti filtera podataka se brišu u odabranim redovima stabla;

    1. Koji informativni sadržaj može biti pozicioniran na svim stranicama?

    Korisnici
    + Kurs studija
    + Informacijski blokovi
    + Oblici

    2. Kada koristite sistem sa više lokacija

    + zajednički korisnički budžeti se koriste za sve stranice
    - za svaku stranicu kreiraju se posebni korisnički budžeti

    Trebate dobru struju? Prvo morate naučiti kako ga kontrolirati, a PKE mjerni uređaj to može savršeno. Energetski tester PKE-A-S4 omogućava energetski pregled, mjerenje i registraciju količina električne energije, potrošnje električne energije, profila opterećenja i mjerenje opterećenja sekundarnih kola.

    3. Ako prilikom postavljanja stranice ne navedete naziv stranice u odjeljku „Parametri“, tada

    + sistem će koristiti ime stranice navedeno u postavkama glavnog modula
    - koristit će se vrijednost navedena u parametru "Ime" u odjeljku glavnih postavki
    - vrijednost neće biti definirana

    4. Broj lokacija u sistemu

    + utvrđeno licencnim ugovorom i licencom za dodatne lokacije
    - zavisi od broja jezika interfejsa u sistemu
    - neograničeno

    5. Konfiguriranje jezičkih postavki za javni dio stranice se vrši:

    U obrascu za uređivanje parametara korijenskog direktorija stranice
    - u obliku kreiranja/uređivanja jezika
    + zasebno za svaku stranicu u obliku kreiranja i uređivanja stranice

    6. Mogu li da konfigurišem više od dve lokacije u konfiguraciji sa više lokacija?

    + Moguće je ako kupite dodatne licence za dodatne stranice
    - Ne, to je zabranjeno ugovorom o licenci
    - Da, bez ograničenja

    7. Prilikom aktiviranja licence za 4 dodatne lokacije (pored dvije dostupne za korištenje prema zadanim postavkama), može se koristiti sljedeći broj kopija kernela sistema:

    3
    - 6
    + 1
    - 2

    8. Prilikom pregleda strukture fajla, podjela po lokacijama će se izvršiti u sljedećim slučajevima:

    Organizacija na više lokacija na jednoj domeni
    + logički prikaz strukture
    + organiziranje više stranica na različitim domenima

    9. Koriste se tehnologije za prijenos korisničkih kolačića između stranica

    + ako je u glavnim postavkama modula aktivirana opcija "Distribuiraj kolačiće na sve domene".
    - uvijek ako postoji statistički modul u sistemu
    - ako je aktivirana opcija "Proširi autorizaciju na sve domene".

    Podesite odgovarajuću opciju u postavkama sajtova
    + označite odgovarajuću opciju u postavkama glavnog modula
    - postavite odgovarajuću opciju u postavkama korisničke grupe

    11. Kako možete zatvoriti samo jedan sajt sa identifikatorom ru za posetioce?

    Korištenje dugmeta: Postavke -> Glavni modul -> Servisne procedure -> Zatvori pristup posjetiteljima
    + postavljanje posebnog programskog koda u datoteku: /bitrix/php_interface/ru/init.php

    12. U postavkama kojih modula možete odvojiti parametre za različite stranice?

    Nijedna ne dozvoljava
    - Modul Web Forms, Tok dokumenata, Modul za upravljanje strukturom
    - Internet prodavnica, Blog modul, Glavni modul
    - Svi dozvoljavaju
    + Modul za blog, Modul za upravljanje strukturom, Online prodavnica

    13. Da biste kreirali dodatne stranice u sistemu izvan onih dozvoljenih u licenci, morate:

    Kreirajte dodatni jezik interfejsa
    - kreirajte nalog u sistemu, kreirajte poseban poddirektorij
    + nabavite licencu za dodatni sajt, kreirajte nalog u sistemu, odredite putanju do fajlova javnog dela sajta

    14. Da li je moguće odvojiti prava za pregled statistike različitih sajtova u proizvodu:

    Da, ako napravite odgovarajuća podešavanja pristupa u modulu Statistika
    + Ne, korisnik koji ima pravo na pregled statistike će moći vidjeti statistiku za sve stranice

    15. Posebno za svaku lokaciju možete podesiti sljedeće postavke za modul upravljanja strukturom:

    + postaviti tipove svojstava
    - organizovati sistem pristupa sekcijama za svaku lokaciju
    - odaberite vizuelni HTML uređivač i njegove postavke pojedinačno za svaku stranicu
    + postavljanje tipova menija
    + definirati broj dodatnih opcija menija

    I šta kažu, ovi glasovi. Jedan i. Isto: Ja sam prodavac, ja sam prodavac. Šta ćeš uraditi. Šta možeš učiniti. da, Hydra luk u Rusiji 2016. A to znači da Bull Gates ne uspostavlja kontakt. Ne radi. Ili možda dolazi. Ali ti ne razumiješ. Možda je Minotaur onaj mrtvi pacov na plafonu. . Možda je tako.

    I nisu ti ništa objasnili. A to znači poseban postupak. Pa sam otišao u mrak. Jadne koze... Ma, nema veze, mi ćemo to shvatiti i kazniti krivce. Biće za njih upute za nigella sativa svijeće, trinaestu platu u valuti... Podigao je. Stavio sam na sto svesku sa profilom Dantea Aligijerija na koricama i neko vreme se koncentrisao na papir olovkom, i odmah sam pretpostavio da unutra crta iste profile Dantea, samo male. Iz nekog razloga ti ljudi misle da je tokom dugog dvadesetog veka upute za nigella sativa svijeće nisu proučavali njihove metode rada. Spuštam notes. Zakoračio je prema meni, kao da će svojim zakasnelim zagrljajem izliječiti sve moje emocionalne rane, ali onda je zazvonio telefon na njegovom stolu. Šmiga je opsovao i podigao slušalicu. Slušao je nekoliko sekundi, a onda mu je lice postalo tmurno i pažljivo. Da gospodine, . Rekao je i spustio slušalicu. Pogledavši u mene, podigao je ruke krivo. Vidi šta se dešava.

    Poslovna tajna. Mornari nemaju pitanja”, odgovorio je Maljuta. Stepa ga je čudno pogledao. Tačno tri sata kasnije nazvao je kapetan Lebedkin. Zašto ti treba moj život? Sačuvano? - upitao je prijeteći. - Pa da se baviš politikom. Ja... - počeo je Stjopa. "Ne pišaj", rekao je kapetan veselo. - Šalim se.

    Wish. Onda samo naprijed, . rekao je Čapajev ustajući s leđa ecstasy hotel. Nakon što smo napustili štabni vagon, otišli smo do zadnjeg dela voza. Ono što se dešavalo mi se činilo sve čudnijim. Nekoliko vagona pored kojih smo prošli bilo je mračno i činilo se da je tako. Prazan. Nigde nije bilo svetla; Iza vrata se nije čuo nijedan zvuk. Jedva sam mogao vjerovati da iza ploča od oraha, u čijoj se uglačanoj površini ogledala svjetlost Čapajevljeve cigare. Crveni vojnik spava, ali ja sam se trudio da ne razmišljam o tome.

    Do 2003. japanski specijalisti. Bilo je moguće razviti set od nekoliko mikrosondi koje vape hydra direktno u mozak i omogućio, u određenoj mjeri, objektivizaciju slike ljudske percepcije. Japanska oprema nije mogla utvrditi šta tačno osoba koja je posmatrana oseća i misli. Ali to je omogućilo da se dobije slika u boji (iako mutna) onoga što on vape hydra. I ne samo u stvarnosti, već iu brzoj fazi sna. To je postalo moguće jer signal nije uzet iz optičkog živca, već iz tih zona. Mozak koji je odgovoran za direktno predstavljanje. Opremu je odmah kupio tim Potašinskog. Signal iz seta sondi implantiranih u mozak mogao bi se prenijeti bežično. Veze koje su omogućile bablonautu da vodi normalan život, ni na koji način nije ograničen učešćem u eksperimentu. Bilo je potrebno samo da se prijemnik signala nalazi negdje u blizini. Koja je zatim prenosila informacije na kompjuter u realnom vremenu. Ukratko, shema eksperimenata Potashinskog izgledala je ovako: Prvo je u mozak bablonauta-eksperimentatora implantiran set kontrolnih elektroda (dobrovoljci su, kao i obično, odabrani među mladim oficirima FSB-a za ovu ulogu).

    Sa mrtve tačke. Slušaj, brate", rekao je, "kakva je ovo priroda?" O cemu pricas? - upitala je Isa. Pa, rekli ste u autu da tijelo od šrapnela ima istu prirodu kao i dugino. A kakva je ovo priroda? Bolje ne pitaj o ovome. Brate,” Isa se namršti. Zašto. Još niste spremni za ovo. Kako nije spreman. A amfetamin marihuana u isto vrijeme. Da sam spreman, ne bih pitao. Tako da možete odgovoriti. Or.

    Uskoro. pitan. Kupujte hašiš u Vladivostoku sad, rekao sam, evo... Neko drugi je izbirljiv. Ljubavnik bi se mogao uvrijediti što mu nije dozvoljeno dalje od mrežnog hodnika. Ali Porfirije nije takav. Prvo što sam uradio je da sam spojio njene naočare. Dobro, rekla je. Kakvi zalisci... U međuvremenu, stavljam sliku naočara na tablu. Morfing to sa pogledom sa plafonske kamere. Ifak ​​je podigao bilo koje preobrazbe bez naprezanja svoje moći. Bilo je monstruozno. Sada me je Mara videla u svojim naočarima na mestu aifaka i istovremeno je mogla da posmatra.

    Razvijena šifra. Ponekad je primetio da ga ponovo muče snovi koji se ponavljaju prema šemi 1. Ili prema šemi 2. I odjednom, u otvorenom tekstu, kao uzvik koji beži: Sanjao pušačke mješavine 24 sata, ubio sam u detinjstvu... Glas iza paravana. Ućutao je. Šta to ona radi? - upitao je Sam. „Zaspala sam“, odgovorila je Nataša. Sam je nježno pogladio bodljikav vrh njenog trbuha i zavalio se na sofu. Natasha je tiho progutala slinu. Sam je povukao kutiju na podu prema sebi, otvorio je i izvadio malu staklenu kutiju. Teglu, pljunuo je crveno u nju, zeznuo je i bacio nazad - cijela ova operacija ga je odvela pušačke mješavine 24 sata sekundi „Znaš, Nataša“, rekao je.

    Nakon toga on hašiš svetac Hej, Tatarsky. Nema odgovora. Tatarsky je čekao još minut i shvatio da je ostao sam. Sam sa svojim umom spremnim da podivlja. Hitno sam morao da se nečim zaokupim. Pozovi, šapnuo je. - Kome. Gireev. On zna šta da radi. Za dugo vremena. Niko se nije javljao na telefon. Konačno, na petnaestom ili dvadesetom zvonu, Gireev je sumorno odgovorio: Zdravo. Andryusha.

    Ne, rekao je. U zaključanoj sobi sjedi čovjek koji ne zna kineski. Kroz prozor mu daju bilješke s pitanjima na kineskom. Za njega su to samo komadi papira na kojima su iscrtane šljokice čije značenje ne razumije. Ali njegova soba je puna raznih knjiga. Pravila koja detaljno opisuju kako i kojim redoslijedom treba odgovoriti samo kičmama. I on, postupajući po ovim pravilima, daje odgovore na kineskom u drugom prozoru. Oni stvaraju potpuno povjerenje kod svakog ko stoji vani da zna kineski. Iako on sam uopšte ne razume šta ga pitaju. Adresa hydra onion browserŠta je smisao njegovih odgovora? Uvedeno. Pa, ja sam to predstavio. Sura je ista kineska soba, samo automatizirana. Umjesto osobe sa priručnikom, tu je skener koji čita hijeroglife. Ogromna baza podataka referenci i pravila koja vam omogućavaju da odaberete hijeroglife za odgovor.

    Ironično, to je ono što mi je donelo jasnoću. Barem u praktičnom smislu. Shvatio sam problem sa kojim se suočavam. Nije samo složeno, već je i neuhvatljivo. Bilo je teško čak i pravilno formulisati pitanja vezana za to. Činilo se da je jedina utjeha Kako pronaći Hydra stranicu na jeziku Torus, stvari su jednako klizave. Sa ljudskom svešću. Nisam se mogao nositi sa ovim. I odlučio sam da je najbolji izlaz iz situacije povratak. Na uobičajeni posao, ostavljajući egzistencijalne vježbe za kasnije ili zaboravljajući na njih.

    Ubrzo je put doveo do bogatog sela sa svježe okrečenom bijelom crkvom. Tužan jednonogi vojnik u izblijedjeloj sivoj uniformi sjedio je kraj crkvene ograde. Ne znate gdje je Optina Pustyn. upitao je T., savijajući se prema njemu sa konja. Ovo je ono o čemu momci pričaju. upitao je vojnik. Koja je nedavno osnovana kao ustanova. Odlučio sam da je serviser poludio. Kako je ovo mjesto nedavno postavljeno. Što znači da je u svakom slučaju sve u redu, časni sude, rekao je vojnik i Hydra rulet ruku, i dalje ćeš biti daleko. Ovdje postoje samo dva puta, i oba idu u jednom smjeru. Idite prvom ili drugom rutom. Ako želite kraći put, onda kroz šumu. Tu je račva, tako da možete uzeti bilo koju stranu.

    I druge grimase, o kojima ste, mislim da ste dosta čuli... Lena nije shvatila kakva je tata-mama budala osamnaest godina (mladić je brzo i tiho promrmljao ove riječi), ali je odmah zaboravila na to - ona odjednom je poželela da otpije gutljaj vina u tolikoj meri od dvadeset hiljada evra da su joj zasuzile usta. Dvoranom je prošao tihi uzdah koji je potvrdio da okupljeni nisu samo čuli za grimase. I uspjeli smo detaljno proučiti sve dostupne informacije o njima. "Nedavno su zapadne obavještajne agencije pokrenule pravi lov na naše bogate idiote", nastavio je mladić. - Čuli ste, naravno, za velike skandale adresa hydra onion tk okey site hydra in torus hapšenja: prvo Courchevel, zatim Fidži, pa butik Hermes, a sada Saint Moritz, Maldivi i Antarktik. Kampanja je pažljivo planirana i ima dva glavna cilja - prvo, diskreditaciju. Ruska civilizacija - uspostaviti kontrolu nad svojim resursima prikupljanjem kompromitujućih dokaza o vlasnicima svojih glavnih dobara. Naša elita je postala meta, a objektivna realnost trenutne tačke u prostor-vremenu je takva. S njom smo postali mete. Mršteći se, ućutao je, kao da daje priliku svojim slušaocima da shvate ozbiljnost situacije. Tada mu se tužan osmijeh vratio na lice i nastavio: Moramo držati situaciju pod kontrolom.

    Ona se naceri. Barem se ne morate pretvarati da ste uvrijeđeni nevinošću pred svojim narodom. O čemu. Kad sam ga isprovocirao. Kada je iskočila gola Hydra luk ulaz i stao ispred njega pseći stil. Vi ovo smatrate provokacijom. Svakako. Zašto si mu, pitam se, okrenuo leđa? Slegnuo sam ramenima. Za pouzdanost. Šta je u ovome posebno pouzdano? Rep je bliže meti”, rekao sam ne baš samouvereno. Pa. I morate pogledati preko ramena.

    Treće montal vanilla ecstasy kako sledi: Njegovoj ekselenciji O. Konstantinu Petroviču Pobedonoscevu, službeniku. Ovim prenosim Vašoj Ekselenciji prijevod drevnog egipatskog natpisa. List zlatnih listića pronađen u medaljonu montal vanilla ecstasy leš oca Varsonofija Netrebka u okviru istrage o slučaju grofa T. Prema mišljenju stručnjaka iz Egipatskog muzeja, obris hijeroglifa nam omogućava da datiramo tekst u doba 18. dinastije ili nešto kasnije. Natpis glasi: Tajno ime hermafrodita sa mačjom glavom, koja daje moć nad njim, je suština. ANGC. Ako možete kontrolirati hermafrodita s ovim imenom. U redu. Prevodioci koji ANGC također mogu biti prevedeni kao tradicionalni BHGV (ili na neki drugi način, ovisno o izboru tablica korespondencije kada se koriste hijeroglifski registri). Međutim, sam medaljon se ne može prenijeti Vašoj Ekselenciji uprkos Vašem zahtjevu.

    Post navigation

  • Najbolji članci na ovu temu