Laravel custom attribute in Model for Scaling image using Cloudinary URL - php

In my web app I am using Cloudinary for image storing. Image uploading is working properly but i want to create a custom attribute for image so when getting back the image url from the database with some modification with width and height.
The link of a image: https://res.cloudinary.com/wokong/image/upload/v1568570430/storyHeader/cxjir4g9tkaa8xepxodg.jpg
which is stored in database but when it fetch from the database, It should come with some scaling so that It wont take much time for website loading.
here is my StoryModel:
class Story extends Model
{
use Commentable, Searchable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'title',
'summary',
'content',
'created_at',
'story_statuses_id',
'image', 'language',
'likes',
'views',
'url_key',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'is_public' => 'boolean',
];
I dont understand how to use it anyone can help?

Cloudinary supports runtime image resizing
As per their documentation instead of this
https://res.cloudinary.com/wokong/image/upload/v1568570430/storyHeader/cxjir4g9tkaa8xepxodg.jpg
use
https://res.cloudinary.com/wokong/image/upload/w_100,h_100,c_fit/v1568570430/storyHeader/cxjir4g9tkaa8xepxodg.jpg
As you can see, i have added /w_100,h_100,c_fit/ after upload to instruct Cloudinary to do the resizing on the fly
w is for width, h is for height and c is for scale type to be used while cropping
You can find the documentation here
UPDATE 1
Something like this should do it
$default_url = "https://res.cloudinary.com/wokong/image/upload/v1568570430/storyHeader/cxjir4g9tkaa8xepxodg.jpg";
$width = 100;
$height = 100;
echo str_replace("/upload", "/upload/w_".$width.",h_".$height.",c_fit", $default_url);
UPDATE 2
Your model will look like
class Story extends Model
{
use Commentable, Searchable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'title',
'summary',
'content',
'created_at',
'story_statuses_id',
'image', 'language',
'likes',
'views',
'url_key',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'is_public' => 'boolean',
];
public function getImageForWebAttribute()
{
$width = 100; // You can keep this info in app config
$height = 100;
// Here i am assuming `image` is where you store Cloudinary url
return str_replace("/upload", "/upload/w_".$width.",h_".$height.",c_fit", $this->image);
}
}
and you can call it like
$story->image_for_web
Documentation for laravel custom mutators can be found here

Instead of saving the whole URL of the uploaded image in your database, you can save the public_id returned in the upload response.
Then you can just use Cloudinary's SDK to generate the transformation URLs for you, by passing the desired transformation parameters to the cloudinary_url() Helper function, along with the image's public_id.
For example, let's assume that you want to generate a URL of an image which its public_id is sample. In addition, you want that the image will be delivered with the best format possible, based on the client's device and browser. You would also like to use Cloudinary's automatic quality algorithm and scale the image down to a width of 500px while retaining its original aspect ratio.
You can achieve it by using the following code:
$url = cloudinary_url('sample', array(
'fetch_format' => 'auto',
'quality' => 'auto',
'crop' => 'scale',
'width' => 500
));
echo $url; will print the following:
http://res.cloudinary.com/<cloud_name>/image/upload/c_scale,f_auto,q_auto,w_500/sample
If you wish to generate the whole <img> tag using the SDK, you can utilize cl_image_tag() as an alternative to the URL only output of cloudinary_url().
Here's the link to the relevant section in Cloudinary's documentation with some more examples on how to use both cl_image_tag() and cloudinary_url().

Okay just an additional help for ...
Say for instance you attached $images to a view from the controller in laravel
you could generate fixed width and height on the fly via the url and attach to bootstrap grid system..
`
<div class="col-6 col-md-4 col-lg-3">
<a href="{{$image->image_url}}">
#php
$url = $image->image_url;
#endphp
<img class="img img-fluid" src="{{ str_replace("/upload", "/upload/w_350,h_220,q_70,c_scale", $url) }}" alt="">
</a>
</div>
`
You could also set this attributes of the image via the controller method using
Cloudder::show(Cloudder::getPublicId(), ["width" => $width, "height"=>$height])

Related

Why the path of file image is not inserted into database MySQL in Laravel?

I'm learning Laravel right now on Laravel From Scratch 2022 by Traversy Media (Youtube). I want to create a file upload function for new listing form. When I tried to upload, the image was uploaded into the right path in public storage but the path is not in the database, instead the value inserted is 0.
Here is the code for ListingController.php
// Store Listing Data
public function store(Request $request) {
$formFields = $request->validate([
'title' => 'required',
'company' => ['required', Rule::unique('listings','company')],
'location' => 'required',
'website' => 'required',
'email' => ['required', 'email'],
'tags' => 'required',
'description' => 'required'
]);
$directory = "logos";
if($request->hasFile('logo')) {
$formFields['logo'] = $request->file('logo')->store('logos','public');
}
Listing::create($formFields);
return redirect('/')->with('message', 'Listing created successfully!');
}
Here is the screenshot of image that I successfully uploaded but the value in database is 0.
Screenshot of Laravel storage/app/public/logos directory
Screenshot of MySQL database, column logo is used to store image path
Thank you for your help!
In my case since he used protected $fillable in Models. I added logo this resolved my issue. See the code below.
protected $fillable = ['title', 'logo','company', 'location', 'website', 'email', 'description', 'tags'];
What Eric commented worked for me as well, in the Models file under Http, you have to add whatever name that you used for the logo ('logo', 'image', 'picture' etc.), since in the course he uses protected $fillable.
I tested it, and your code is fine. probably it might be related to the type of logo column in your database. make sure it's "Varchar" and not "Boolean".
you could use: var_dump($request->file('logo')->store('logos','public'));
to see if the path of image showed up or not. if not, try use storeAs()
instead of store() .
$request->file('logo')->storeAs('public' , "logo.jpg");
in this alternative code, you can set a proper name for your image as a second parameter and save it in the database.
It seems $request->file('logo')->store('logos','public') doesn't return the file name or path.
Considering that, it might be better to assign a custom file name. In the example below, we use the name of the original uploaded file.
$fileName = $request->file('logo')->getClientOriginalName();
$request->file('logo')->storeAs('logos', $fileName);
$formFields['logo'] = $fileName;
Source: https://blog.quickadminpanel.com/file-upload-in-laravel-the-ultimate-guide/
Are you using "protected $fillable =..." in your model file? If so, you need to add 'logo' to the array.
(I'm doing the course and got stuck at the same part.)

Output an image and videos stored in a folder while the path is in the database in yii2

Am creating a court management system whereby a person should be able to view images and videos pertaining to a certain case
I have two related tables that is case and evidence tables
RELATIONSHIPS
Evidence model code:
public function getCaseRef()
{
return $this->hasOne(Cases::className(), ['ref_no' => 'case_ref']);
}
public function rules()
{
return [
[['case_ref', 'saved_by', 'saved_on', 'evidence_type'], 'required'],
[['saved_on'], 'safe'],
[['path'], 'safe'],
[['case_ref', 'saved_by'], 'string', 'max' => 100],
[['evidence_type'], 'string', 'max' => 50],
[['path'], 'file']
];
}
Case model code:
public function getEvidences()
{
return $this->hasMany(Evidence::className(), ['case_ref' => 'ref_no']);
}
Uploading works well and I save the evidence with the case reference no. The path in the evidence model is where I save the path to where the image is uploaded to.
In the action view of the cases controller
public function actionView($id)
{
$evidence = new Evidence();
return $this->render('view', [
'model' => $this->findModel($id),
'id'=>$id,'evidence'=>$evidence,
]);
}
How do I put my view model so that it displays the images/videos/pdf files stored in a folder (corresponding to an id i.e $id passed during the click using the path stored in the database evidence table
if the folder is in the var myFolder and the filename in the var myFilename in your model you can easly use it your view for image and video adding the proer value to the related attribut
echo "<img src='". $model->myFolder . $model->myFilename . "' >";
echo " <video width='320' height='240' controls>
<source src='" . $model->myFolder . $model->myFilename ."'type='video/mp4'>
Your browser does not support the video tag.
</video> "
for pdf you should use a proper extension like mpdf or if you mime is correctly setted a simple link build with the same rules
If you have plenty of evidence connected to the case evidence, this evidence will be made available in an object with many instances or in related details with many istance. To handle this situation is sufficient that you make a foreach loop on these istances (submodels or sub object) and for each one produces the echo as suggested in the first part of the answer.

How to Download Images from new RETS CRMLS

I am trying to download images from new RETS CRMLS
$photos = $rets->SearchQuery("Media","Media",$lid, array('Limit' => 'none', 'Select' => "MediaOrder,MediaURL"));
foreach ($photos as $photo)
{
if ($photo['Success'] == true)
{
file_put_contents("../images/{$photo['Content-ID']}-{$photo['Object-ID']}.jpg", $photo['Data']);
$count++;
}
}
this is not working
If you want to download the images from the Property class, you can use this rets function
$rets->GetObject("Property", "Photo", $listingId, "*", 1);
This will return the array of images associated with the particular listingId as image url.
If you want to download as binary image files then you can use the last parameter as '0', instead of '1'. [ '1' is for getting public image Urls]
If the image is to be downloaded from the Media class then you can use the same function with Media as the class. And you should first get the listing Id from the Property class.
Your "file_put_contents" function appears to be attempting to parse the info headers within a multipart/mime response from a GetObject query. Rather, you'd want to do a straight http download of the MediaUrls. I'm not a php wizard, but you'd do something more like:
$photoUrls = $rets->SearchQuery("Media","Media",$lid, array('Limit' => 'none', 'Select' => "MediaOrder,MediaURL"));
while ($photo = $rets->FetchRow($photoUrls)) {
file_put_contents("../images/{$lid}-{$photo['MediaOrder']}.jpg", file_get_contents($photo['MediaURL']));
}
$rets->FreeResult($photoUrls);
Also, you probably want to limit your search to MediaTypes of "Image" so you don't get other binary data or documents, like virtual tour URLs or PDFs (see google group for this MLS that you also posted within).

Changing default pagination in Yii to 50

Working with yii framework and was wondering if there was a way of changing the default pagination. Currently it's at 10 elements, and I would like to make it 50.
You can set pagination by
$dataProvider = new CActiveDataProvider('model name',
array('pagination' => array(
'pageSize' => 50,
),
)
);
CPagination->$pageSize Number of items in each page. http://www.yiiframework.com/doc/api/CPagination#pageSize-detail
In yii/framework/web/CPagination.php, change
const DEFAULT_PAGE_SIZE=20;
/**
* #var string name of the GET variable storing the current page index. Defaults to 'page'.
*/
to
const DEFAULT_PAGE_SIZE=50;
/**
* #var string name of the GET variable storing the current page index. Defaults to 'page'.
*/
This will adjust the page, and pagination accordingly.

Yii booster TbImageColumn - setting Image attributes

Is there any way to add other attributes to the image tag generated by TbImageColoumn ?
The documentation is not very clear on how to set image attributes like height, width etc. It only mentions on how to add image src using imagePathExpression attribute,
My current column looks like this
.....
array(
'class'=>'bootstrap.widgets.TbImageColumn',
'imagePathExpression'=>'$data->getImage("large")',
'usePlaceKitten'=>false,
),
.....
Digging through the code it seems there is an attribute for setting html attributes to the generated tag using the imageOptions and to set attributes on generated td cell tag we can use the htmlOptions array from the base clase
/**
* TbImageColumn widget class
*
* #package booster.widgets.grids.columns
*/
class TbImageColumn extends CGridColumn
{
/**
* #var array the HTML options of the image tag
*/
public $imageOptions = array();
so to limit image width to 50px the column should be modified to
.....
array(
'class'=>'bootstrap.widgets.TbImageColumn',
'imagePathExpression'=>'$data->getImage("large")',
'headerHtmlOptions'=>array('style'=>'min-width: 50px;'),
'imageOptions'=>array('width'=>'50px'),
'usePlaceKitten'=>false,
),
.....

Categories