php laravel laravel-3

php - No se pudo obtener el elocuente para crear uniones automáticamente



laravel laravel-3 (4)

Disculpas de antemano si la respuesta a mi pregunta es obvia. He hecho mi diligencia debida al investigar este tema antes de publicar aquí.

La mayor parte de mi experiencia marco proviene del uso de CodeIgniter, por lo que nunca he tenido experiencia práctica con ORM. (CI tiene algunas soluciones ORM listas para usar, pero nunca las he usado).

Me gustaría utilizar la funcionalidad ORM incorporada en el ORM Eloquent de Laravel para unir automáticamente los torneos y las tablas de países cuando se ejecuta una consulta , y devolver un conjunto de datos que incluye datos de torneos, así como sus datos de país asociados.

Es decir, quiero que Eloquent reconozca automáticamente la relación de clave externa para que pueda ejecutar una consulta (por ejemplo, Tournament :: con (''País'') -> todo ()) que devolverá todo el conjunto de datos de torneo y país.

¡Por favor, deténganme ahora mismo si uso Eloquent de una manera que nunca fue pensada para ser utilizada! Mi confusión puede ser más sobre mí tratando de mezclar una solución insostenible en lugar de una sintaxis o un error de codificación.

Pregunta que me gustaría replicar en Eloquent

SELECT * FROM tournaments LEFT JOIN countries ON tournaments.country_id = countries.id

Resultado esperado en PHP

Espero recibir una serie de objetos de Torneo (en PHP), donde se verá un solo objeto de Torneo:

  • torneos.id
  • torneos.año
  • torneos.country_id
  • torneos.created_at
  • torneos.updated_at
  • countries.id
  • countries.code
  • countries.name
  • countries.url
  • countries.created_at
  • countries.updated_at

Intentos fallidos que he hecho hasta ahora

Ejecuté todos estos intentos en un método de controlador falso y envié el resultado como una cadena formateada al generador de perfiles.

Intento fallido n. ° 1:

Código PHP en el controlador ficticio:

$tournaments = Tournament::with(''Country'')->all();

Genera la siguiente consulta:

SELECT * FROM `tournaments`

Intento # 1 regresa:

Una matriz que contiene objetos de torneo que solo incluyen las columnas en la tabla de torneos.

Intento fallido # 2

Código PHP en el controlador ficticio:

$tournaments = Tournament::with(''Country'')->first();

Genera el siguiente error:

SQLSTATE[42S22]: Column not found: 1054 Unknown column ''tournament_id'' in ''where clause'' SQL: SELECT * FROM `countries` WHERE `tournament_id` IN (?) Bindings: array ( 0 => ''1'', )

Otros intentos fallidos

He intentado varias combinaciones de convenciones de nomenclatura (por ejemplo, columnas, tablas, etc.) en vano. También intenté crear la consulta en Fluent, que funcionó bien, pero requirió que especificara las combinaciones, que es lo que trato de evitar.

Mi entorno

  • PHP: 5.3.13
  • MySQL: 5.1.53
  • Laravel: 3.2.3

Relación entre tablas

  • relación uno-a-uno
  • Un torneo debe tener un país (hay una restricción de clave externa para aplicarlo)
  • Un país puede pertenecer a muchas otras relaciones (por ejemplo, un participante, que no se muestra aquí, tiene un país de nacimiento)

Tabla de países

CREATE TABLE `countries` ( `id` int(11) NOT NULL AUTO_INCREMENT, `code` varchar(4) NOT NULL, `name` varchar(25) NOT NULL, `url` varchar(25) NOT NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `countries_code_unique` (`code`), KEY `countries_url_index` (`url`) ) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=latin1

Tabla de torneos

CREATE TABLE `tournaments` ( `id` int(11) NOT NULL AUTO_INCREMENT, `year` int(11) NOT NULL, `country_id` int(11) NOT NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `tournaments_year_unique` (`year`), KEY `tournaments_country_id_foreign` (`country_id`), CONSTRAINT `tournaments_country_id_foreign` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON UPDATE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=latin1

Modelo de países (countries.php)

class Country extends Eloquent { public static $timestamps = true; public static $table = ''countries''; }

Modelo de Torneos (tournaments.php)

class Tournament extends Eloquent { public static $timestamps = true; public function country() { return $this->has_one(''Country''); } }


Claramente with(''Country'') o with(''country'') no hace ninguna diferencia debido al hecho de que logró obtener el siguiente error:

Column not found: 1054 Unknown column ''tournament_id'' in ''where clause'' SQL: SELECT * FROM `countries` WHERE `tournament_id` IN (?)

Lo que está mal es cómo se define la relación: Un torneo debe tener un país. Sería un torneo necesario para pertenecer a un país, y no tener un país. Entonces para resolver esto cambia la relación a

public function country() { return $this->belongs_to(''Country''); }


De acuerdo con los documentos Eloquent:

Nota: Todos los métodos disponibles en el generador de consultas también están disponibles cuando se consultan modelos Eloquent.

Entonces con eso en mente algo así como:

DB::table("tournament")->join("countries","tournaments.country_id","=","countries.id")->get();

Debería ser replicable en Eloquent. Personalmente utilizo la versión del generador de consultas que desea usar ahora, pero intentaré probar con Eloquent cuando tenga la oportunidad y actualizo esto.

ACTUALIZAR:

Sí, usando los métodos del generador de consultas de Eloquent puedes tener:

Tournament::join("countries","tournaments.country_id","=","countries.id")->get();

Esto devolverá un modelo de torneo que incluye los campos de ambas tablas.

HTH


Debes asegurarte de que tu relación esté declarada en tu modelo de torneo:

public function country() { return $this->has_one(''Country''); }

Además, deberá declarar lo contrario en su modelo de país:

public function tournament() { return $this->belongs_to(''Tournament''); }

En este punto, puede acceder al objeto de torneo asociado con el objeto de país de la siguiente manera:

$tournaments = Tournament::with(''country'')->all(); foreach ($tournaments as $tournament) { echo $tournament->country; }

Avíseme si esto muestra cada país correspondiente al torneo.


Su cláusula ''con'' pide ''País'', pero su código lo declara como ''país''.

También debería:

$tournaments = Tournament::with(''Country'')->all();

Ser:

$tournaments = Tournament::with(''country'')->all();

Porque en su Modelo de Torneos, usted ha definido esto como:

public function country() { return $this->has_one(''Country''); }

¿Hacer que este cambio lo resuelva?