Hola, estoy creando un trait de yii 2 para el manejo de relaciones, en este componente no tiene mucho potencial ya que es la primera versión, les comparto el codigo que eh creado y como se usa para
trait Relations
{
/**
* @var array $relations
* Variable que tendra
* las relaciones que se desean
* usar
*/
protected $relations;
/**
* Carga las relaciones que el modelo tiene disponible
*
* @param \yii\base\Model $model modelo de tu base de datos
* @return void
*/
public function setRelations()
{
$args = func_get_args();
if (empty($args)) return;
if (isset($args[0]) && is_array($args[0]))
$this->relations = $args[0];
if (!is_array($args[0])) {
foreach ($args as $key => $value) {
if (is_int($key)) $this->relations[] = $value;
}
}
$this->getRelations();
}
protected function getRelations()
{
foreach ($this->relations as $value) {
$get = $this->_convertToGet($value);
if (($relation = $this->isGetRelation($get)) !== null) {
$this->loadRelationClass($relation, $value);
}
}
}
protected function isGetRelation(string $item): ActiveQuery|null
{
if (!method_exists($this, $item)) return null;
$method = new ReflectionMethod($this, $item);
if (
!$this->$item() instanceof ActiveQuery ||
$method->getNumberOfRequiredParameters() != 0
) return null;
return $this->$item();
}
protected function loadRelationClass(ActiveQuery $model, $relationName)
{
if ($model->multiple) return;
$relation = $model->one() === null ? new $model->modelClass : $model->modelClass;
$this->populateRelation($relationName, $relation);
}
public function loadAll(array $post)
{
$post = Yii::$app->request->post();
if (!is_array($post))
throw new InvalidConfigException('Invalid parameters');
$status = $this->load($post) && $this->validate();
if (count($this->relatedRecords) == 0)
return $status;
foreach ($this->relatedRecords as $value)
$status = $value->load($post) && $value->validate();
return $status;
}
public function saveAll()
{
$transaction = $this->getDb()->beginTransaction();
try {
$relations = $this->relatedRecords;
foreach ($relations as $key => $_) {
$item = $this->_convertToGet($key);
$foreignKey = array_values($this->$item()->link)[0];
if (!$this->$key->save()) {
$transaction->rollBack();
return false;
}
$this->$foreignKey = $this->$key->primaryKey;
}
if (!$this->save()) {
$transaction->rollBack();
return false;
}
$transaction->commit();
return true;
} catch (\Throwable $err) {
$transaction->rollBack();
throw $err;
}
}
protected function _convertToGet($name)
{
return 'get' . ucfirst($name);
}
}
en el modelo se aplica de la siguiente manera
class Empresa extends \yii\db\ActiveRecord
{
use Relations;
}
y en el controlador se usa asi
$model = new Empresa();
$model->setRelations('direccion');
if (!$this->request->isPost) return $this->render('create', [
'model' => $model,
'states' => Estado::selectStates(),
'typeBuilding' => TipoEdificio::select()
]);
$model->loadAll($this->request->post());
$model->saveAll();
$this->refresh();
basicamente tu envias la relaciones que necesitas y en tu formulario lo usas con normalidad
luego cargar la informacion del post y despues puedes hacer un save all
para guardar toda la info, aun que todavia tengo inseguridades por la parte de save all
porque puede fallar de diferentes formas, pero que opinan de este codigo que les comparto?