Форум программистов, компьютерный форум, киберфорум
PHP: ООП
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.86/21: Рейтинг темы: голосов - 21, средняя оценка - 4.86
4 / 3 / 2
Регистрация: 11.08.2016
Сообщений: 352

Передача private переменных

22.06.2019, 11:03. Показов 4760. Ответов 24
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте!
Пишу свой класс подключения к БД. Он работает более чем успешно, но проблема в том, что переменная соединения использует private доступ. То есть вызвать из другого класса не получится. protected так же дает отказ по той же причине. public - рабочее решение, но почитав форумы понял, что так делать небезопасно и лучше использовать private. static дает предупреждение, но все исполняет. Сейчас приведу отрывки кода, а потом задам вопрос:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?
     namespace app\lib;
     use PDO;
     class DataBaze {
         public $connection;
 
         public function __construct() {
             //данные подключения тут
             $this->connection=new PDO("mysql:host=$host;dbname=$dbname", $uname, $password);
             $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
             $this->connection->exec("set names utf8"); //успешное соединение
         }
}
?>
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
<?
     namespace app\controllers;
     use app\core\Controller;
     use app\lib\DataBaze;
     class MainController extends Controller{
         public function indexAction(){
             $db= new DataBaze;
             $data= $db->connection->prepare("SELECT name FROM users");
             var_dump($data);
             $this->view->render('Главная страница');
         }
     }
?>
Вопрос: Как передать $this->connection или $connection в метод класса indexAction используя модификатор доступа private или protected вместо public? Если нет решения, то тогда оставлять как есть?
Заранее благодарен!
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
22.06.2019, 11:03
Ответы с готовыми решениями:

Передача интерполяционных переменных
Здравствуйте. Строится цикл: for ($counte = 1; $counte &lt;= 4; $counte++) { $iden += 1; print &quot;&lt;input type='text'...

Передача переменных методом GET
Здравствуйте. Помогите с проблемой. Пытаюсь передать данные методом GET. Вот начало кода, в котором, собственно, и проблема. ...

Передача переменных (get/post/.)
Привет. В общем вот кусочек кода, имеется input text с именем &quot;name&quot; значение которого нужно передать(name): print ' &lt;input...

24
Эксперт PHP
3900 / 3238 / 1353
Регистрация: 01.08.2012
Сообщений: 10,914
22.06.2019, 11:47
Для этого сейчас используется IoC контейнер, например от Laravel. Можете установить его отдельно и использовать без фреймворка.

Если это пока слишком сложно, тогда гляньте паттерн Синглтон.

Добавлено через 7 минут
Цитата Сообщение от Uni_programist Посмотреть сообщение
Как передать $this->connection или $connection в метод класса indexAction используя модификатор доступа private или protected вместо public?
Можно сделать метод getConnection(), который будет возвращать объект pdo. Минус в том, что сколько таких объектов создашь, столько создастся подключений к базе. При использовании синглтона такой проблемы не будет.
0
4 / 3 / 2
Регистрация: 11.08.2016
Сообщений: 352
22.06.2019, 11:53  [ТС]
Jodah, то есть так, как обращаемся к public, обратиться к private и protected не получится? И почему нельзя оставить public? Нет, конечно для тренировки можно и попробовать Синглтон.
0
Эксперт PHP
3900 / 3238 / 1353
Регистрация: 01.08.2012
Сообщений: 10,914
22.06.2019, 13:03
Цитата Сообщение от Uni_programist Посмотреть сообщение
так, как обращаемся к public, обратиться к private и protected не получится?
Да, они же для этого и предназначены.

Цитата Сообщение от Uni_programist Посмотреть сообщение
почему нельзя оставить public?
Классы нужно проектировать так, чтобы их легко было использовать правильно и сложно использовать неправильно. В вашем примере можно изменить переменную $this->connection извне. Этого быть не должно.
0
4 / 3 / 2
Регистрация: 11.08.2016
Сообщений: 352
22.06.2019, 13:14  [ТС]
Jodah, ну вот сделал по паттерну Сиглтон, но кидает ошибку:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?
     namespace app\lib;
     use PDO;
     class DataBaze {
         private $connection;
         static private $_ins = NULL;
         static public function get_instance() {
             if(self::$_ins instanceof self) {
                 return self::$_ins;
             }
             return self::$_ins = new self;
         }
         private function __construct() {
            //данные к БД
             $this->connection=new PDO("mysql:host=$host;dbname=$dbname", $uname, $password);
             $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
             $this->connection->exec("set names utf8");
         }
         private function __clone(){}
}
?>
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
<?
     namespace app\controllers;
     use app\core\Controller;
     use app\lib\DataBaze;
     class MainController extends Controller{
         public function indexAction(){
             $db= DataBaze::get_instance();
             $data= $db->connection->prepare("SELECT name FROM users");
             var_dump($data);
             $this->view->render('Главная страница');
         }
     }
?>
Ошибка Fatal error: Uncaught Error: Cannot access private property app\lib\DataBaze::$connection
То есть у меня до сих пор нет доступа к переменной подключения, почему?
0
Эксперт PHP
3900 / 3238 / 1353
Регистрация: 01.08.2012
Сообщений: 10,914
22.06.2019, 16:21
Uni_programist, здесь $connection не нужна, через get_instance можно сразу объект PDO возвращать.
0
 Аватар для sad67man
2604 / 1508 / 689
Регистрация: 23.08.2015
Сообщений: 3,839
22.06.2019, 17:38
Uni_programist, Синглтон правильное решение, но хочу написать просто, чтоб вы понимали. Модификаторы protected или private служит для того, чтоб их не дергали из вне. К примеру, если вы делаете публичное свойство, то вы должны учитывать, что кто-то сможет его изменить из-вне к примеру:
PHP
1
2
$db= new DataBaze;
$db->connection = 5; // просто кто-то изменил свойство, все поломалось и потом будете долго искать ошибку)
Вот чтоб такое не происходило делаем это свойство private и пишем getter
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class DataBaze {
    
    private $connection;
    
    public function __construct() {
        //данные подключения тут
        $this->connection=new PDO("mysql:host=$host;dbname=$dbname", $uname, $password);
        $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->connection->exec("set names utf8"); //успешное соединение
    }
    
    public function getConnection() 
    {
        return $this->connection;
    }
}
PHP
1
2
$db = new DataBaze;
$data= $db->getConnection()->prepare("SELECT name FROM users");
0
4 / 3 / 2
Регистрация: 11.08.2016
Сообщений: 352
22.06.2019, 21:15  [ТС]
sad67man, хотелось бы поддержать дискуссию:
Цитата Сообщение от sad67man Посмотреть сообщение
К примеру, если вы делаете публичное свойство, то вы должны учитывать, что кто-то сможет его изменить из-вне к примеру
Вопрос в том кто? Если над сайтом работаю только я и пару знакомых, которые уж точно не сломают систему, если это данные из формы, то применим FILTER_SANITIZE_STRING, ну а если это будет профессиональный хакер тут хоть private ставь, хоть protected, если у него получилось взломать и войти в систему он может редактировать код, точно так же как это делаю я.
Цитата Сообщение от sad67man Посмотреть сообщение
Вот чтоб такое не происходило делаем это свойство private и пишем getter
Ну я читал мануалы целый день и так и сделал ибо судя по всему выхода нет .
Jodah, модифицируя эту строку так:
PHP
1
$data= $db->prepare("SELECT name FROM users");
по-моему тоже приводит к ошибке. Попробую еще раз, если выскочит ошибка, то пришлю её в данную ветку.
0
Эксперт PHP
4925 / 3920 / 1620
Регистрация: 24.04.2014
Сообщений: 11,441
22.06.2019, 23:14
Цитата Сообщение от Uni_programist Посмотреть сообщение
Вопрос в том кто? Если над сайтом работаю только я и пару знакомых, которые уж точно не сломают систему, если это данные из формы, то применим FILTER_SANITIZE_STRING, ну а если это будет профессиональный хакер тут хоть private ставь, хоть protected, если у него получилось взломать и войти в систему он может редактировать код, точно так же как это делаю я.
Модификаторы доступа нужны не для защиты от взлома, это относится к одному из "столпов" ООП - инкапсуляции. Если ты изучаешь ООП и не слышал этого слова, то значит что-то делаешь не так.
1
 Аватар для sad67man
2604 / 1508 / 689
Регистрация: 23.08.2015
Сообщений: 3,839
23.06.2019, 00:35
Uni_programist,
Цитата Сообщение от Uni_programist Посмотреть сообщение
Вопрос в том кто? Если над сайтом работаю только я и пару знакомых
Разные бывают ситуации, конкретно в данном случае может и прокатит, но это вы сами понимаете, что это должны быть устные соглашения, что вот данное свойство нельзя переопределять, а потом пойди и разберись, почему человек так сделал, знаете бывает и сам че-нить такое напишешь, и потом сам не понимаешь, чем ты руководствовался в тот момент. При этом это сегодня у вас над проектом работает пару человек, а что будет скажем через 5 лет никто не знает.
Потом если вы пользуетесь ide (к примеру как phpstorm), то он дает разные подсказки, какие у объекта есть свойства и методы, и если там он дает подсказку что есть данное свойство, то это значит, что его будут дергать)
И мы сейчас уже обсуждаем суть, если бы у нас был только один такой объект, ведь в проекте их множество, и когда вы сами спустя достаточно большое время возвращаетесь к нему за доработкой, то там уже сложно будет вспомнить что к чему. Чем все строже, тем лучше.
1
4 / 3 / 2
Регистрация: 11.08.2016
Сообщений: 352
25.06.2019, 00:48  [ТС]
Jewbacabra,
Цитата Сообщение от Jewbacabra Посмотреть сообщение
Модификаторы доступа нужны не для защиты от взлома, это относится к одному из "столпов" ООП - инкапсуляции. Если ты изучаешь ООП и не слышал этого слова, то значит что-то делаешь не так.
Да как раз слово да и только и слышал... До этого дня...
Цитата Сообщение от sad67man Посмотреть сообщение
Разные бывают ситуации, конкретно в данном случае может и прокатит, но это вы сами понимаете, что это должны быть устные соглашения
Да, согласен разубедили.
Jodah,
Цитата Сообщение от Jodah Посмотреть сообщение
здесь $connection не нужна, через get_instance можно сразу объект PDO возвращать.
Но ведь без return не получится, верно?
0
Эксперт PHP
3900 / 3238 / 1353
Регистрация: 01.08.2012
Сообщений: 10,914
25.06.2019, 13:04
Цитата Сообщение от Uni_programist Посмотреть сообщение
Но ведь без return не получится, верно?
В методе get_instance? Ну да, return нужен. Просто вместо $this->connection объект PDO сохраняете в self::$_ins, который затем возвращаете.
0
4 / 3 / 2
Регистрация: 11.08.2016
Сообщений: 352
25.06.2019, 13:40  [ТС]
Jodah, Иначе говоря так:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?
     namespace app\lib;
     use PDO;
     class DataBaze {
         private $connection;
         static private $_ins = NULL;
         static public function get_instance() {
             if(self::$_ins instanceof self) {
                 return self::$_ins;
                 return $this->connection;
             }
             return self::$_ins = new self;
         }
         private function __construct() {
            //данные к БД
             $this->connection=new PDO("mysql:host=$host;dbname=$dbname", $uname, $password);
             $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
             $this->connection->exec("set names utf8");
         }
         private function __clone(){}
}
?>
0
Эксперт PHP
3900 / 3238 / 1353
Регистрация: 01.08.2012
Сообщений: 10,914
25.06.2019, 21:20
Uni_programist, не, я же говорю, $this->connection тут вообще не нужна. Типа такого:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
namespace app\lib;
use PDO;
 
class DataBase
{
    private static $instance;
 
    public static function getInstance()
    {
        if(!self::$instance)
        {
            $host = 'localhost';
            $dbname = 'test';
            $uname = 'root';
            $password = 'test';
            
            $pdo = new PDO("mysql:host=$host;dbname=$dbname", $uname, $password);
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $pdo->exec("set names utf8");
            
            self::$instance = $pdo;
        }
        
        return self::$instance;
    }
 
    private function __construct(){}
    private function __clone(){}
}
 
$pdo = \app\lib\Database::getInstance();
$pdo->query('SELECT * FROM `users`')->fetchAll(PDO::FETCH_ASSOC);
1
4 / 3 / 2
Регистрация: 11.08.2016
Сообщений: 352
25.06.2019, 22:49  [ТС]
Jodah, требует PDO...
Fatal error: Uncaught Error: Class 'app\core\PDO' not found in /home/f///public_html/app/core/Model.php:8 Stack trace: #0
Но почему ведь PDO это... ? В общем почему-то app\core\PDO
Вот файл модели:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
<?
     namespace app\core;
     //use app\lib\DataBase;
     class Model{
         public $db;
         public function __construct(){
             $pdo= \app\lib\DataBase::getInstance();
             $pdo->query('SELECT * FROM `users`')->fetchAll(PDO::FETCH_ASSOC);
             var_dump($this->db);
         }
     }
?>
может потому, что он наследуется
PHP
1
2
3
4
5
<?
     namespace app\model;
     use app\core\Model;
     class Main extends Model{
         public function getNews(){
Помогите разобраться, ведь это похоже на безумие (для меня)...
0
Эксперт PHP
3900 / 3238 / 1353
Регистрация: 01.08.2012
Сообщений: 10,914
25.06.2019, 23:42
Цитата Сообщение от Uni_programist Посмотреть сообщение
В общем почему-то app\core\PDO
Если вы не указали пространство имён, то можно писать new \PDO и new PDO, будет работать одинаково.

Если указали пространство имён, например App\Library, то new \PDO создаст объект PDO, а код new PDO (без слеша) создаст объект App\Library\PDO.

Либо можно добавить в начало кода use PDO, как у вас было изначально и я оставил в своём примере, тогда можно писать new PDO без слеша и PHP поймёт, что речь идёт именно о базовом классе PDO.

К слову, в документации всё это расписано простым языком.
0
4 / 3 / 2
Регистрация: 11.08.2016
Сообщений: 352
25.06.2019, 23:55  [ТС]
Jodah,
Цитата Сообщение от Jodah Посмотреть сообщение
Либо можно добавить в начало кода use PDO, как у вас было изначально и я оставил в своём примере, тогда можно писать new PDO без слеша и PHP поймёт, что речь идёт именно о базовом классе PDO.
Ну да так и есть вот эта строка:
PHP
1
$pdo = new \PDO("mysql:host=$host;dbname=$dbname", $uname, $password);
без слеша и use PDO; есть и пространство имен namespace app\lib;
в модели написал так:
PHP
1
$pdo= '\app\lib\DataBase'::getInstance();
и так:
PHP
1
$pdo= '\app\lib\DataBase'::getInstance();
ошибку про PDO это не убирает...
0
Эксперт PHP
3900 / 3238 / 1353
Регистрация: 01.08.2012
Сообщений: 10,914
25.06.2019, 23:59
Uni_programist, ещё раз: либо пишем use PDO перед описанием класса, либо пишем просто new \PDO. Посмотрите ещё раз мой пример, он полностью рабочий.
0
4 / 3 / 2
Регистрация: 11.08.2016
Сообщений: 352
26.06.2019, 00:06  [ТС]
Jodah, ну скажем так я его и скопировал:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?
     namespace app\lib;
     use PDO;
     class DataBase{
         private static $instance;
         public static function getInstance(){
         if(!self::$instance){
             $host = 'localhost';
             $dbname = 'root';
             $uname = 'root';
             $password = 'notfound';
            
             $pdo = new PDO("mysql:host=$host;dbname=$dbname", $uname, $password);
             $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
             $pdo->exec("set names utf8");
             self::$instance = $pdo;
         }
         return self::$instance;
     }
     private function __construct(){}
     private function __clone(){}
}
 
?>
Записал свои данные подключения, но ошибка сохраняется, проверил и очистил кеш, но толку маловато от этого действия... use есть и пространство имен тоже...
0
Эксперт PHP
3900 / 3238 / 1353
Регистрация: 01.08.2012
Сообщений: 10,914
26.06.2019, 00:16
Uni_programist, пройдитесь ещё раз по файлам, возможно что-то где-то не сохранили и осталась прежняя версия. У меня этот код работает.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
26.06.2019, 00:16
Помогаю со студенческими работами здесь

Вызов скрипта и передача ему переменных
есть такой скрипт $var=include(&quot;d.php&quot;); echo ($var); d.php &lt;?php $var2='blablabla'; return $var2; ?&gt; всё...

Передача значений переменных внутри класса.
В результате класс выдает результат 0, без сообщений об ошибках. Что не верно? class arithmetic { var $one = 1; ...

Передача функции в качестве переменных другим функциям
Возможно ли в PHP передавать функции в качестве аргумента методам класса? Например есть такой код: class test { function funcToRun() {...

Передача в private
Как можно передать эти 2 переменные : class Menu{ private: int arrow; int last_arrow;

Передача private класса в функцию
Имеется класс class Computer { ... } и второй класс который наследует первый class NoteBook1 : private Computer {... } И...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt
8Observer8 05.04.2026
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: https:/ / github. com/ qt-creator/ qt-creator, где можно скачать установщик, на вкладке Releases:. . .
AkelPad-скрипты, структуры, и немного лирики..
testuser2 05.04.2026
Такая программа, как AkelPad существует уже давно, и также давно существуют скрипты под нее. Тем не менее, прога живет, периодически что-то не спеша дополняется, улучшается. Что меня в первую очередь. . .
Отображение реквизитов в документе по условию и контроль их заполнения
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеСпецтехники", разработанного в конфигурации КА2. Данный документ берёт данные из другого нетипового документа. . .
Фото всей Земли с борта корабля Orion миссии Artemis II
kumehtar 04.04.2026
Это первое подобное фото сделанное человеком за 50 лет. Снимок называют новым вариантом легендарной фотографии «The Blue Marble» 1972 года, сделанной с борта корабля «Аполлон-17». Новое фото. . .
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизитов табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: 1. Реализовать контроль заполнения реквизита. . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru