I have a script when user can clip video, then that video uploads to public folder, and now I want to upload all video data to database. But i get error like in title. Here's my code:
Controller:
public function clip($id)
{
$video = Video::where('id', $id)->first();
$oldId = $video->id;
$originalName = $video->original_name;
$newName = str_random(50) . '.' . 'mp4';
FFMpeg::fromDisk('public')
->open('/uploads/videos/' .$video->file_name)
->addFilter(function ($filters) {
$filters->clip(FFMpeg\Coordinate\TimeCode::fromSeconds(5), FFMpeg\Coordinate\TimeCode::fromSeconds(2));
})
->export()
->toDisk('public')
->inFormat(new \FFMpeg\Format\Video\X264)
->save('/uploads/videos/' . $newName);
$data = ['user_id'=>Auth::user()->id,
'file_name'=>$newName,
'original_name'=> $originalName,
'old_id' => $oldId,
];
$video = Video::edit($data);
}
Model:
public static function edit($request)
{
$video = new Video;
$video->user_id = $request->user_id;
$video->file_name = $request->file_name;
$video->original_name = $request->original_name;
$video->save();
$old = $file = Video::where('id', $request->old_id)->delete();
//$old_file = unlink($request->file('file'));
return $video;
}
What should I edit?
Since you're passing array, you need to use $request['user_id'] syntax instead $request->user_id. You're getting the error because you're trying to treat the array as an object.
But since you have prepared array here, just use create method:
public static function edit($data)
{
$this->destroy($data['old_id']);
return $this->create($data);;
}
Don't forget to add $fillable array to your model to make it work.
Related
im using modal bootstrap with codeignitter 4. I can delete the data in database but cannot unlink the image. here my code :
Model :
public function deleteProduct($id)
{
$query = $this->db->table('produk')->delete(array('kode' => $id));
return $query;
}
Controller :
public function delete()
{
$model = new produkModel();
$id = $this->request->getPost('kode');
$produk = $this->produkModel->find($id);
if ($produk['gambar'] != 'default.png') {
unlink('imgproduk/' . $produk['gambar']);
}
$model->deleteProduct($id);
return redirect()->to('/Tabel_Produk');
}
i want to delete the image in directory but dont delete the default.img
Use complete folder path to delete/access image through PHP by using $_SERVER['DOCUMENT_ROOT'] to get server path.
public function delete(){
$model = new produkModel();
$id = $this->request->getPost('kode');
$produk = $this->produkModel->find($id);
if ($produk['gambar'] != 'default.png') {
unlink($_SERVER['DOCUMENT_ROOT'].'/imgproduk/' . $produk['gambar']);
}
$model->deleteProduct($id);
return redirect()->to('/Tabel_Produk');
}
How can I convert Base64 value to Image PNG using intervention image and laravel storage?
public function userLogout(Request $request) {
$data = $request->all();
if ($request->isMethod('post')) {
$poster = explode(";base64", $request->picture);
$image_type = explode("image/", $poster[0]);
$mime_type = '.'.$image_type[1];
$image_base = base64_decode($poster[1]);
$data['picture'] = Storage::disk('player-images')->put($image_base, file_get_contents($poster));
$path = public_path('storage/player-images/'.$image_base);
Image::make($poster)->save($path);
$data['picture'] = 'player-images/' . $image_base;
User::where('name', Auth::user()->name)->update($data);
}
return view('gallery');
}
i got an error message:
"file_get_contents() expects parameter 1 to be a valid path, array given"
and here is my ajax function
var canvas = document.getElementById('canvas');
var dataUrl = canvas.toDataURL('image/png');
$(document).ready(function(){
$('#save').click(function(e){
e.preventDefault();
$.ajax({
headers: {'X-CSRF-TOKEN': $('meta[name="csrf_token"]').attr('content')},
type: "POST",
url: "/gallery",
data: {
picture: dataUrl,
}
}).done(function(o) {
console.log("saved");
});
});
});
How can i save the base64 value to database like player-images/blabla.png and store image to path public/storage/player-images/
sorry, my English is bad.
thanks.
I solved it!. I changed the function in controller like this.
public function userLogout(Request $request)
{
$data = $request->all();
if ($request->isMethod('post')) {
if (preg_match('/^data:image\/(\w+);base64,/', $data['picture'])) {
$value = substr($data['picture'], strpos($data['picture'], ',') + 1);
$value = base64_decode($value);
$imageName = time() . '.png';
$val = Storage::disk('player-images')->put($imageName, $value);
$path = public_path('storage/player-images/'.$imageName);
Image::make($data['picture'])->resize(304, 277)->save($path);
$data['picture'] = 'player-images/' . $imageName;
User::where('name', Auth::user()->name)->update(['picture' => $data['picture']]);
}
}
return view('gallery');
}
I know that probably you solved your doubt, but I was looking for something similar and I didn't find it, so I will leave the following code for someone that may need it.
The goal of this code is to get an image from Pixabay using an URL.
My solution for something similar:
public function store(){
$url = json_decode(request('photo')); //Photo is the field that I fill in the view, that contain a URL to my image in pixabay;
$contents = file_get_contents($url);
$name = substr($url, strrpos($url, '/') + 1);
$blob = base64_encode($this->resizeImage($contents));
Photos::firstOrCreate(['photo' => $name,'thumb' => $blob]); //Photos is my model
}
private function resizeImage($contents) : string {
return (string) Image::make($contents)->resize(75, 75)->encode('data-url'); // Very important this cast to String, without it you can not save correctly the binary in your DB;
}
View:
For use the code in my view I put:
When I return to view the Model I use a 'for' to print all images, like that:
#foreach($photos as $element)
<img src="{{ base64_decode($element->thumb) }}" alt="" >
#endforeach
#Warning
Is very important you have a Blob field in your DB, so in your Schema on Laravel Migrate you have to put something as: $table->binary('thumb');
You can check my code on my git:
lucasfranson10/multisafepay
I basically have this:
foreach ($request->input('images', []) as $imagesData) {
$images = new ScenesImages($imagesData);
$images->product()->associate($product);
$images->save();
}
This saves correctly in my foreign key the name of the image/s but how do I safe the image path dynamicly here.
If I dd($product);
I get this:
> #attributes: array:2 [▼
> "name" => "test"
> "product_id" => 7 ]
but no img(path)
Javascript which creates that html in a loop:
for(var i = 1; i<slider.value; i++) {
$('#sliderAppendSz').append(
'<div class=\"form-group\">'
+'<div class=\"fileinput fileinput-new\" data-provides=\"fileinput\">'
+'<div class=\"input-group\">'
+'<input name=\"images['+i+'][name]\" type=\"text\">'
+'<span class=\"input-group-btn\">'
+'<span class=\"btn btn-primary btn-file\">'
+'<input name=\"images['+i+'][scenes_images]\" type=\"file\" multiple class=\"ImageInput\" accept=\"file_extension/*\">'
+'</span>'
+'</span>'
+'</div>'
+'</div>');
}
And my ScenesImages Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ScenesImages extends Model
{
protected $table = 'scenes_images';
protected $fillable = ['product_id', 'name', 'scenes_images'];
public function product()
{
return $this->belongsTo('App\Product', 'product_id');
}
}
And here my Product Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
public static $projects = 'C:\\xampp\\htdocs\\MyProject\\Web';
protected $table = 'products';
protected $fillable = [
'scenes_images'
];
public static $rules = [
'scenes_images' => 'max:500',
];
public function scenesImages()
{
return $this->hasMany('App\ScenesImages');
}
}
Edit:
OK I think I got it I had to add this as since I only got input before I just added a foreach with a file, my question now is if it is somehow possible to sum the two foreach loops into one like $requesting->file and input.
foreach ($request->file('images', []) as $imagesData) {
$images = new ScenesImages($imagesData);
$images->product()->associate($product);
$images->save();
}
Could be better if you show us more information about the model ScenesImages, otherwise maybe you can have something like this.
foreach ($request->input('images', []) as $imagesData) {
$images = new ScenesImages($imagesData);
$images->product()->associate($product);
$images->path = $your_path
$images->save();
}
Of course you will need the variable $your_path with the path where is saved the images or if it's an url from Amazon S3, but as I said we need maybe more information about your Models structure.
Don't forget upload the image, save it to the server
foreach ($request->input('images', []) as $imagesData)
{
$images = new ScenesImages($imagesData);
$images->product()->associate($product);
$destinationPath = 'uploads'; // upload path
$extension = $imagesData->getClientOriginalExtension(); // getting image extension
$fileName = $imagesData->getClientOriginalName()'.'.$extension; // renameing image
$imagesData->move($destinationPath, $fileName); // uploading file to given path
$images->path = $destinationPath.'/'.$fileName;
$images->save();
}
Couple of issues I'm having with your code:
I'm a bit confused on what $request->file('images') returns. If it's an array of the UploadedFile object then I'm pretty sure you're doing it wrong. You're not even uploading the images to your server, once uploaded that's the file path you want to use when saving your ScenesImages model.
Your code here:
$images = new ScenesImages($imagesData);
is newing up a ScenesImages object and passing it a variable which would need to satisfy the model's required attributes to be created properly, its attributes being: name, scenes_images according to your question code. If you don't it's not going to work properly. You should be passing it an associative array with the keys matching the attributes the model has.
You should usually make your tables plural: scene_images and then your model singular: SceneImage
Consider doing your code like this:
$product = Product::first(); // assume you've defined this already
$uploadedImages = $request->file('images'); // get the images
$destinationPath = storage_path . '/uploads'; // somewhere to put your images
foreach ($uploadedImages as $uploadedImage) {
// upload the image first!
if ($uploadedImage->isValid()) {
$extension = $uploadedImage->getClientOriginalExtension(); // file extension
$uploadedImageName = uniqid(). '.' .$extension; // unique file name with extension
$uploadedImage->move($destinationPath, $uploadedImageName); // move file to our uploads path
// create ScenesImages record in DB
$image = ScenesImages::create([
'name' => $uploadedImageName, // assuming this is your file path?
'scenes_images' => '' // assign something here, not sure what it's supposed to be?
]);
// associate product
$image->product()->associate($product);
} else {
// handle error here
}
}
I've been using Dropzone for several days and I faced some issues. The idea is: the user selects his file, it uploads and goes in his file directory and some of the file's properties (size, name) go in the DB. I can't do it because when the user uploads the file, the page does not refresh and nothing goes in Input::file('file'). I just can't do it. Here is the code i'm using:
class UploadController extends Controller {
public function upload() {
if(Input::hasFile('file')){
$file = Input::file('file');
$user = Auth::id();
$file->move('uploads/'.$user, $file->getClientOriginalName());
}
else {
echo 'Please select a file first';
}
}
Here are the two functions in File.php model
public function getFileId(){
$fileName = Input::file('file')->getClientOriginalName();
$files = File::where('filename', $fileName)->get(); //$fileName
foreach ($files as $file) {
$fileid = $file->fileid;
echo $fileid.'<br>';
Input::file('file')->fileid = $file->fileid; // put fileid as an attribute to the object file for futher usage
}
}
public function incrementFileId(){
$files = File::orderBy('fileid', 'desc')->take(1)->get();
foreach($files as $file){
echo $file->fileid + 1 .' incremented file id<br>';
}
}
So how should my third model function look like to upload the file's properties? DropZone uses Ajax and I though that I should get the file attributes from there but could this be done?!
Use Request instead of Input:
public function upload(Request $request)
{
if ($request->hasFile('file'))
{
$file = $request->file('file');
$file->move('uploads/'.$user, $file->getClientOriginalName());
}
Below example of 'store' method of my controller Admin/MoviesController. It already seems quite big, and 'update' method will be even bigger.
The algoritm is:
Validate request data in CreateMovieRequest and create new movie
with all fillable fields.
Upload poster
Fill and save all important, but not required fields (Meta title, Meta Description..)
Then 4 blocks of code with parsing and attaching to movie of Genres, Actors, Directors, Countries.
Request of IMDB's rating using third-party API
My questions:
Should I just move all this code to Model and divide it into smaller methods like: removeGenres($id), addGenres(Request $request), ...
Are there some best practices? I'm talking not about MVC, but Laravel's features. At the moment to keep some logic behind the scene I'm using only Request for validation.
public function store(CreateMovieRequest $request) {
$movie = Movies::create($request->except('poster'));
/* Uploading poster */
if ($request->hasFile('poster')) {
$poster = \Image::make($request->file('poster'));
$poster->fit(250, 360, function ($constraint) {
$constraint->upsize();
});
$path = storage_path() . '/images/movies/'.$movie->id.'/';
if(! \File::exists($path)) {
\File::makeDirectory($path);
}
$filename = time() . '.' . $request->file('poster')->getClientOriginalExtension();
$poster->save($path . $filename);
$movie->poster = $filename;
}
/* If 'Meta Title' is empty, then fill it with the name of the movie */
if ( empty($movie->seo_title) ) {
$movie->seo_title = $movie->title;
}
/* If 'Meta Description' is empty, then fill it with the description of the movie */
if ( empty($movie->seo_description) ) {
$movie->seo_description = $movie->description;
}
// Apply all changes
$movie->save();
/* Parsing comma separated string of genres
* and attaching them to movie */
if (!empty($request->input('genres'))) {
$genres = explode(',', $request->input('genres'));
foreach($genres as $item) {
$name = mb_strtolower(trim($item), 'UTF-8');
$genre = Genre::where('name', $name)->first();
/* If such genre doesn't exists in 'genres' table
* then we create a new one */
if ( empty($genre) ) {
$genre = new Genre();
$genre->fill(['name' => $name])->save();
}
$movie->genres()->attach($genre->id);
}
}
/* Parsing comma separated string of countries
* and attaching them to movie */
if (!empty($request->input('countries'))) {
$countries = explode(',', $request->input('countries'));
foreach($countries as $item) {
$name = mb_strtolower(trim($item), 'UTF-8');
$country = Country::where('name', $name)->first();
if ( empty($country) ) {
$country = new Country();
$country->fill(['name' => $name])->save();
}
$movie->countries()->attach($country->id);
}
}
/* Parsing comma separated string of directors
* and attaching them to movie */
if (!empty($request->input('directors'))) {
$directors = explode(',', $request->input('directors'));
foreach($directors as $item) {
$name = mb_strtolower(trim($item), 'UTF-8');
// Actors and Directors stored in the same table 'actors'
$director = Actor::where('fullname', trim($name))->first();
if ( empty($director) ) {
$director = new Actor();
$director->fill(['fullname' => $name])->save();
}
// Save this relation to 'movie_director' table
$movie->directors()->attach($director->id);
}
}
/* Parsing comma separated string of actors
* and attaching them to movie */
if (!empty($request->input('actors'))) {
$actors = explode(',', $request->input('actors'));
foreach($actors as $item) {
$name = mb_strtolower(trim($item), 'UTF-8');
$actor = Actor::where('fullname', $name)->first();
if ( empty($actor) ) {
$actor = new Actor();
$actor->fill(['fullname' => $name])->save();
}
// Save this relation to 'movie_actor' table
$movie->actors()->attach($actor->id);
}
}
// Updating IMDB and Kinopoisk ratings
if (!empty($movie->kinopoisk_id)) {
$content = Curl::get('http://rating.kinopoisk.ru/'.$movie->kinopoisk_id.'.xml');
$xml = new \SimpleXMLElement($content[0]->getContent());
$movie->rating_kinopoisk = (double) $xml->kp_rating;
$movie->rating_imdb = (double) $xml->imdb_rating;
$movie->num_votes_kinopoisk = (int) $xml->kp_rating['num_vote'];
$movie->num_votes_imdb = (int) $xml->imdb_rating['num_vote'];
$movie->save();
}
return redirect('/admin/movies');
}
You need to think on how you could re-utilize the code if you need to use it in another classes or project modules. For starting, you could do something like this:
Movie model, can improved in order to:
Manage the way on how the attributes are setted
Create nice functions in functions include/manage the data of relationships
Take a look how the Movie implements the functions:
class Movie{
public function __construct(){
//If 'Meta Title' is empty, then fill it with the name of the movie
$this->seo_title = empty($movie->seo_title)
? $movie->title
: $otherValue;
//If 'Meta Description' is empty,
//then fill it with the description of the movie
$movie->seo_description = empty($movie->seo_description)
? $movie->description
: $anotherValue;
$this->updateKinopoisk();
}
/*
* Parsing comma separated string of countries and attaching them to movie
*/
public function attachCountries($countries){
foreach($countries as $item) {
$name = mb_strtolower(trim($item), 'UTF-8');
$country = Country::where('name', $name)->first();
if ( empty($country) ) {
$country = new Country();
$country->fill(['name' => $name])->save();
}
$movie->countries()->attach($country->id);
}
}
/*
* Update Kinopoisk information
*/
public function updateKinopoisk(){}
/*
* Directors
*/
public function attachDirectors($directors){ ... }
/*
* Actores
*/
public function attachActors($actors){ ... }
/*
* Genders
*/
public function attachActors($actors){ ... }
}
Poster, you may considere using a service provider (I will show this example because I do not know your Poster model
looks like):
public class PosterManager{
public static function upload($file, $movie){
$poster = \Image::make($file);
$poster->fit(250, 360, function ($constraint) {
$constraint->upsize();
});
$path = config('app.images') . $movie->id.'/';
if(! \File::exists($path)) {
\File::makeDirectory($path);
}
$filename = time() . '.' . $file->getClientOriginalExtension();
$poster->save($path . $filename);
return $poster;
}
}
Config file
Try using config files to store relevant application constanst/data, for example, to store movie images path:
'images' => storage_path() . '/images/movies/';
Now, you are able to call $path = config('app.images'); globally. If you need to change the path only setting the config file is necessary.
Controllers as injected class.
Finally, the controller is used as a class where you only need to inject code:
public function store(CreateMovieRequest $request) {
$movie = Movies::create($request->except('poster'));
/* Uploading poster */
if ($request->hasFile('poster')) {
$file = $request->file('poster');
$poster = \PosterManager::upload($file, $movie);
$movie->poster = $poster->filename;
}
if (!empty($request->input('genres'))) {
$genres = explode(',', $request->input('genres'));
$movie->attachGenders($genders);
}
// movie->attachDirectors();
// movie->attachCountries();
// Apply all changes
$movie->save();
return redirect('/admin/movies');
}