[laravel] Eloquent collection 결과가 비었는지(empty) 확인

2015. 3. 23. 13:16 from Dev/php

Eloquent collection으로 작업하다 보면 항상 헷갈리는 부분이 있습니다. 바로 Eloquent model을 이용하는 collection을 불러왔을 때 결과가 비었는지 아닌지 하는 것입니다.

가령 블로그를 만들면서 특정한 $tag을 가지는 포스트들을 아래와 같이 가져오면..

$posts = Post::where('tag', $tag)->get();

 

결과값이 있는지를 봐야겠지요.. 무의식적으로 아래와 같이 빈 결과인지 아닌지를 체크한다고 해놓고 지나가면 나중에 뭐가 문제인지 모르는 경우가 생깁니다:

if (empty($posts)) { }

if (!$posts) { }

if (isset($posts) { }

 

 

이럴 때에는 아래처럼 해주시면 됩니다:

if ($result->isEmpty()) { }

if ($result->count()) { }

 

 

 

 

Posted by banasun :

[php] mime type 알아내는 방법 - PHP version < 5.3 일 경우 꼼수

2015. 3. 16. 17:31 from Dev/php

파일을 업로드 전송받는 경우 파일 MIME type을 결정해주어야 하는 경우가 종종 생깁니다.

오늘은 이미지를 데이터베이스에 blob으로 넣는 작업을 하면서 클라이언트 요청으로 MIME TYPE도 같이 저장해주도록 하였습니다.

시작하면서는 Fileinfo function이 있으니 별거 아니겠네.. 하였는데 역시나 제가 하는 일은 쉽게 끝나는 법이 없군요. OTL

일단 서버 PHP 버전이 5.2라 Fileinfo 가 이용 불가능한 상태였고, mime_content_type 함수는 depreciated 입니다.

요새 제 프로젝트의 프레임워크로 이용하는 laravel에는 mime type을 guessing하는 부분이 있긴 한데..

오늘은 할 수 없이 업로드되는 파일 확장명을 기반으로 mime type을 리턴해주는 함수를 구글링해서 이용하였습니다:

http://www.brightcherry.co.uk/scribbles/php-alternative-to-the-depreciated-mime_content_type-function-and-fileinfo-functions/

물론 이 방식은 이용자가 전송하는 파일의 확장명을 의심없이(?) 받아들여서 처리하기 때문에 보안상 문제의 여지는 있습니다.

이런 문제를 해결해주는 것이 맞는 것이긴 한데.. 성격상 서버 PHP 버전만 업그레이드 해주면 되는 문제를 굳이 시간을 들여가면서 하고 싶진 않기도 하고.. 어차피 DB에 있으니 보안상 문제는 그나마 조금 덜하니 차라리 DB에서 꺼내주는 과정만 신경을 써주면 되겠구나 하면서 마무리하였습니다.

Posted by banasun :

[php] array_unique의 결과값을 json_encode 로 변환시 복불복에 대해서

2015. 2. 14. 05:24 from Dev/php

php라는 언어 자체가 상당히 헐렁(loose. 비하는 아님)한 언어이기 때문에 편하기도 하지만, 가끔 가다가는 결과값이 어떻게 올지 불확실할 수 있다는 점 또한 받아들여야 하는데.. 삽질 열심히 하다 원인을 알게 되면 너무 허무합니다.

오늘의 삽질은.. 처음에 손대면서는 30분이면 되겠지 하고 시작한 처음은 미미하였던 일이.. 시간이 지나면서 해결도 안되고 점점 창대해지는 사태를 거치는 상황이었습니다.

요는. array_unique를 써서 array 내의 중복값을 없앤 다음에 json_encode로 다른 app에 넘겨주면 끝나는 일이었습니다.

뭐 간단하네. 요거만 하고 자야지 했는데 이게 왠걸;; 어디서 났는지 모를 에러들이..

원인을 찾아보니 array_unique로 정리를 할 때, 그냥 예쁘게 이렇게 되는 걸 바랬는데 :

['Series A', 'Series B']


가끔 가다 그렇게 안되고 이렇게 되고 마는 것입니다.

[{"0":"'Series A","1":"Series B"}]


뒤져보다 보니, array_unique로 중복값을 정리하면서 어떤 경우에는 숫자로 인덱싱된 array가 남지 않는 경우가 생긴다는 거였습니다. 즉 json_encode해주면 위의 경우처럼 숫자 인덱싱이 남아버리는 거지요. ㅡ.ㅡ

원인을 알고나니 방법은 의외로 간단히..

json_encode 해주기 전에 array_values로 numerically indexed array를 강제로 만들어주는 것으로 해결되었습니다.

array_values(array_unique($data))


php를 다시 한번 돌아보게 해주는 하루였습니다. ㅋㅋ

Posted by banasun :

[php] openweathermap.org의 API를 이용한 현재 기상정보 보여주기

2015. 1. 29. 15:43 from Dev/php

예전에 openweathermap.org에서 제공하는 기상 정보를 이용하는 방법에 대해서 간단하게 올렸었습니다. (링크)

무료로 이용할 수 있는 날씨 정보 API가 별로 없는데, 이곳 서비스는 안정적으로 잘 이용하고 있습니다.

오늘은 간단하게 객체화 시킨 소스를 보여드리겠습니다. 언제나 그렇듯이 잘못된 부분이나 더 개선할 부분이 있으면 알려주세요. ^^



class Weather {

	const API_URL_CURRENT = "http://api.openweathermap.org/data/2.5/weather?lat=37.56826&lon=126.977829&units=metric&APPID=<발급받은 아이디>";
	const API_URL_FORECAST = "http://api.openweathermap.org/data/2.5/forecast/daily?lat=37.56826&lon=126.977829&cnt=5&units=metric&APPID=<역시 발급받은 아이디>";

	public static function get_current_weather() {
		$c = curl_init(self::API_URL_CURRENT);
		$options = array(
			CURLOPT_HEADER => false,
			CURLOPT_RETURNTRANSFER => true
		);
		curl_setopt_array($c, $options);
		$data = curl_exec($c);
		curl_close($c);
		
		if (isset($data) && $data) {
			$data_obj = json_decode($data);
			$result = array(
				'current_temp' => $data_obj->main->temp,
				'temp_min' => $data_obj->main->temp_min,
				'temp_max' => $data_obj->main->temp_max,
				'desc' => $data_obj->weather[0]->main,
				'icon' => "http://openweathermap.org/img/w/{$data_obj->weather[0]->icon}.png",
				'status' => 'ok'
			);
			return $result;
		}
	}
	
	public static function get_weather_forecast() {
		$c = curl_init(self::API_URL_FORECAST);
		$options = array(
			CURLOPT_HEADER => false,
			CURLOPT_RETURNTRANSFER => true
		);
		curl_setopt_array($c, $options);
		$data = curl_exec($c);
		curl_close($c);
		
		return json_decode($data);
	}
}

$w = Weather::get_current_weather();
echo "現在 " . number_format($w['current_temp'], 1) . "℃";


php 파일을 만드신 다음에 원하는 곳에 include만 해주면 간단한 날씨 아이콘과 현재 기온이 그림처럼 출력됩니다.

위 예제는 서울을 기준으로 했으니 다른 도시라면 lat, lon을 바꾸어주셔야 합니다.


이미지 아이콘도 $w['icon']으로 이용하실 수 있습니다만, 이쁜 아이콘이 아니라 pass. ㅋㅋ



여기에 가시면 오픈소스 날씨 관련 아이콘이 있습니다

erikflowers/weather-icons



기상 예측에 대해서도 일단 정보를 가져오는 부분은 코딩을 해 놓았습니다. json 객체이니 보시고 입맛에 맞게 이용하시면 됩니다.

Posted by banasun :

[php] openweathermap.org의 API와 cUrl을 이용하여 기상정보 가져오기

2014. 11. 6. 15:47 from Dev/php

간단하게 기상정보를 표시해주어야 할 일이 있어서 검색을 해보았는데, yahoo나 기상청의 공개 api 등이 나오더군요.

기상청은 공개 API이긴 하지만 승인요청하고 며칠 기다려야 하고, 상업적 용도의 사이트에 이용이 가능한지도 애매하고, 주의사항에 있는 '서버 과부하시 이용이 제한될 수 있습니다'라는 문구를 보고는 솔직히 좀 불안하더군요. 군함도 486 컴퓨터로 돌리는 나란데.. 아무도 책임 안지는 공개 api의 서버는 어떠할지...

그래서 조금 더 찾아 보니 http://openweathermap.org/api 라는 공개 서비스가 있네요. 일단 key 발급 같은 것도 간단하고(email 등록하면 됨), 일정 용량 이상 넘어가지 않는다면 이용하는 데 문제는 없어 보입니다.


php의 cUrl을 이용해서 자료를 가져와 보겠습니다:

 
$w = curl_init('http://api.openweathermap.org/data/2.5/weather?q=Seoul');
$weather_options = array(
	CURLOPT_HEADER => false,
	CURLOPT_RETURNTRANSFER => true
	);
curl_setopt_array($w, $weather_options);
$a = curl_exec($w);
curl_close($w);

if (isset($a) && $a) {
	$weather = json_decode($a);
	
	$current_temp = $weather->main->temp - 273.15;
	$temp_min = $weather->main->temp_min - 273.15;
	$temp_max = $weather->main->temp_max - 273.15;
	$weather_main = $weather->weather[0]->main;
	$weather_icon = "http://openweathermap.org/img/w/{$weather->weather[0]->icon}.png";

	echo "
";
	echo "현재 기온 : " . $current_temp;
	echo "최저 기온 : " . $temp_min;
	echo "최고 기온 : " . $temp_max;
	echo "날씨 : " . $weather_main;
	echo "
"; } else { exit(0); }

json 타입과 xml 타입으로 받을 수 있고, 넘겨온 값을 처리할 때에는 하위 값이 object도 있고, array도 있으니 이용할 때 참고하시고요, 그리고 한참 헤맸던게, 온도가 화씨가 아니라 절대온도(K)입니다. 섭씨 온도로 변경하려면 273.15를 빼주어야 합니다.

그리고 해당 날씨의 아이콘도 같이 제공해줍니다. 18번째 라인이 아이콘을 가져오는 부분인데, 아이콘도 예뻤으면 좋았을텐데 하는 생각이 드는 군요. ^^

원래는 APPKEY를 같이 넘겨줘야 한다고 되어 있는데, 테스트 할 때에는 없이도 잘 수행이 됩니다. 그래도 정책이 APPKEY를 받도록 되어 있고, 발급도 간단하니 안정적으로 이용할 때에는 넣어주시면 될 것 같습니다.

위 코드는 테스트용이라.. 이용하시는 목적에 맞게 객체를 만드시든, 함수를 만드시든 해서 사용하세요. ^^

Posted by banasun :

[php] serialize() VS json_encode()

2014. 9. 30. 17:15 from Dev/php

예전에는 거의 serialize()를 많이 사용했던 것 같은데, 요새는 AJAX 가 대세고, 더구나 angularJS처럼 아예 javascript로 app을 만드는 때가 되다 보니 json_encode()를 실무에서도 많이 이용하게 됩니다. json_encode()로 포맷을 잡아 놓으면 데이터 송수신하면서 따로 작업을 할 필요가 없어지게 된 거지요.

퍼포먼스 측면에서도 외국에서 벤치마킹한 결과를 보면 serialize()보다 json_encode()가 1.5~2배 이상 더 빠른 것으로 알려져 있습니다. 

그럼에도 개인적으로 작업을 하다 보면, serialize()가 필요한 이유는 개인적으로 몇가지 있습니다 :

1. 자료를 복원할 때 정확하게 특정 class로 복원해야 하는 경우에는 serialize()가 아직도 더 편리합니다. 물론 단순 class나 array라면 캐스팅해버리면 되긴 하지만요.


2. 서버의 php 버전이 낮은 경우입니다. 사실 이 글을 포스팅하는 이유가 오늘 하루 종일 예전 DB의 레코드를 json_encode 해서 신규 서버 mysql에 넣었다가 다시 이용하는 작업을 하다 짜증하서 쓰게 되었는데요. 특히 PHP 5.2 이전 버전은 json과 관련된 함수들의 기능에 제한이 많습니다. 


3. 이건 별 실효성은 없는 한계이지만, json_decode() 실행시 nested 계단이 127개 이상이면 에러가 발생합니다. json을 이용하는 이유가 직관적이고 사람이 바로 알아보기 편하다는 이유도 있는데.. 127 계단을 만들지는 않겠지요? ㅋㅋ 아마 PHP 개발자들도 그렇게 생각하고 한계를 127개로 한 것 같습니다.


하여튼 대세는 json 이지만, 아직도 serialize()가 더 편한 점도 남아있습니다. 

Posted by banasun :

application/json 포맷으로 angularJS - php script 사이에 데이터 주고받기

2014. 9. 21. 02:22 from Dev/php

데이터를 post 방식으로 php server로 보낼 때, 각 요소들을 파싱해서 application/x-www-form-urlencoded 방식으로 보낼 수도 있고, 아니면 application/json 방식으로 보낼 수 있습니다.

angularJS에서는 아래와 같이 보냅니다 :


        $http({
            method: "post",
            url: apiUrl,
            data: JSON.stringify(data),
            headers: {'Content-Type': 'application/json'}
        }).success( function(rtnData){
           //
        });


그리고 서버의 php script에서는 간단하게 다음과 같이 받습니다:


$foo = file_get_contents("php://input");

var_dump(json_decode($foo, true));


Posted by banasun :

[tip] 빈 객체 만들기 stdClass()

2014. 9. 15. 16:58 from Dev/php

가끔 가다 깡통(?) 객체를 만들어야 할 필요가 생길 수 있습니다. 

그럴 때에는 다음과 같이 생성해 줍니다:


$myObj = new stdClass();


이 방식이 제일 깔끔한 방식이라고 보시면 됩니다. ^^

Posted by banasun :

[그누보드5] 주요 함수 정리...

2014. 8. 26. 16:04 from Dev/php

그누보드로 작업된 사이트를 컨버전해야 될 일이 생겼는데, 작업하다 보니 하도 헷갈려서 그때그때 정리를 해볼까 합니다. 물론 sir.co.kr에 가셔서 검색하면 더 잘 되어 있습니다. ㅋㅋ

 
  1.  cut_str : 글 제목, 본문 등의 문자열을 일정 길이 이상에서 가릴 때

    echo cut_str($list[$i][wr_content], 120, "...");
    
  2.  conv_content($content, $html) : $html값을 2로 넘겨주면 $content에서 개행문자를

    로 바꾸어주고, 1이면

    $list[$i][content] = conv_content($row[wr_content], 0, 'wr_content');
    



Posted by banasun :

[php] a href tag에서 url만 추출하고 <a> tag 제거

2014. 8. 11. 14:57 from Dev/php

며칠전에 포스팅한 글대로(정규식 Regular expression 이용한 url 추출) url을 처리하다 보니 기존의 컨텐츠에 <a href="..." ...> </a> 형식으로 들어간 링크와 충돌이 되기에 이번에는 <a> tag에서 url 부분만 추출하고 <a> tag를 날려 버리는 정규식이 필요하네요.

$content = preg_replace('#\S*#i', "\\1 ", $content);

이렇게 해주면 됩니다. ^^

Posted by banasun :