I am working on a project for ads/properties in Laravel. I have gallery of multiple videos for each individual ad. I want to be able to select one of those videos with radio button and make it primary video for that ad (show that particular video next to ad). I have has many relationship between property and video and I am trying to insert id of video from videos table to main_video_id column in properties table and also when I change current video for new one to update that foreign key accordingly. I am having trouble to write that method in my controller. Any help is appreciated. Here are my tables and code.
properties (id, title, location, price, main_video_id)
videos (id, filename_video, model_id)
In videos table model_id column is foreign key that connects to properties table.
PropertyController.php
public function edit(Property $property, Request $request)
{
if (!($property->user_id == Auth::user()->id)) {
abort(404);
}
$category = $property->category;
foreach ($property->photos as $value) {
$photoarray[] = $value->filename;
};
empty($photoarray) ? $photo = '' : $photo = implode(",", $photoarray);
foreach ($property->videos as $value1) {
$videoArray[] = $value1->filename_video;
};
empty($videoArray) ? $video = '' : $video = implode(",", $videoArray);
$data = .... Here I am having trouble writing method!
return view('property.edit', compact(
'category',
'photo',
'property',
'video',
'data'
));
}
edit.blade.php
<form id="form" action="/property/{{$property->id}}" method="POST" enctype="multipart/form-data">
<input type="hidden" id="hideninput" data-src="property/{{$property->id}}/gallery"value="{{old('video',$video)}}" name="video">
#if (old('video', $video))
#foreach (array_filter(explode(',',old('video', $video)), 'strlen') as $key =>$value)
<div id="{{'div_video_'.$key}}" class="col-md-3" style="padding: 15px;">
#foreach ($data as $key => $value)
<input type="radio" name="radio" value="{{ $value->video_id }}">Make main
#endforeach
<button data="{{$key}}" type="button" class="closebuttonvideo">
<span aria-hidden="true">×</span>
</button>
<video id="{{'video_'.$key}}" data={{$value}} src="/storage/property/{{$property->id}}/gallery/{{$value}}" class="video-js vjs-default-skin" controls preload="auto" data-setup='{"inactivityTimeout": 0}' width="180" height="180">
</video>
</div>
#endforeach
#endif
Property.php
public function videos()
{
return $this->hasMany(Video::class, 'model_id');
}
Video.php
public function properties()
{
return $this->belongsTo(Property::class);
}
Instead of having main_video_id in the properties table, I would go with the following approach:
Add a column is_main_video to videos table and a composite unique constraint as below:
$table->boolean('is_main_video')->nullable()->default(null);
$table->unique(['model_id', 'is_main_video']);
The unique constraint ensures that there are no multiple main videos for a single property.
In Property.php
protected $appends = ['mainVideo'];
public function videos()
{
return $this->hasMany(Video::class, 'model_id');
}
public function getMainVideoAttribute()
{
return $this->videos->first(function($video) {
return $video->is_main_vide;
});
}
Now when you fetch properties, you'll automatically get the mainVideo and related videos as a result as show below:
array:4 [
"id" => 1
"name" => "property 1"
"mainVideo" => array:4 [
"id" => 2
"model_id" => 1
"is_main_video" => 1
"name" => "Video 2"
]
"videos" => array:2 [
0 => array:4 [
"id" => 1
"model_id" => 1
"is_main_video" => null
"name" => "Video 1"
]
1 => array:4 [
"id" => 2
"model_id" => 1
"is_main_video" => 1
"name" => "Video 2"
]
]
]
Hope it helps!
Related
In my Laravel-5.8 application, I have this code:
Controller
$data = AppraisalGoalType::create([
'name' => $request->name,
'parent_id' => $request->parent_id,
'max_score' => $request->max_score,
'company_id' => Auth::user()->company_id,
]);
$data1 = DB::table('appraisal_goal_types')
->select('max_score')
->where('id', $request->parent_id)
->whereNull('parent_id')
->first();
if (!empty($request->max_score)) {
$data->update(['max_score1' => $data1->max_score]);
} else {
$data->update(['max_score1' => 0]);
}
View
<div class="form-group">
<label class="control-label"> Max. Score:</label>
<input type="number" name="max_score" class="form-control" value="{{ old('max_score') }}" step="0.01" placeholder="Enter maximum weight here: 15, 50, 75 etc" style="width: 100%;">
</div>
When I tried to insert into the database, I got this error:
ErrorException: Trying to get property 'max_score' of non-object
I dd($data); and got:
#original: array:12 [▼
"name" => "dxxddxdx"
"parent_id" => null
"max_score" => "56"
"company_id" =>
and dd($data1); gives null which is true. I already have a conditional statement.
I see that it has "max_score" => "56"
Why the error and how do I resolve it?
your select statement not correct , you trying to select first row where id = parent_id and the parent_id = null so this is always return null because id column in auto increment and the parent id is number you get it from request . and in your case parent id equal null , you compare value that auto increment with null value that return null . that mean your condition not correct .
try to fix the select statement.
i dont know your business , but i think try to change this condition
->where('id', $request->parent_id) to be
->where('parent_id', $request->parent_id)
Im not sure if the question title is correct but what I wanna do is clear in the example below
I have 3 arrays and I want to store data in one table
the table structure is like this
table name: tour_transports
id
transport_id
transport_track
transport_note
arrays coming from blade
"transport_id" => array:2 [
1 => "1"
5 => "5"
]
"transport_track" => array:3 [
1 => " from airport to the hotel"
3 => null
5 => " be ready at 4:pm"
]
"transport_note" => array:3 [
1 => "from hotel to the beach"
3 => null
5 => " bring ur swiming suite"
]
so as you see the ids are 1 and 5 so I wanna store two rows here
id = 1,transport_id = 1 , transport_track = from airport to the hotel , transport_note = be ready at 4:pm
id = 2,transport_id = 5, transport_track = from hotel to the beach , transport_note = bring ur swiming suite
I tried to do this but can't get it correct
if(!empty($request->transport_id))
{
foreach ($request->transport_id as $key => $transport_id) {
foreach ($request->transport_track as $key => $track) {
foreach ($request->transport_note as $key => $transport_note) {
TourTransport::create([
'transport_id' =>$transport_id,
'transport_track' =>$track[$transport_id],
'transport_note' =>$transport_note[$transport_id]
]);
}
}
}
}
You can use this code to achieve your results:
$data = $request->only('transport_id', 'transport_track', 'transport_note');
foreach ($data['transport_id'] as $key => $transportId) {
TourTransport::create([
'transport_id' => $transportId,
'transport_track' => $data['transport_track'][$key],
'transport_note' => $data['transport_note'][$key],
]);
}
Now $results contains the required data. However the better solution might be to configure your html form to send related data in single array entry, Like:
<input type="text" name="transports[0][transport_id]">
<input type="text" name="transports[0][transport_track]">
<input type="text" name="transports[0][transport_note]">
<input type="text" name="transports[1][transport_id]">
<input type="text" name="transports[1][transport_track]">
<input type="text" name="transports[1][transport_note]">
Which you can also use Javascript/php loops to generate the form inputs. Then you will receive form data in server side in well formed structure like:
"transports" => array:2 [
[
'transport_id' => 1,
'transport_track' => 'from airport to the hotel',
'transport_note' => 'be ready at 4:pm',
],
[
'transport_id' => 5,
'transport_track' => 'from hotel to the beach',
'transport_note' => ' bring ur swiming suite',
],
]
i want to create a shop site by laravel.
i want to create cart page and cart page showing all product that user want to shop it.
i create a session for every product that user want to shop.
i have some session in laravel like this
$_SESSION[cart_133] = [
'product' => 'test1',
'quantity' => '3',
'price' => '30'
];
$_SESSION[cart_30] = [
'product' => 'test2',
'quantity' => '1',
'price' => '50'
];
$_SESSION[cart_65] = [
'product' => 'test3',
'quantity' => '10',
'price' => '653',
];
and i wan to showing them like this
<p>test1</p>
<p>3</p>
<p>30</p>
<hr>
<p>test2</p>
<p>1</p>
<p>50</p>
<hr>
<p>test3</p>
<p>10</p>
<p>653</p>
<hr>
<hr>
<p>all price 733</p>
If you want to do it Laravel way, you have to define relations.
Category Model (each category might have some products)
public function products()
{
return $this->hasMany('App\Product');
}
Product model (each product belongs to some category)
public function category()
{
return $this->belongsTo('App\Category');
}
Then when you want to get categories with their products, you can use Eager Loading.
Controller:
$categories = Category::with('products')->get();
View:
#foreach ($categories as $cat)
#foreach ($cat->products as $product)
<!-- product data -->
#endforeach
#endforeach
you can use call all session an use substr function to limit one suffix.
you can use this
$x = [];
foreach(Session::all() as $name => $val){
if(substr($name , 0 , 5 ) == "cart_"){
$x[$name] = $val;
}
}
echo '<pre>';
print_r($x;);
I have a classified with categories. My classified can have one or several categories:
/**
* #ORM\OneToMany(targetEntity="Category", mappedBy="classified", cascade={"persist"}, orphanRemoval=true)
*/
protected $categories;
An important thing to know is that my Category entity has composite primary keys : the ID of the category, and the classified.
I want to populate categories into my classified with a choices field:
$builder->add(
$builder->create('categories', ChoiceType::class, [
'choices' => [
'Category 1' => 1,
'Category 2' => 2,
'Category 3' => 3,
'Category 4' => 4,
],
'multiple' => true,
])->addModelTransformer(new CallbackTransformer(
// Transform collection of entities into an array of IDs
function($categories) {
if (!$categories) {
return [];
}
return $categories->map(function(Category $category) {
return $category->getId();
})->toArray();
},
// Reverse transform IDs array from request to a collection of entities
function($categories) {
$items = [];
if ($categories && is_array($categories)) {
foreach ($categories as $id) {
$items[] = new Category($id);
}
}
return $items;
}
))
);
As you can see I have a transformer to convert the categories collection to a list of ID, and vice versa.
Everything is fine during the creation of my classified, but edition is bugged.
My problem is that when I submit the form, I have duplicate entries issues:
An exception occurred while executing 'INSERT INTO tv_classified_category (id, classified_id) VALUES (?, ?)' with params [4, 1]:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '4-1' for key 'PRIMARY'
Here is what I found when I dump the list of categories before and after handleRequest:
dump($classified->getCategories()->toArray());
$form->handleRequest($request);
if ($form->isValid()) {
dump($classified->getCategories()->toArray());
Debug result:
array:2 [▼
0 => Category {#1036 ▶}
1 => Category {#1038 ▶}
]
array:3 [▼
2 => Category {#4108 ▶}
3 => Category {#4110 ▶}
]
As you can see, there is a strange mismatch between keys, and the PHP ids of objects are differents before and after the handleRequest call. What is wrong and how can I fix this?
Regards,
So I found that the problem is that when an item is removed then added again in the collection, it causes a duplicate entry because Doctrine performs inserts before deletions.
To fix my problem, I need to make sure that same Category objects are used if my categories already in the classified. The only way I found to do this is some uggly code that will probably be broken one day. I hope anybody will find a better way to do this than the code bellow.
// Add the listener on the categories field (a ChoiceType field)
->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
$form = $event->getForm();
$categories = $form->getData();
$classified = $form->getParent()->getData();
$classifiedCategories = [];
foreach ($classified->getCategories() as $classifiedCategory) {
$classifiedCategories[$classifiedCategory->getId()] = $classifiedCategory;
}
$modelData = new ArrayCollection();
foreach ($categories as $category) {
$modelData->add($classifiedCategories[$category->getId()] ?? $category);
}
// This is uggly, don't reproduce this at home kids :)
$refProperty = new \ReflectionProperty($form, 'modelData');
$refProperty->setAccessible(true);
$refProperty->setValue($form, $modelData);
})
I need to do this stuff in POST_SUBMIT (and use Reflection) because in SUBMIT I only get the flat view data and not the ArrayCollection.
This piece of code should be deleting all old data from the database and when add the new ones (using sync())
Now I have a project with users, and a user can be linked to a project with a checkbox.
So on checkbox checked this function will trigger, but for example when I say that user 1 and user 2 are going through this fuction to get added to the pivot table it will only send user 2, and user 1 will not get through, what is going wrong?
And when I add 3 users user 1, user 2, user 3, only user 2 will get added.
Controller
public function update(CreateProjectRequest $request)
{
if($request->get('contribute'))
{
foreach($request->get('contribute') as $k => $contribute)
{
if($contribute == 1)
{
$project = $this->project->find($request->project_id);
$project->users()->sync(array($k));
}
}
}
$project = $this->project->find($request->project_id);
$project->fill($request->input())->save();
return redirect('project');
}
Blade
#foreach($users as $user)
<tr>
<td>
{{$user->firstname}} {{$user->middlename}} {{$user->lastname}}
</td>
<td>
{!! Form::checkbox('contribute['.$user->id.']', '1', $user->projects->contains('id', $project->id)) !!}
</td>
</tr>
#endforeach
On a dd($request->input()); at the start of my update method (with selecting atleast 3 users) this will get in return:
array:9 [▼
"_method" => "PATCH"
"_token" => "0uIZNn6zwZjVKfgE0ckhDULeYda0OaLzKVdUgoM8"
"name" => "Dire Straits"
"completion_date" => "2015-05-18"
"DataTables_Table_0_length" => "10"
"contribute" => array:3 [▼
1 => "1"
3 => "1"
2 => "1"
]
"completed" => "1"
"active" => "0"
"project_id" => "11"
]
So 1 / 3 / 2 would be the user_id and => 1 should be the value.
The problem is that sync gets called in loop 3 times so each time it's syncing one value. You have to pass an array of the ids in sync ex:
$project->users()->sync([1,3,2]);
Or if you want you can use attach when contribute==1 and detach when contribute==0
Or if contribute doesnt return input when a user is deselected and it only returns when it is selected then you can try:
$this->project->users()->sync(array_keys($request->get('contribute'));
I just noticed that you have another bug unless you are updating many projects with one call you should put the line below on the first line of your function.
$project = $this->project->find($request->project_id);