dimsav / laravel-translatable

[Deprecated] A Laravel package for multilingual models
MIT License
1.95k stars 320 forks source link

Using save method leads to blank translatedAttributes or error if they are not null in the database #412

Closed saidbakr closed 5 years ago

saidbakr commented 7 years ago

The following is the action for creating new record.

public function store(Request $request)
    {
        $this->validate($request,[
            'title' => 'required',
            'weight' => 'required|integer|max:99,min:-99',
            'color' => 'required|regex:/^#[0-9A-F]{6}$/',
            'suspension' => 'required|integer|in:0,1'
        ]);        
        $status = new Status();
        $status->weight = $request->weight;
        $status->title = request('title');
       // dd($request->title);

        $status->color = $request->color;
        $status->suspension = $request->suspension;
        $status->description = $request->description;
        $status->save(['title' => $request->title]);
        $request->session()->flash('status','success');
        $request->session()->flash('msg',__('Status has benn created Successfully'));
        return redirect('/status');

    }

This is Status Model:

class Status extends Model
{

       use \Dimsav\Translatable\Translatable;

       public $translatedAttributes = ['title', 'description']; //'title', 'description'
       // protected $fillable = ['code'];

        public $timestamps = false;

      // public $timestamps = false;
...

The problem the field title is not saved. i.e it generates an error about it has no default value. As shown in the code above it already supplied. Otherwise, I have to change the MySQL connection to be strict => false. Also in this case, the value of title is placed in the translation table not in the original table. i.e it placed in status_translations instead of statuses table.

Laravel version 5.4. and MySQL 7.

Update

Making empty translatedAttributes in the model during save() solves this issue. but it stops translations management.

dimsav commented 7 years ago

Why do you do $status->save(['title' => $request->title]); ?

saidbakr commented 7 years ago

@dimsav I usually don't do this. I just do it temporary to test fillable. However, I tried the following to solve the problem based on the idea of default language i.e the original language that the original table data with it.

<?php
// Parent model that all translatable models should extends
namespace App;

use Illuminate\Database\Eloquent\Model;

class Langless extends Model
{
    public $langlessModels;
    public function __construct(array $attributes = array()) {
          parent::__construct($attributes);
          $this->langlessModels = config('fox.langlessModels'); // List of store and update actions ['store','update']
         // dd(\Route::currentRouteAction());
          if (!is_null(\Route::currentRouteAction())){
              $routeArr = explode('@', \Route::currentRouteAction());
              $actionName = $routeArr[1];
              $controllerName = (strpos($routeArr[0], 'TranslationController')!== false)? false:true;
             // dd($controllerName);
            if (in_array($actionName, $this->langlessModels)&&$controllerName) {
                $this->translatedAttributes = []; // set empty translatedAttributes for store and update
            }
        }

      }
}

Status.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Dimsav\Translatable\Translatable;
/**
 * App\Status
 *
 * @property int $id
 * @property string $title
 * @property string $color
 * @property int $weight
 * @property bool $suspension Does the action suspend the production. default 0 i.e no, 1 = yes
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Cavity[] $cavities
 * @method static \Illuminate\Database\Query\Builder|\App\Status whereColor($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Status whereId($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Status whereSuspension($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Status whereTitle($value)
 * @method static \Illuminate\Database\Query\Builder|\App\Status whereWeight($value)
 * @mixin \Eloquent
 */
class Status extends Langless
{

       use Translatable;

       public $translatedAttributes = ['title', 'description']; //'title', 'description'
        protected $fillable = ['title','description'];

        public $timestamps = false;

Also there is LanglessController that turns locale to default language for that controllers

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Route;

class LanglessController extends Controller
{
    public $langlessActions;
    public function __construct(Route $route) {
         $this->langlessActions = config('fox.langlessActions');

        //\App::setLocale('ar');
        $this->middleware(['auth'])->except('nojs');
        $actionName = explode('@',$route->getActionName())[1];
        if (in_array($actionName,$this->langlessActions)){
            \App::setLocale(config('app.fallback_locale')); //in my case it is en
            config(['app.localeDir' => 'ltr']);
        }

By this way, when I create or edit original Status record it will be created in English, and then there is another global controller called TranslationController that performs translation from English to any other supported language.

Gummibeer commented 6 years ago

The model method save(array $options) doesn't accept model data and puts them into fill() method https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L625 It just passes them to protected finishSave() method which just uses the touch key of it. https://github.com/illuminate/database/blob/9e33ce9384043deff1f39654a30ee75199dcac3a/Eloquent/Model.php#L687-L696

And if you get exceptions can you post them here? They will help to debug your issue. At the moment I don't get your problem.

dimsav commented 5 years ago

As announced here, the project has been deprecated. Please use astrotomic/laravel-translatable.