php-ში სახელთა სივრცის გამოყენების მაგალითები. სახელთა სივრცეები PHP-ში, განმარტა. სახელთა სივრცეები: აღწერის მრავალი სფერო

მე ცოტა ხნის წინ ჩავყარე ჩემი პროექტი სახელთა სივრცეში და წავაწყდი სათანადო დოკუმენტაციის არარსებობის პრობლემას. ყველაფერი, რისი პოვნაც მოვახერხეთ, თარიღდება დაახლოებით 2009 წლით, და ეს თითქმის 2012 წლითაა... ნაპოვნი მასალაში არის უამრავი არასამუშაო ადგილი, რომელიც იყენებს იმას, რაც არ არის php-ის მიმდინარე ვერსიაში. ამასთან დაკავშირებით, მსურს ამ საკითხს გარკვეული სინათლე მოჰფინოს.
მაშ, რა არის სახელთა სივრცე ან სახელთა სივრცე? დიდი ვიკიპედია მათ ასე განსაზღვრავს:

სახელთა სივრცე არის ნაკრები, რაც ნიშნავს მოდელს, აბსტრაქტულ საცავს ან გარემოს, რომელიც შექმნილ იქნა უნიკალური იდენტიფიკატორების (ანუ სახელების) ლოგიკური დაჯგუფებისთვის. სახელთა სივრცეში განსაზღვრული იდენტიფიკატორი ასოცირდება ამ სახელთა სივრცესთან. ერთი და იგივე იდენტიფიკატორი შეიძლება დამოუკიდებლად განისაზღვროს მრავალ სივრცეში. ამრიგად, ერთ სახელთა სივრცეში განსაზღვრულ იდენტიფიკატორთან ასოცირებულ მნიშვნელობას შეიძლება (ან შეიძლება არ ჰქონდეს) იგივე (ან უფრო სწორად განსხვავებული) მნიშვნელობა, რაც იგივე იდენტიფიკატორს, რომელიც განსაზღვრულია სხვა სახელთა სივრცეში. სახელთა სივრცის მცოდნე ენები განსაზღვრავენ წესებს, რომლებიც მიუთითებენ რომელ სახელთა სივრცეს ეკუთვნის იდენტიფიკატორი (ანუ მისი განმარტება).wiki

Ყველაფერი გასაგებია? სინამდვილეში მარტივია. 5.3 ვერსიამდე php-ში მხოლოდ ორი სივრცე იყო - გლობალური (რომელშიც თქვენი მთავარი კოდი იყო შესრულებული) და ლოკალური (რომელშიც იყო განსაზღვრული ფუნქციის ცვლადები).

5.3 ვერსიის შემდეგ ყველაფერი შეიცვალა. ახლა თქვენ შეგიძლიათ განსაზღვროთ თქვენი სახელების სივრცე, რომელშიც იარსებებს თქვენი კლასები, მეთოდები და ა.შ.


იმედია ცოტა უფრო ნათელი გახდა.

მე კონკრეტულად იგივე დავასახელე კლასები. ვინაიდან ისინი განსაზღვრულია სხვადასხვა სივრცეში, ისინი ორი განსხვავებული კლასია, მიუხედავად ერთი და იგივე სახელებისა. მთავარი სკრიპტი კვლავ ფუნქციონირებს გლობალურ სივრცეში, აქ არაფერი შეცვლილა და მასში კლასები და ფუნქციები ჯერ კიდევ შეიძლება განისაზღვროს. მაშინ რისთვის არის სივრცეები? უპირველეს ყოვლისა, დარწმუნდით, რომ როდესაც თქვენ აერთიანებთ ფაილს რაიმე ჩარჩოს ან ბიბლიოთეკაში, თქვენი კლასები არ გადალახავს ჩარჩოს კლასებს ან პირიქით.

იმისათვის, რომ გამოიყენოთ თქვენს სახელთა სივრცეში განსაზღვრული კლასები, თქვენ უნდა შემოიტანოთ თქვენს მიერ განსაზღვრული სივრცე გლობალურ სივრცეში სწორ ადგილას (ჩვეულებრივ მირჩევნია ამის გაკეთება ფაილის დასაწყისში). ამისათვის გამოიყენეთ საკვანძო სიტყვა use.

ყურადღება:რატომღაც php არ იძლევა საკვანძო სიტყვის გამოყენებას გამოყენებამდგომარეობაში ბლოკები და მარყუჟები

ავიღოთ მაგალითი სურათებიდან და განვახორციელოთ კოდით:

ყურადღება:სახელთა სივრცის საკვანძო სიტყვა უნდა განთავსდეს ფაილის დასაწყისშივე, ამის შემდეგ
ფაილი A.php
B.php ფაილი
შესაძლებელია ალტერნატიული სინტაქსი:
რეკომენდებულია თითოეული სახელების სივრცის ცალკე ფაილში გამოცხადება. მიუხედავად იმისა, რომ ეს შესაძლებელია ერთში, მკაცრად არ არის რეკომენდებული!
ახლა გადავიდეთ მესამე ფაილზე, რომელშიც ჩვენი მთავარი სკრიპტი იმუშავებს
index.php
როგორც ჩანს, ეს უპირატესობაა, მხოლოდ მეტი კოდია დამატებული, მაგრამ ეს მთლად ასე არ არის, ცოტა შემდგომ მე მივცემ ავტოჩატვირთვის კლასის მაგალითს, რომლითაც კლასებთან ფაილების დამაკავშირებელი ხაზები ზედმეტი იქნება.
ახლა მოდით გადავხედოთ ჩვენს კლასებს.

ყურადღება:მასშტაბის გარჩევადობის ოპერატორის (::) გამოყენებით php სახელთა სივრცეებში არაა ნებადართული! ერთადერთი, რისთვისაც ის შესაფერისია, არის სტატიკური კლასის მეთოდებსა და მუდმივებზე წვდომა. თავიდან მათ სურდათ მისი გამოყენება სახელთა სივრცისთვის, მაგრამ შემდეგ მათ წინააღმდეგობა გადაწყვიტეს წარმოქმნილი პრობლემების გამო. მაშასადამე, A::A::say(); არასწორია და გამოიწვევს შეცდომას.

სახელთა სივრცისთვის, თქვენ უნდა გამოიყენოთ უკუღმა დახაზვის სიმბოლო "\"
ყურადღება:გაუგებრობების თავიდან ასაცილებლად, აუცილებელია ამ სიმბოლოს გაქცევა სტრიქონებში გამოყენებისას: "\\"

სახელთა სივრცეები შეიძლება იყოს ჩასმული ერთმანეთში, მოდით დავამატოთ ჩვენს A.php ფაილს:
და ინდექსში ჩავწერთ შემდეგს:

მნიშვნელოვანი პუნქტია იმპორტირებული ფართებისთვის მეტსახელების გამოყენება. შეგიძლიათ დაწეროთ A\subA::say(); დამეთანხმებით, რომ ძნელია ყოველ ჯერზე სრული ბილიკის დაწერა სივრცეებისკენ, ამის თავიდან ასაცილებლად შემოიღეს მეტსახელები. კომპილაციისას მოხდება შემდეგი: მეტსახელის sub-ის ნაცვლად შეიცვლება A\subA, ამიტომ მივიღებთ გამოძახებას A\subA::say();

რა ხდება მაშინ გლობალურ სივრცეში განსაზღვრული ფუნქციების გამოძახებისას? PHP ჯერ ეძებს ფუნქციას იმ სივრცეში, სადაც ამჟამად მუშაობთ, და თუ ვერ პოულობს, გადადის გლობალურ მასშტაბზე. იმისთვის, რომ დაუყოვნებლივ მიუთითოთ, რომ იყენებთ გლობალურ ფუნქციას, წინ უნდა უძღოდეთ უკანა ხაზით.

იმისათვის, რომ თავიდან ავიცილოთ პრობლემები სივრცეებიდან კლასების ავტომატური ჩატვირთვასთან დაკავშირებით, ფაილური სისტემა უნდა იყოს ორგანიზებული სივრცეების ორგანიზების მსგავსად. მაგალითად, ჩვენ გვაქვს root საქაღალდის კლასები, სადაც შეინახება ჩვენი კლასები, შემდეგ ჩვენი სივრცეები შეიძლება დალაგდეს შემდეგნაირად.
კლასები\A\A.php
classes\A\sub\A.php (ქვესივრცე განთავსდება ცალკე ფაილში)
კლასები\B\B.php

PHP-ს აქვს ჯადოსნური მუდმივი __NAMESPACE__, რომელიც შეიცავს მიმდინარე სივრცის სახელს.

ახლა კი ავტომატური ჩატვირთვის შესახებ.

ქვემოთ მოყვანილი კლასი ჩემი არ არის, უბრალოდ გავამუშავე და ცოტა გავაუმჯობესე, აქედან აღებული.
ყურადღება:იმისათვის, რომ თქვენი კლასები ჩაიტვირთოს, კლასის სახელი უნდა შეესაბამებოდეს ფაილის სახელს!

" .$ფაილი." in " .$filepath)); if (file_exists($filepath)) (if(Autoloader::debug) Autoloader::StPutFile(("დაკავშირებული" .$filepath)); $flag = FALSE; require_once($filepath); break; ) Autoloader::recursive_autoload($file, $path2, &$flag); ) ) closeir($handle); ) ) პირადი სტატიკური ფუნქცია StPutFile($data) ($dir = $_SERVER["DOCUMENT_ROOT"] ." /Log/Log.html"; $file = fopen($dir, "a"); flock($file, LOCK_EX); fwrite($file, ("║" .$data ."=>" .date(" d.m.Y H:i:s") ."

" .PHP_EOL)); flock ($file, LOCK_UN); fclose ($file); ) ) \spl_autoload_register("yourNameSpace\Autoloader::autoload"); )
თუ გადახედავთ იმ კლასების სახელებს, რომლებიც შემოდის ჩატვირთვისთვის, ნახავთ, რომ თითოეულ კლასს წინ უძღვის პრეფიქსი სახელთა სივრციდან, რომელიც მითითებულია გამოყენებაში. ამიტომ გირჩევთ გამოიყენოთ ფაილების ადგილმდებარეობა სახელთა სივრცის მსგავსი დირექტორიაში; ეს აჩქარებს ძიებას ერთ ან ორ გამეორებამდე.

ახლა ჩვენი ინდექსი შეიძლება დაიწეროს ასე:
ახლა ყველა კლასი და ინტერფეისი, რომელსაც გამოიყენებთ, ავტომატურად იტვირთება.

ენის ზოგიერთი დინამიური შესაძლებლობების საჩვენებლად სივრცეებით, მოდით გამოვაცხადოთ სხვა კლასი:
test.php

ინდექსი.php
sayName ("ტესტი"); //ან შეგიძლიათ გააკეთოთ ეს ტესტი\sayName("test2"); //ან ასე $obj::sayName("ტესტი"); //ან შეგიძლიათ გააკეთოთ ეს ტესტი::sayName("test2");

იმედი მაქვს, რომ ჩემი სტატია ვინმესთვის სასარგებლო იქნება.

PHP-მა, დაწყებული 5.3 ვერსიით, მოგვცა სახელთა სივრცეები. მას შემდეგ, იყო დუნე და მწვავე დისკუსია იმის შესახებ, თუ როგორ გამოვიყენოთ ეს სახელთა სივრცე?
ზოგიერთმა ჩარჩომ, როგორიცაა Symphony, Laravel და, რა თქმა უნდა, Zend, მიიღო ეს ტექნოლოგია.
ეს ყველაფერი მეტ-ნაკლებად ჯდება MVC სქემაში. რჩება ერთი, ალბათ მარადიული დებატები: როგორი უნდა იყოს განაცხადის მთავარი საქორწინო წყვილი - მოდელი და კონტროლერი?
ზოგი გვეუბნება, რომ მოდელი უნდა იყოს მსუქანი და მსუქანი და მასთან ერთად სუსტი და გამხდარი კონტროლერი. ერთი სიტყვით - მატრიარქატი.
სხვები, პირიქით, თვლიან, რომ კონტროლიორმა უნდა მართოს და მართოს ყველაფერი, ასე რომ, ის აღმოჩნდება მყარი და კარგად გამოკვებადი. და მასთან ერთად არის გამხდარი, გამხდარი მოდელი, რომლის ამოცანაც მიცემა და მოტანა სრულდება. ეს არის პატრიარქატი.
ასე რომ, რომელია უკეთესი MVC სქემაში? პატრიარქატი თუ მატრიარქატი?
ამას შევხედოთ დემოკრატიაზე დაფუძნებული ოჯახის ერთეულის აგების კუთხით. და მოდით, Namespace დაგვეხმაროს ამაში.

ჩვენ არ მოგვწონს სქელი, უხერხული კონტროლერები, რომლებსაც, როგორც ხარი ჩინურ მაღაზიაში, შეუძლიათ გაანადგურონ მთელი აპლიკაცია, თუ უყურადღებოდ იქნებით.
არც მსუქანი მოდელები მოგვწონს. აბა, ვის მოსწონს ისინი? ისინი უნდა იყვნენ პოდიუმის ღირსნი!
შევეცადოთ, Namespace-ის დახმარებით, როგორც კარგ მაჭანკალს, შევქმნათ ჰარმონიული ოჯახი.

პირველი, მოდით შევქმნათ განაცხადის ჩონჩხი. რაც არ უნდა ბანალური იყოს, ბლოგი იყოს.

ჩვენ შევქმენით ძირითადი სტრუქტურა, სადაც:

  • ბლოგი არის ჩვენი აპლიკაციის საცავი;
  • ხედები და შაბლონები - ნახვების და შაბლონების შენახვა;
  • კომუნალური - საერთო ბიბლიოთეკების საცავი;
  • index.php - bootstrap სკრიპტი;
  • პოსტი - სწორედ აქ უნდა მოხდეს კონტროლერისა და მოდელის ოჯახური იდილია.

index.php-ით ყველაფერი მარტივია:

run(); /* * ინდექსის დასასრული.php */

ჩვენ განვსაზღვრავთ საჭირო ბილიკებს და ვქმნით ავტოჩამტვირთველს.
ავტოჩამტვირთველი ატვირთავს საჭირო კლასებს, რომლებიც განლაგებულია საქაღალდეში იერარქიაში კლასის სახელთა სივრცის მიხედვით. მაგალითად, BlogPostServicesView კლასი მოიძებნება Blog/Post/Services-ში.
და აი, პირველი შეხვედრა სახელთა სივრცესთან.
როდესაც ვიწყებთ index.php, ვქმნით Blog აპლიკაციის ინსტანციას, რომლის კლასი იტვირთება Blog/Blog.php-დან.
მოდით შევხედოთ მას.

პოსტი = ახალი პოსტი(); ) საჯარო ფუნქცია run() ( $this->post->view->all(); ) )//end class ბლოგი

Blog კლასის შექმნისას მასში ჩავრთავთ Post კლასს Namespace BlogPost-ით და ავტოჩამტვირთველი იტვირთება მას Blog/Post/Post.php-დან.
ალბათ ამ კლასს შეიძლება ეწოდოს Controller,

ხედი = new View(); ) )//კლასის დასასრული პოსტი

ფოსტის ერთეული მოიცავს:
- თავად მონაცემთა ჩანაწერის სტრუქტურა - BlogPostEntitiesPostEntity.php

სერვისები, რომლებიც ემსახურებიან კონტროლერის მოთხოვნებს - BlogPostServicesView.php (მაგალითად, ერთ-ერთი სერვისი)

db = new DB(); )//ბოლო __აშენება საჯარო ფუნქცია all() ( $posts = $this->db->survey(); Contemplate::compose(array("header" => "header", "main" => "main", "footer" => "footer",), array ("posts" => $posts, "title" => "Viper საიტი",)); ) )//კლასის დასასრული PostView

მონაცემთა ბაზის ურთიერთქმედების სისტემა - BlogPostRepositoriesDB.php - აი, ეს არის ჩვენი თხელი, ელეგანტური მოდელი,
უბრალოდ მიეცი, მოიტანე და მეტი არაფერი!

dbh = new PDO ("mysql:host=localhost;dbname=test", $user, $pass, მასივი (PDO::ATTR_PERSISTENT => true)); ) catch (PDOException $e) (echo "Error!:" . $e->getMessage() ."
"; die(); ) )//end __construct public function research() ( $query_view = $this->dbh->prepare("SELECT * პოსტებიდან"); $query_view->execute(); დაბრუნება $query_view- >fetchAll(PDO::FETCH_CLASS, "BlogPostEntitiesPostEntity"); )//გამოკითხვის დასრულება )//კლასის დასასრული Db

შედეგად, ჩვენ შევძელით შეგვექმნა აპლიკაციის სტრუქტურა, სადაც ყველა კომპონენტი კარგად არის დაკავშირებული, ხოლო ჩვენ მივაღწიეთ კლასების მკაფიო გამიჯვნას, სადაც თითოეული კლასი ასრულებს თავის დავალებას. ჩვენი კონტროლერი არის თხელი და ამავე დროს ძლიერი. მოდელი მას ემთხვევა. იდეალური ოჯახი!
და ეს ყველაფერი სახელების სივრცის წყალობით.

მე არ ვკამათობ, ხშირ შემთხვევაში ჩარჩო მოსახერხებელია. მაგრამ ნახეთ, სახელთა სივრცე არაფერს გახსენებს?
მკაფიო დაყოფა კლასებად, დირექტორიებისა და კლასების მკაცრი და ამავე დროს მოქნილი იერარქია, რომელიც მთლიანად ექვემდებარება დეველოპერს.
ზოგჯერ არ არსებობს ასეთი მნიშვნელოვანი დანამატი ასობით ფაილის და კლასების სახით ჩარჩოს სახით.
კლასებისა და კომპონენტების ურთიერთქმედების წესების პროკრუსტეს კალაპოტის არარსებობა.

სტატია ამ თემაზე შთაგონებული იყო ტეილორ ოტველის, Laravel-ის ჩარჩოს ავტორის აზრებით, რისთვისაც დიდი მადლობა მას.
GitHub-ზე მაგალითის წყაროს კოდის მისამართი.

გამარჯობა. დღევანდელ სტატიაში განვიხილავთ, რა არის სახელთა სივრცეები PHP-ში.

თუ დიდი ხანია იყენებთ OOP, მაშინ თქვენ ალბათ შეგხვედრიათ სიტუაცია, როდესაც მესამე მხარის ბიბლიოთეკის დაკავშირებისას თქვენ განიცადეთ წარუმატებლობა იმის გამო, რომ თქვენ უკვე იყენებთ იმავე კლასის სახელებს თქვენს კოდში, როგორც ბიბლიოთეკაში. ეს განსაკუთრებით შეიძლება მოხდეს, თუ იყენებთ ჩვეულებრივ სახელებს, როგორიცაა "მოდელი", "db"და ასე შემდეგ. მე გეტყვით ახლა როგორ გამოვასწოროთ ეს.

სახელთა სივრცე- ეს არის ერთგვარი საცავი, რომელიც შექმნილია უნიკალური იდენტიფიკატორების (სახელების) აბსტრაქტული დაჯგუფებისთვის.

იმათ. თუ იყენებთ სახელთა სივრცეები, მაშინ შეგიძლიათ უსაფრთხოდ დააკავშიროთ მესამე მხარის ბიბლიოთეკები და არ შეგეშინდეთ, რომ მათ ექნებათ იგივე სახელები, როგორც თქვენს კოდში. დავასრულოთ თეორია და გადავიდეთ პრაქტიკაზე.

მოდით შევქმნათ ფაილი myclass.phpამ შინაარსით

სახელთა სივრცე my\oneProject;
კლასი MyClass ( )
?>

აქ ჩვენ შევქმენით კლასი სახელთა სივრცეში ჩემი\ერთიპროექტი. სხვათა შორის, თქვენ უნდა დაწეროთ ზუსტად უკანა ხაზი. არ დაიბნეთ!

ახლა ფაილში index.phpდავწეროთ შემდეგი

require_once ("myclass.php");
$mc = new MyClass(); // შეცდომა: კლასი ვერ მოიძებნა
$mc = ახალი my\oneProject\MyClass(); // ყველაფერი მუშაობს
?>

როგორც ხედავთ, ახლა შეუძლებელია ასეთი კლასის შექმნა, თქვენ უნდა მიუთითოთ რომელში სახელთა სივრცეის წევს.

შეგვიძლია ერთდროულად რამდენიმე დავაზუსტოთ სახელთა სივრცეებიერთ ფაილში

სახელთა სივრცის პროექტი;

Const CONNECT_OK = 1;
კლასის კავშირი ()
ფუნქცია დაკავშირება () ()

NamespaceAnotherProject;

Const CONNECT_OK = 1;
კლასის კავშირი ()
ფუნქცია დაკავშირება () ()
?>

მიუხედავად იმისა, რომ ჩვენ გვაქვს კლასების, ფუნქციების და მუდმივების აბსოლუტურად იდენტური სახელები, სახელების კონფლიქტი არ გვექნება, რადგან ისინი სხვადასხვა სივრცეში წევენ.

ჩვენ ასევე შეგვიძლია გამოვიყენოთ ბრეკეტის სინტაქსი.

სახელთა სივრცის პროექტი (

Const CONNECT_OK = 1;
კლასის კავშირი ()
ფუნქცია დაკავშირება () ()
}

სახელთა სივრცე AnotherProject (

Const CONNECT_OK = 1;
კლასის კავშირი ()
ფუნქცია დაკავშირება () ()
}
?>

თუ კოდს აერთიანებთ გლობალური სახელების სივრცეკოდით სხვა სივრცეებში, მაშინ გამოიყენება მხოლოდ სინტაქსი ფრჩხილებით.

სახელთა სივრცის პროექტი (

Const CONNECT_OK = 1;
კლასის კავშირი ()
ფუნქცია დაკავშირება () ()
}

სახელთა სივრცე (// გლობალური კოდი
session_start();
$a = პროექტი\დაკავშირება();
echo Project\Connection::start();
}
?>

ასევე, არ დაგავიწყდეთ, რომ სახელთა სივრცის განსაზღვრა ყოველთვის უნდა იყოს კოდის პირველი ხაზი. თუ ასე დაწერ, შეცდომა იქნება

იმის გასარკვევად, რომელ სახელთა სივრცეში იმყოფებით ამჟამად, შეგიძლიათ გამოიყენოთ მუდმივი __NAMESPACE__

სახელთა სივრცის პროექტი;
ექო """, __NAMESPACE__, """; // დაბეჭდავს "პროექტს"
?>

ამ მუდმივის გამოყენებით შეგიძლიათ, მაგალითად, სახელების დინამიურად აგება

სახელთა სივრცის პროექტი;

ფუნქცია incl($classname) (
$a = __NAMESPACE__ . "\\". $classname;
დააბრუნეთ ახალი $a;
}
?>

ასე რომ დღეისთვის სულ ესაა. კურსის გავლისას შეგიძლიათ მიიღოთ მეტი ინფორმაცია და პრაქტიკული ცოდნა

მე ცოტა ხნის წინ ჩავყარე ჩემი პროექტი სახელთა სივრცეში და წავაწყდი სათანადო დოკუმენტაციის არარსებობის პრობლემას. ყველაფერი, რისი პოვნაც მოვახერხეთ, თარიღდება დაახლოებით 2009 წლით, და ეს თითქმის 2012 წლითაა... ნაპოვნი მასალაში არის უამრავი არასამუშაო ადგილი, რომელიც იყენებს იმას, რაც არ არის php-ის მიმდინარე ვერსიაში. ამასთან დაკავშირებით, მსურს ამ საკითხს გარკვეული სინათლე მოჰფინოს.
მაშ, რა არის სახელთა სივრცე ან სახელთა სივრცე? დიდი ვიკიპედია მათ ასე განსაზღვრავს:

სახელთა სივრცე არის ნაკრები, რაც ნიშნავს მოდელს, აბსტრაქტულ საცავს ან გარემოს, რომელიც შექმნილ იქნა უნიკალური იდენტიფიკატორების (ანუ სახელების) ლოგიკური დაჯგუფებისთვის. სახელთა სივრცეში განსაზღვრული იდენტიფიკატორი ასოცირდება ამ სახელთა სივრცესთან. ერთი და იგივე იდენტიფიკატორი შეიძლება დამოუკიდებლად განისაზღვროს მრავალ სივრცეში. ამრიგად, ერთ სახელთა სივრცეში განსაზღვრულ იდენტიფიკატორთან ასოცირებულ მნიშვნელობას შეიძლება (ან შეიძლება არ ჰქონდეს) იგივე (ან უფრო სწორად განსხვავებული) მნიშვნელობა, რაც იგივე იდენტიფიკატორს, რომელიც განსაზღვრულია სხვა სახელთა სივრცეში. სახელთა სივრცის მცოდნე ენები განსაზღვრავენ წესებს, რომლებიც მიუთითებენ რომელ სახელთა სივრცეს ეკუთვნის იდენტიფიკატორი (ანუ მისი განმარტება).wiki

Ყველაფერი გასაგებია? სინამდვილეში მარტივია. 5.3 ვერსიამდე php-ში მხოლოდ ორი სივრცე იყო - გლობალური (რომელშიც თქვენი მთავარი კოდი იყო შესრულებული) და ლოკალური (რომელშიც იყო განსაზღვრული ფუნქციის ცვლადები).

5.3 ვერსიის შემდეგ ყველაფერი შეიცვალა. ახლა თქვენ შეგიძლიათ განსაზღვროთ თქვენი სახელების სივრცე, რომელშიც იარსებებს თქვენი კლასები, მეთოდები და ა.შ.


იმედია ცოტა უფრო ნათელი გახდა.

მე კონკრეტულად იგივე დავასახელე კლასები. ვინაიდან ისინი განსაზღვრულია სხვადასხვა სივრცეში, ისინი ორი განსხვავებული კლასია, მიუხედავად ერთი და იგივე სახელებისა. მთავარი სკრიპტი კვლავ ფუნქციონირებს გლობალურ სივრცეში, აქ არაფერი შეცვლილა და მასში კლასები და ფუნქციები ჯერ კიდევ შეიძლება განისაზღვროს. მაშინ რისთვის არის სივრცეები? უპირველეს ყოვლისა, დარწმუნდით, რომ როდესაც თქვენ აერთიანებთ ფაილს რაიმე ჩარჩოს ან ბიბლიოთეკაში, თქვენი კლასები არ გადალახავს ჩარჩოს კლასებს ან პირიქით.

იმისათვის, რომ გამოიყენოთ თქვენს სახელთა სივრცეში განსაზღვრული კლასები, თქვენ უნდა შემოიტანოთ თქვენს მიერ განსაზღვრული სივრცე გლობალურ სივრცეში სწორ ადგილას (ჩვეულებრივ მირჩევნია ამის გაკეთება ფაილის დასაწყისში). ამისათვის გამოიყენეთ საკვანძო სიტყვა use.

ყურადღება:რატომღაც php არ იძლევა საკვანძო სიტყვის გამოყენებას გამოყენებამდგომარეობაში ბლოკები და მარყუჟები

ავიღოთ მაგალითი სურათებიდან და განვახორციელოთ კოდით:

ყურადღება:სახელთა სივრცის საკვანძო სიტყვა უნდა განთავსდეს ფაილის დასაწყისშივე, ამის შემდეგ
ფაილი A.php
B.php ფაილი
შესაძლებელია ალტერნატიული სინტაქსი:
რეკომენდებულია თითოეული სახელების სივრცის ცალკე ფაილში გამოცხადება. მიუხედავად იმისა, რომ ეს შესაძლებელია ერთში, მკაცრად არ არის რეკომენდებული!
ახლა გადავიდეთ მესამე ფაილზე, რომელშიც ჩვენი მთავარი სკრიპტი იმუშავებს
index.php
როგორც ჩანს, ეს უპირატესობაა, მხოლოდ მეტი კოდია დამატებული, მაგრამ ეს მთლად ასე არ არის, ცოტა შემდგომ მე მივცემ ავტოჩატვირთვის კლასის მაგალითს, რომლითაც კლასებთან ფაილების დამაკავშირებელი ხაზები ზედმეტი იქნება.
ახლა მოდით გადავხედოთ ჩვენს კლასებს.

ყურადღება:მასშტაბის გარჩევადობის ოპერატორის (::) გამოყენებით php სახელთა სივრცეებში არაა ნებადართული! ერთადერთი, რისთვისაც ის შესაფერისია, არის სტატიკური კლასის მეთოდებსა და მუდმივებზე წვდომა. თავიდან მათ სურდათ მისი გამოყენება სახელთა სივრცისთვის, მაგრამ შემდეგ მათ წინააღმდეგობა გადაწყვიტეს წარმოქმნილი პრობლემების გამო. მაშასადამე, A::A::say(); არასწორია და გამოიწვევს შეცდომას.

სახელთა სივრცისთვის, თქვენ უნდა გამოიყენოთ უკუღმა დახაზვის სიმბოლო "\"
ყურადღება:გაუგებრობების თავიდან ასაცილებლად, აუცილებელია ამ სიმბოლოს გაქცევა სტრიქონებში გამოყენებისას: "\\"

სახელთა სივრცეები შეიძლება იყოს ჩასმული ერთმანეთში, მოდით დავამატოთ ჩვენს A.php ფაილს:
და ინდექსში ჩავწერთ შემდეგს:

მნიშვნელოვანი პუნქტია იმპორტირებული ფართებისთვის მეტსახელების გამოყენება. შეგიძლიათ დაწეროთ A\subA::say(); დამეთანხმებით, რომ ძნელია ყოველ ჯერზე სრული ბილიკის დაწერა სივრცეებისკენ, ამის თავიდან ასაცილებლად შემოიღეს მეტსახელები. კომპილაციისას მოხდება შემდეგი: მეტსახელის sub-ის ნაცვლად შეიცვლება A\subA, ამიტომ მივიღებთ გამოძახებას A\subA::say();

რა ხდება მაშინ გლობალურ სივრცეში განსაზღვრული ფუნქციების გამოძახებისას? PHP ჯერ ეძებს ფუნქციას იმ სივრცეში, სადაც ამჟამად მუშაობთ, და თუ ვერ პოულობს, გადადის გლობალურ მასშტაბზე. იმისთვის, რომ დაუყოვნებლივ მიუთითოთ, რომ იყენებთ გლობალურ ფუნქციას, წინ უნდა უძღოდეთ უკანა ხაზით.

იმისათვის, რომ თავიდან ავიცილოთ პრობლემები სივრცეებიდან კლასების ავტომატური ჩატვირთვასთან დაკავშირებით, ფაილური სისტემა უნდა იყოს ორგანიზებული სივრცეების ორგანიზების მსგავსად. მაგალითად, ჩვენ გვაქვს root საქაღალდის კლასები, სადაც შეინახება ჩვენი კლასები, შემდეგ ჩვენი სივრცეები შეიძლება დალაგდეს შემდეგნაირად.
კლასები\A\A.php
classes\A\sub\A.php (ქვესივრცე განთავსდება ცალკე ფაილში)
კლასები\B\B.php

PHP-ს აქვს ჯადოსნური მუდმივი __NAMESPACE__, რომელიც შეიცავს მიმდინარე სივრცის სახელს.

ახლა კი ავტომატური ჩატვირთვის შესახებ.

ქვემოთ მოყვანილი კლასი ჩემი არ არის, უბრალოდ გავამუშავე და ცოტა გავაუმჯობესე, აქედან აღებული.
ყურადღება:იმისათვის, რომ თქვენი კლასები ჩაიტვირთოს, კლასის სახელი უნდა შეესაბამებოდეს ფაილის სახელს!

" .$ფაილი." in " .$filepath)); if (file_exists($filepath)) (if(Autoloader::debug) Autoloader::StPutFile(("დაკავშირებული" .$filepath)); $flag = FALSE; require_once($filepath); break; ) Autoloader::recursive_autoload($file, $path2, &$flag); ) ) closeir($handle); ) ) პირადი სტატიკური ფუნქცია StPutFile($data) ($dir = $_SERVER["DOCUMENT_ROOT"] ." /Log/Log.html"; $file = fopen($dir, "a"); flock($file, LOCK_EX); fwrite($file, ("║" .$data ."=>" .date(" d.m.Y H:i:s") ."

" .PHP_EOL)); flock ($file, LOCK_UN); fclose ($file); ) ) \spl_autoload_register("yourNameSpace\Autoloader::autoload"); )
თუ გადახედავთ იმ კლასების სახელებს, რომლებიც შემოდის ჩატვირთვისთვის, ნახავთ, რომ თითოეულ კლასს წინ უძღვის პრეფიქსი სახელთა სივრციდან, რომელიც მითითებულია გამოყენებაში. ამიტომ გირჩევთ გამოიყენოთ ფაილების ადგილმდებარეობა სახელთა სივრცის მსგავსი დირექტორიაში; ეს აჩქარებს ძიებას ერთ ან ორ გამეორებამდე.

ახლა ჩვენი ინდექსი შეიძლება დაიწეროს ასე:
ახლა ყველა კლასი და ინტერფეისი, რომელსაც გამოიყენებთ, ავტომატურად იტვირთება.

ენის ზოგიერთი დინამიური შესაძლებლობების საჩვენებლად სივრცეებით, მოდით გამოვაცხადოთ სხვა კლასი:
test.php

ინდექსი.php
sayName ("ტესტი"); //ან შეგიძლიათ გააკეთოთ ეს ტესტი\sayName("test2"); //ან ასე $obj::sayName("ტესტი"); //ან შეგიძლიათ გააკეთოთ ეს ტესტი::sayName("test2");

იმედი მაქვს, რომ ჩემი სტატია ვინმესთვის სასარგებლო იქნება.

(PHP 5 >= 5.3.0, PHP 7)

სანამ სახელთა სივრცის გამოყენებას განვიხილავთ, მნიშვნელოვანია გვესმოდეს, თუ როგორ იცის PHP-მა სახელთა სივრცის რომელ ელემენტს ითხოვს თქვენი კოდი. მარტივი ანალოგია შეიძლება გაკეთდეს PHP სახელთა სივრცესა და ფაილურ სისტემას შორის. ფაილურ სისტემაში ფაილზე წვდომის სამი გზა არსებობს:

  1. ფაილის შედარებითი სახელი, როგორიცაა foo.txt. ეს წყვეტს მიმდინარე დირექტორია/foo.txtსადაც currentdirectory არის დირექტორია, რომელიც ამჟამად დაკავებულია. ასე რომ, თუ მიმდინარე დირექტორია არის /სახლი/ფუ, სახელი გადაწყვეტს /home/foo/foo.txt.
  2. ბილიკის შედარებითი სახელი, როგორიცაა ქვედირექტორია/foo.txt. ეს წყვეტს currentdirectory/subdirectory/foo.txt.
  3. ბილიკის აბსოლუტური სახელი, როგორიცაა /main/foo.txt. ეს წყვეტს /main/foo.txt.
იგივე პრინციპი შეიძლება გამოყენებულ იქნას PHP-ში სახელთა სივრცის ელემენტებზე. მაგალითად, კლასის სახელი შეიძლება მოიხსენიებოდეს სამი გზით:
  1. არაკვალიფიცირებული სახელი, ან კლასის არაპრეფიქსის მსგავსი სახელი $a = new foo();ან foo::staticmethod(); მიმდინარე სახელთა სივრცე, ეს გადაწყვეტს მიმდინარე სახელთა სივრცე\foo ფუ. ერთი გაფრთხილება: ფუნქციების და მუდმივების არაკვალიფიცირებული სახელები გადაიჭრება გლობალურ ფუნქციებსა და მუდმივებზე, თუ სახელთა სივრცის ფუნქცია ან მუდმივი არ არის განსაზღვრული. დეტალებისთვის იხილეთ სახელების სივრცის გამოყენება: დაბრუნება გლობალურ ფუნქციაზე/მუდმივზე.
  2. კვალიფიციური სახელი, ან კლასის პრეფიქსის მსგავსი სახელი $a = new subnamespace\foo();ან subnamespace\foo::staticmethod();. თუ მიმდინარე სახელთა სივრცე არის მიმდინარე სახელთა სივრცე, ეს გადაწყვეტს currentnamespace\subnamespace\foo. თუ კოდი არის გლობალური, არასახელთაშორისი კოდი, ეს გადაწყდება ქვესახელთა სივრცე\foo.
  3. სრულად კვალიფიციური სახელი, ან პრეფიქსის სახელი გლობალური პრეფიქსის ოპერატორის მსგავსი $a = new \currentnamespace\foo();ან \currentnamespace\foo::staticmethod();. ეს ყოველთვის წყდება კოდში მითითებულ სიტყვასიტყვით, მიმდინარე სახელთა სივრცე\foo.

აქ მოცემულია სამი სახის სინტაქსის მაგალითი რეალურ კოდში:

სახელთა სივრცე Foo\Bar\subnamespace;

const FOO = 1;
ფუნქცია foo()()
კლასის საკვები
{
}
?>

სახელთა სივრცე Foo\Bar;
მოიცავს "file1.php" ;

const FOO = 2;
ფუნქცია foo()()
კლასის საკვები
{
სტატიკური ფუნქცია staticmethod()()
}

/* არაკვალიფიციური სახელი */
foo(); foo::staticmethod(); echo FOO;

/* კვალიფიციური სახელი */
subnamespace\foo(); // გადაწყვეტს ფუნქციას Foo\Bar\subnamespace\foo
subnamespace\foo::staticmethod(); // წყვეტს კლასს Foo\Bar\subnamespace\foo,
// მეთოდის სტატიკური მეთოდი
echo subnamespace\FOO; // გადადის მუდმივზე Foo\Bar\subnamespace\FOO

/* სრულად კვალიფიციური სახელი */
\foo\bar\foo(); // წყვეტს ფუნქციას Foo\Bar\foo
\foo\bar\foo::staticmethod(); // გადადის კლასში Foo\Bar\foo, მეთოდი staticmethod
echo\Foo\Bar\FOO; // გადადის მუდმივზე Foo\Bar\FOO
?>

გაითვალისწინეთ, რომ ნებისმიერი გლობალური კლასის, ფუნქციის ან მუდმივის წვდომისთვის შეიძლება გამოყენებულ იქნას სრულად კვალიფიციური სახელი, როგორიცაა \strlen()ან \გამონაკლისიან \INI_ALL. ?>