Как последоватьно связать три таблицы?

Есть три таблицы County(id, name), Sity(id,name,country_id),Street(id,name,sity_id)


Country                      Sity                            Steet
     id   name          id   name    country_id      id   name   sity_id          
     1   Россия         1    Москва     1            1    Арбат    1



вопрос 1 как мне, обращаясь через модель Street получить такую запись: Россия г.Москва, ул. Арбат
Вопрос 2 как мне получить все Города и улицы этих городов обращаясь через модель Country . В просторах интернета и в документации встретил такой код
public function getItems()
        {
            return $this->hasMany(Item::className(), ['id' => 'item_id'])
                ->via('orderItems');
        }


не знаю подходит ли он мне и как с ним работать тоже не понял. Объясните пожалуйста
  • Вопрос задан
  • 107 просмотров
Решения вопроса 1
Код, который вы скинули это промежуточная таблица, которая реализует связь многие-ко-многим. И это не ваш случай т.к. В таком случае выходит, что Город Москва принадлежит и России и Любым другим странам. А Другие страны имеют у себя город Москву.

У вас связи один ко многим. Т.е.
1) Одна страна(один) имеет множество городов(многим).
2) Один город(один) имеет множество улиц(многие).

class Country extends ActiveRecord
{
    // HasMany - указывает на то, что получаемое будет множество.
    public function getСities()
    {
        return $this->hasMany(City::className(), ['country_id' => 'id']);
    }
}

class City extends ActiveRecord
{
    public function getCountry()
    {
         //HasOne - показывает, что получаемая запись одна 
        return $this->hasOne(Counter::className(), ['id' => 'country_id']);
    }
}


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

Вот так получаете все города, которые принадлежат одной стране.
$country = Country::findOne(1); // ищем город с id 1

// SELECT * FROM `City` WHERE `country_id` = 1
// $сities - это массив объектов City
$сities = $country->сities; // Обратите внимание, что в модели города, есть Getter и именно то название.


Для получения вложенных связей лучше использовать жадную загрузку(тянуть все связи одни запросом т.к. это менее ресурсозатратно чем вытаскивать по десять раз только нужное.)

$countries = Country::find()->with('cities.streets')->all(); // внутри With помещены геттеры связей.
// ниже код, запрос в базу не делает. он вытаскивает все из запроса то что выше. т.е. экономит вашу память и бережет БД. 
$streets = $countries[0]->cities[0]->streets; // указывая массивы можно вызвать конкретную страну с конкретным городом и получить нужные улицы.

Так же вы можете сделать кастомный запрос, через анонимные функции. в которых подставлять нужные значения Страны, Города, улицы - тем самым вытаскивая что-то конкретное

P.S. Обратите внимание на название Getter-ов они в единственном числе где связь одна и во множественном где многие. Не забывайте про хороший нейминг. Так вы не запутаетесь сами в своих связях. Удачи )
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы